@@ -138,21 +138,10 @@ def urlsafe_b64decode(s):
138138
139139
140140# Base32 encoding/decoding must be done in Python
141- _b32alphabet = {
142- 0 : b'A' , 9 : b'J' , 18 : b'S' , 27 : b'3' ,
143- 1 : b'B' , 10 : b'K' , 19 : b'T' , 28 : b'4' ,
144- 2 : b'C' , 11 : b'L' , 20 : b'U' , 29 : b'5' ,
145- 3 : b'D' , 12 : b'M' , 21 : b'V' , 30 : b'6' ,
146- 4 : b'E' , 13 : b'N' , 22 : b'W' , 31 : b'7' ,
147- 5 : b'F' , 14 : b'O' , 23 : b'X' ,
148- 6 : b'G' , 15 : b'P' , 24 : b'Y' ,
149- 7 : b'H' , 16 : b'Q' , 25 : b'Z' ,
150- 8 : b'I' , 17 : b'R' , 26 : b'2' ,
151- }
152-
153- _b32tab = [v [0 ] for k , v in sorted (_b32alphabet .items ())]
154- _b32rev = dict ([(v [0 ], k ) for k , v in _b32alphabet .items ()])
155-
141+ _b32alphabet = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
142+ _b32tab = [bytes ([i ]) for i in _b32alphabet ]
143+ _b32tab2 = [a + b for a in _b32tab for b in _b32tab ]
144+ _b32rev = {v : k for k , v in enumerate (_b32alphabet )}
156145
157146def b32encode (s ):
158147 """Encode a byte string using Base32.
@@ -161,41 +150,30 @@ def b32encode(s):
161150 """
162151 if not isinstance (s , bytes_types ):
163152 raise TypeError ("expected bytes, not %s" % s .__class__ .__name__ )
164- quanta , leftover = divmod ( len (s ), 5 )
153+ leftover = len (s ) % 5
165154 # Pad the last quantum with zero bits if necessary
166155 if leftover :
167156 s = s + bytes (5 - leftover ) # Don't use += !
168- quanta += 1
169- encoded = bytes ()
170- for i in range (quanta ):
171- # c1 and c2 are 16 bits wide, c3 is 8 bits wide. The intent of this
172- # code is to process the 40 bits in units of 5 bits. So we take the 1
173- # leftover bit of c1 and tack it onto c2. Then we take the 2 leftover
174- # bits of c2 and tack them onto c3. The shifts and masks are intended
175- # to give us values of exactly 5 bits in width.
176- c1 , c2 , c3 = struct .unpack ('!HHB' , s [i * 5 :(i + 1 )* 5 ])
177- c2 += (c1 & 1 ) << 16 # 17 bits wide
178- c3 += (c2 & 3 ) << 8 # 10 bits wide
179- encoded += bytes ([_b32tab [c1 >> 11 ], # bits 1 - 5
180- _b32tab [(c1 >> 6 ) & 0x1f ], # bits 6 - 10
181- _b32tab [(c1 >> 1 ) & 0x1f ], # bits 11 - 15
182- _b32tab [c2 >> 12 ], # bits 16 - 20 (1 - 5)
183- _b32tab [(c2 >> 7 ) & 0x1f ], # bits 21 - 25 (6 - 10)
184- _b32tab [(c2 >> 2 ) & 0x1f ], # bits 26 - 30 (11 - 15)
185- _b32tab [c3 >> 5 ], # bits 31 - 35 (1 - 5)
186- _b32tab [c3 & 0x1f ], # bits 36 - 40 (1 - 5)
187- ])
157+ encoded = bytearray ()
158+ from_bytes = int .from_bytes
159+ b32tab2 = _b32tab2
160+ for i in range (0 , len (s ), 5 ):
161+ c = from_bytes (s [i : i + 5 ], 'big' )
162+ encoded += (b32tab2 [c >> 30 ] + # bits 1 - 10
163+ b32tab2 [(c >> 20 ) & 0x3ff ] + # bits 11 - 20
164+ b32tab2 [(c >> 10 ) & 0x3ff ] + # bits 21 - 30
165+ b32tab2 [c & 0x3ff ] # bits 31 - 40
166+ )
188167 # Adjust for any leftover partial quanta
189168 if leftover == 1 :
190- return encoded [: - 6 ] + b'======'
169+ encoded [- 6 :] = b'======'
191170 elif leftover == 2 :
192- return encoded [: - 4 ] + b'===='
171+ encoded [- 4 :] = b'===='
193172 elif leftover == 3 :
194- return encoded [: - 3 ] + b'==='
173+ encoded [- 3 :] = b'==='
195174 elif leftover == 4 :
196- return encoded [:- 1 ] + b'='
197- return encoded
198-
175+ encoded [- 1 :] = b'='
176+ return bytes (encoded )
199177
200178def b32decode (s , casefold = False , map01 = None ):
201179 """Decode a Base32 encoded byte string.
@@ -217,8 +195,7 @@ def b32decode(s, casefold=False, map01=None):
217195 characters present in the input.
218196 """
219197 s = _bytes_from_decode_data (s )
220- quanta , leftover = divmod (len (s ), 8 )
221- if leftover :
198+ if len (s ) % 8 :
222199 raise binascii .Error ('Incorrect padding' )
223200 # Handle section 2.4 zero and one mapping. The flag map01 will be either
224201 # False, or the character to map the digit 1 (one) to. It should be
@@ -232,42 +209,36 @@ def b32decode(s, casefold=False, map01=None):
232209 # Strip off pad characters from the right. We need to count the pad
233210 # characters because this will tell us how many null bytes to remove from
234211 # the end of the decoded string.
235- padchars = 0
236- mo = re .search (b'(?P<pad>[=]*)$' , s )
237- if mo :
238- padchars = len (mo .group ('pad' ))
239- if padchars > 0 :
240- s = s [:- padchars ]
212+ l = len (s )
213+ s = s .rstrip (b'=' )
214+ padchars = l - len (s )
241215 # Now decode the full quanta
242- parts = []
243- acc = 0
244- shift = 35
245- for c in s :
246- val = _b32rev .get (c )
247- if val is None :
216+ decoded = bytearray ()
217+ b32rev = _b32rev
218+ for i in range (0 , len (s ), 8 ):
219+ quanta = s [i : i + 8 ]
220+ acc = 0
221+ try :
222+ for c in quanta :
223+ acc = (acc << 5 ) + b32rev [c ]
224+ except KeyError :
248225 raise TypeError ('Non-base32 digit found' )
249- acc += _b32rev [c ] << shift
250- shift -= 5
251- if shift < 0 :
252- parts .append (binascii .unhexlify (bytes ('%010x' % acc , "ascii" )))
253- acc = 0
254- shift = 35
226+ decoded += acc .to_bytes (5 , 'big' )
255227 # Process the last, partial quanta
256- last = binascii .unhexlify (bytes ('%010x' % acc , "ascii" ))
257- if padchars == 0 :
258- last = b'' # No characters
259- elif padchars == 1 :
260- last = last [:- 1 ]
261- elif padchars == 3 :
262- last = last [:- 2 ]
263- elif padchars == 4 :
264- last = last [:- 3 ]
265- elif padchars == 6 :
266- last = last [:- 4 ]
267- else :
268- raise binascii .Error ('Incorrect padding' )
269- parts .append (last )
270- return b'' .join (parts )
228+ if padchars :
229+ acc <<= 5 * padchars
230+ last = acc .to_bytes (5 , 'big' )
231+ if padchars == 1 :
232+ decoded [- 5 :] = last [:- 1 ]
233+ elif padchars == 3 :
234+ decoded [- 5 :] = last [:- 2 ]
235+ elif padchars == 4 :
236+ decoded [- 5 :] = last [:- 3 ]
237+ elif padchars == 6 :
238+ decoded [- 5 :] = last [:- 4 ]
239+ else :
240+ raise binascii .Error ('Incorrect padding' )
241+ return bytes (decoded )
271242
272243
273244
0 commit comments