From 53a51b3529ad5f985e6f65b5b3a4e155af1d2d63 Mon Sep 17 00:00:00 2001 From: Chris O <46587501+ChrisO345@users.noreply.github.com> Date: Sun, 24 Sep 2023 19:09:32 +1300 Subject: [PATCH] Rewrite of base32.py algorithm (#9068) * rewrite of base32.py * changed maps to list comprehension * Apply suggestions from code review Co-authored-by: Tianyi Zheng --------- Co-authored-by: Tianyi Zheng --- ciphers/base32.py | 51 +++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/ciphers/base32.py b/ciphers/base32.py index fee53ccaf..1924d1e18 100644 --- a/ciphers/base32.py +++ b/ciphers/base32.py @@ -1,42 +1,45 @@ -import base64 +""" +Base32 encoding and decoding + +https://en.wikipedia.org/wiki/Base32 +""" +B32_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" -def base32_encode(string: str) -> bytes: +def base32_encode(data: bytes) -> bytes: """ - Encodes a given string to base32, returning a bytes-like object - >>> base32_encode("Hello World!") + >>> base32_encode(b"Hello World!") b'JBSWY3DPEBLW64TMMQQQ====' - >>> base32_encode("123456") + >>> base32_encode(b"123456") b'GEZDGNBVGY======' - >>> base32_encode("some long complex string") + >>> base32_encode(b"some long complex string") b'ONXW2ZJANRXW4ZZAMNXW24DMMV4CA43UOJUW4ZY=' """ - - # encoded the input (we need a bytes like object) - # then, b32encoded the bytes-like object - return base64.b32encode(string.encode("utf-8")) + binary_data = "".join(bin(ord(d))[2:].zfill(8) for d in data.decode("utf-8")) + binary_data = binary_data.ljust(5 * ((len(binary_data) // 5) + 1), "0") + b32_chunks = map("".join, zip(*[iter(binary_data)] * 5)) + b32_result = "".join(B32_CHARSET[int(chunk, 2)] for chunk in b32_chunks) + return bytes(b32_result.ljust(8 * ((len(b32_result) // 8) + 1), "="), "utf-8") -def base32_decode(encoded_bytes: bytes) -> str: +def base32_decode(data: bytes) -> bytes: """ - Decodes a given bytes-like object to a string, returning a string >>> base32_decode(b'JBSWY3DPEBLW64TMMQQQ====') - 'Hello World!' + b'Hello World!' >>> base32_decode(b'GEZDGNBVGY======') - '123456' + b'123456' >>> base32_decode(b'ONXW2ZJANRXW4ZZAMNXW24DMMV4CA43UOJUW4ZY=') - 'some long complex string' + b'some long complex string' """ - - # decode the bytes from base32 - # then, decode the bytes-like object to return as a string - return base64.b32decode(encoded_bytes).decode("utf-8") + binary_chunks = "".join( + bin(B32_CHARSET.index(_d))[2:].zfill(5) + for _d in data.decode("utf-8").strip("=") + ) + binary_data = list(map("".join, zip(*[iter(binary_chunks)] * 8))) + return bytes("".join([chr(int(_d, 2)) for _d in binary_data]), "utf-8") if __name__ == "__main__": - test = "Hello World!" - encoded = base32_encode(test) - print(encoded) + import doctest - decoded = base32_decode(encoded) - print(decoded) + doctest.testmod()