Skip to content

Commit fd67627

Browse files
committed
fix(ciphers): operate on raw bytes in base32
1 parent 6e03a48 commit fd67627

1 file changed

Lines changed: 23 additions & 10 deletions

File tree

‎ciphers/base32.py‎

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,48 @@
99

1010
def base32_encode(data: bytes) -> bytes:
1111
"""
12+
>>> base32_encode(b"")
13+
b''
1214
>>> base32_encode(b"Hello World!")
1315
b'JBSWY3DPEBLW64TMMQQQ===='
1416
>>> base32_encode(b"123456")
1517
b'GEZDGNBVGY======'
1618
>>> base32_encode(b"some long complex string")
1719
b'ONXW2ZJANRXW4ZZAMNXW24DMMV4CA43UOJUW4ZY='
20+
>>> base32_encode("héllo".encode())
21+
b'NDB2S3DMN4======'
1822
"""
19-
binary_data = "".join(bin(ord(d))[2:].zfill(8) for d in data.decode("utf-8"))
20-
binary_data = binary_data.ljust(5 * ((len(binary_data) // 5) + 1), "0")
21-
b32_chunks = map("".join, zip(*[iter(binary_data)] * 5))
23+
if not data:
24+
return b""
25+
binary_data = "".join(bin(byte)[2:].zfill(8) for byte in data)
26+
remainder = len(binary_data) % 5
27+
if remainder != 0:
28+
binary_data = binary_data + "0" * (5 - remainder)
29+
b32_chunks = [binary_data[i : i + 5] for i in range(0, len(binary_data), 5)]
2230
b32_result = "".join(B32_CHARSET[int(chunk, 2)] for chunk in b32_chunks)
23-
return bytes(b32_result.ljust(8 * ((len(b32_result) // 8) + 1), "="), "utf-8")
31+
pad_len = (8 - (len(b32_result) % 8)) % 8
32+
return (b32_result + "=" * pad_len).encode("ascii")
2433

2534

2635
def base32_decode(data: bytes) -> bytes:
2736
"""
37+
>>> base32_decode(b"")
38+
b''
2839
>>> base32_decode(b'JBSWY3DPEBLW64TMMQQQ====')
2940
b'Hello World!'
3041
>>> base32_decode(b'GEZDGNBVGY======')
3142
b'123456'
3243
>>> base32_decode(b'ONXW2ZJANRXW4ZZAMNXW24DMMV4CA43UOJUW4ZY=')
3344
b'some long complex string'
45+
>>> base32_decode(b'NDB2S3DMN4======').decode()
46+
'héllo'
3447
"""
35-
binary_chunks = "".join(
36-
bin(B32_CHARSET.index(_d))[2:].zfill(5)
37-
for _d in data.decode("utf-8").strip("=")
38-
)
39-
binary_data = list(map("".join, zip(*[iter(binary_chunks)] * 8)))
40-
return bytes("".join([chr(int(_d, 2)) for _d in binary_data]), "utf-8")
48+
if not data:
49+
return b""
50+
s = data.decode("ascii").strip("=")
51+
binary_chunks = "".join(bin(B32_CHARSET.index(c))[2:].zfill(5) for c in s)
52+
num_bytes = len(binary_chunks) // 8
53+
return bytes(int(binary_chunks[i : i + 8], 2) for i in range(0, num_bytes * 8, 8))
4154

4255

4356
if __name__ == "__main__":

0 commit comments

Comments
 (0)