16
16
'encode' , 'decode' , 'encodebytes' , 'decodebytes' ,
17
17
# Generalized interface for other encodings
18
18
'b64encode' , 'b64decode' , 'b32encode' , 'b32decode' ,
19
- 'b16encode' , 'b16decode' ,
19
+ 'b32hexencode' , 'b32hexdecode' , ' b16encode' , 'b16decode' ,
20
20
# Base85 and Ascii85 encodings
21
21
'b85encode' , 'b85decode' , 'a85encode' , 'a85decode' ,
22
22
# Standard Base64 encoding
@@ -135,19 +135,40 @@ def urlsafe_b64decode(s):
135
135
136
136
137
137
# Base32 encoding/decoding must be done in Python
138
+ _B32_ENCODE_DOCSTRING = '''
139
+ Encode the bytes-like objects using {encoding} and return a bytes object.
140
+ '''
141
+ _B32_DECODE_DOCSTRING = '''
142
+ Decode the {encoding} encoded bytes-like object or ASCII string s.
143
+
144
+ Optional casefold is a flag specifying whether a lowercase alphabet is
145
+ acceptable as input. For security purposes, the default is False.
146
+ {extra_args}
147
+ The result is returned as a bytes object. A binascii.Error is raised if
148
+ the input is incorrectly padded or if there are non-alphabet
149
+ characters present in the input.
150
+ '''
151
+ _B32_DECODE_MAP01_DOCSTRING = '''
152
+ RFC 3548 allows for optional mapping of the digit 0 (zero) to the
153
+ letter O (oh), and for optional mapping of the digit 1 (one) to
154
+ either the letter I (eye) or letter L (el). The optional argument
155
+ map01 when not None, specifies which letter the digit 1 should be
156
+ mapped to (when map01 is not None, the digit 0 is always mapped to
157
+ the letter O). For security purposes the default is None, so that
158
+ 0 and 1 are not allowed in the input.
159
+ '''
138
160
_b32alphabet = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
139
- _b32tab2 = None
140
- _b32rev = None
161
+ _b32hexalphabet = b'0123456789ABCDEFGHIJKLMNOPQRSTUV'
162
+ _b32tab2 = {}
163
+ _b32rev = {}
141
164
142
- def b32encode (s ):
143
- """Encode the bytes-like object s using Base32 and return a bytes object.
144
- """
165
+ def _b32encode (alphabet , s ):
145
166
global _b32tab2
146
167
# Delay the initialization of the table to not waste memory
147
168
# if the function is never called
148
- if _b32tab2 is None :
149
- b32tab = [bytes ((i ,)) for i in _b32alphabet ]
150
- _b32tab2 = [a + b for a in b32tab for b in b32tab ]
169
+ if alphabet not in _b32tab2 :
170
+ b32tab = [bytes ((i ,)) for i in alphabet ]
171
+ _b32tab2 [ alphabet ] = [a + b for a in b32tab for b in b32tab ]
151
172
b32tab = None
152
173
153
174
if not isinstance (s , bytes_types ):
@@ -158,7 +179,7 @@ def b32encode(s):
158
179
s = s + b'\0 ' * (5 - leftover ) # Don't use += !
159
180
encoded = bytearray ()
160
181
from_bytes = int .from_bytes
161
- b32tab2 = _b32tab2
182
+ b32tab2 = _b32tab2 [ alphabet ]
162
183
for i in range (0 , len (s ), 5 ):
163
184
c = from_bytes (s [i : i + 5 ], 'big' )
164
185
encoded += (b32tab2 [c >> 30 ] + # bits 1 - 10
@@ -177,29 +198,12 @@ def b32encode(s):
177
198
encoded [- 1 :] = b'='
178
199
return bytes (encoded )
179
200
180
- def b32decode (s , casefold = False , map01 = None ):
181
- """Decode the Base32 encoded bytes-like object or ASCII string s.
182
-
183
- Optional casefold is a flag specifying whether a lowercase alphabet is
184
- acceptable as input. For security purposes, the default is False.
185
-
186
- RFC 3548 allows for optional mapping of the digit 0 (zero) to the
187
- letter O (oh), and for optional mapping of the digit 1 (one) to
188
- either the letter I (eye) or letter L (el). The optional argument
189
- map01 when not None, specifies which letter the digit 1 should be
190
- mapped to (when map01 is not None, the digit 0 is always mapped to
191
- the letter O). For security purposes the default is None, so that
192
- 0 and 1 are not allowed in the input.
193
-
194
- The result is returned as a bytes object. A binascii.Error is raised if
195
- the input is incorrectly padded or if there are non-alphabet
196
- characters present in the input.
197
- """
201
+ def _b32decode (alphabet , s , casefold = False , map01 = None ):
198
202
global _b32rev
199
203
# Delay the initialization of the table to not waste memory
200
204
# if the function is never called
201
- if _b32rev is None :
202
- _b32rev = {v : k for k , v in enumerate (_b32alphabet )}
205
+ if alphabet not in _b32rev :
206
+ _b32rev [ alphabet ] = {v : k for k , v in enumerate (alphabet )}
203
207
s = _bytes_from_decode_data (s )
204
208
if len (s ) % 8 :
205
209
raise binascii .Error ('Incorrect padding' )
@@ -220,7 +224,7 @@ def b32decode(s, casefold=False, map01=None):
220
224
padchars = l - len (s )
221
225
# Now decode the full quanta
222
226
decoded = bytearray ()
223
- b32rev = _b32rev
227
+ b32rev = _b32rev [ alphabet ]
224
228
for i in range (0 , len (s ), 8 ):
225
229
quanta = s [i : i + 8 ]
226
230
acc = 0
@@ -241,6 +245,26 @@ def b32decode(s, casefold=False, map01=None):
241
245
return bytes (decoded )
242
246
243
247
248
+ def b32encode (s ):
249
+ return _b32encode (_b32alphabet , s )
250
+ b32encode .__doc__ = _B32_ENCODE_DOCSTRING .format (encoding = 'base32' )
251
+
252
+ def b32decode (s , casefold = False , map01 = None ):
253
+ return _b32decode (_b32alphabet , s , casefold , map01 )
254
+ b32decode .__doc__ = _B32_DECODE_DOCSTRING .format (encoding = 'base32' ,
255
+ extra_args = _B32_DECODE_MAP01_DOCSTRING )
256
+
257
+ def b32hexencode (s ):
258
+ return _b32encode (_b32hexalphabet , s )
259
+ b32hexencode .__doc__ = _B32_ENCODE_DOCSTRING .format (encoding = 'base32hex' )
260
+
261
+ def b32hexdecode (s , casefold = False ):
262
+ # base32hex does not have the 01 mapping
263
+ return _b32decode (_b32hexalphabet , s , casefold )
264
+ b32hexdecode .__doc__ = _B32_DECODE_DOCSTRING .format (encoding = 'base32hex' ,
265
+ extra_args = '' )
266
+
267
+
244
268
# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns
245
269
# lowercase. The RFC also recommends against accepting input case
246
270
# insensitively.
0 commit comments