Skip to content

Commit 7465338

Browse files
committed
fix(ciphers): operate on raw bytes in base85
1 parent fd67627 commit 7465338

1 file changed

Lines changed: 33 additions & 16 deletions

File tree

‎ciphers/base85.py‎

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66

77

88
def _base10_to_85(d: int) -> str:
9-
return "".join(chr(d % 85 + 33)) + _base10_to_85(d // 85) if d > 0 else ""
9+
res = []
10+
for _ in range(5):
11+
res.append(chr(d % 85 + 33))
12+
d //= 85
13+
return "".join(res)
1014

1115

1216
def _base85_to_10(digits: list) -> int:
@@ -21,13 +25,22 @@ def ascii85_encode(data: bytes) -> bytes:
2125
b'0etOA2#'
2226
>>> ascii85_encode(b"base 85")
2327
b'@UX=h+?24'
28+
>>> ascii85_encode("héllo".encode())
29+
b'BZ$fcCi9'
2430
"""
25-
binary_data = "".join(bin(ord(d))[2:].zfill(8) for d in data.decode("utf-8"))
26-
null_values = (32 * ((len(binary_data) // 32) + 1) - len(binary_data)) // 8
27-
binary_data = binary_data.ljust(32 * ((len(binary_data) // 32) + 1), "0")
28-
b85_chunks = [int(_s, 2) for _s in map("".join, zip(*[iter(binary_data)] * 32))]
31+
if not data:
32+
return b""
33+
binary_data = "".join(bin(byte)[2:].zfill(8) for byte in data)
34+
remainder = len(binary_data) % 32
35+
null_bits = (32 - remainder) % 32
36+
binary_data = binary_data + "0" * null_bits
37+
null_bytes = null_bits // 8
38+
39+
b85_chunks = [
40+
int(binary_data[i : i + 32], 2) for i in range(0, len(binary_data), 32)
41+
]
2942
result = "".join(_base10_to_85(chunk)[::-1] for chunk in b85_chunks)
30-
return bytes(result[:-null_values] if null_values % 4 != 0 else result, "utf-8")
43+
return bytes(result[:-null_bytes] if null_bytes > 0 else result, "utf-8")
3144

3245

3346
def ascii85_decode(data: bytes) -> bytes:
@@ -38,18 +51,22 @@ def ascii85_decode(data: bytes) -> bytes:
3851
b'12345'
3952
>>> ascii85_decode(b"@UX=h+?24")
4053
b'base 85'
54+
>>> ascii85_decode(b'BZ$fcCi9').decode()
55+
'héllo'
4156
"""
42-
null_values = 5 * ((len(data) // 5) + 1) - len(data)
43-
binary_data = data.decode("utf-8") + "u" * null_values
44-
b85_chunks = map("".join, zip(*[iter(binary_data)] * 5))
45-
b85_segments = [[ord(_s) - 33 for _s in chunk] for chunk in b85_chunks]
46-
results = [bin(_base85_to_10(chunk))[2::].zfill(32) for chunk in b85_segments]
47-
char_chunks = [
48-
[chr(int(_s, 2)) for _s in map("".join, zip(*[iter(r)] * 8))] for r in results
57+
if not data:
58+
return b""
59+
s = data.decode("ascii")
60+
null_values = (5 - (len(s) % 5)) % 5
61+
binary_data = s + "u" * null_values
62+
b85_chunks = [binary_data[i : i + 5] for i in range(0, len(binary_data), 5)]
63+
b85_segments = [[ord(c) - 33 for c in chunk] for chunk in b85_chunks]
64+
results = [bin(_base85_to_10(chunk))[2:].zfill(32) for chunk in b85_segments]
65+
byte_chunks = [
66+
[int(r[j : j + 8], 2) for j in range(0, 32, 8)] for r in results
4967
]
50-
result = "".join("".join(char) for char in char_chunks)
51-
offset = int(null_values % 5 == 0)
52-
return bytes(result[: offset - null_values], "utf-8")
68+
raw_bytes = bytes(b for chunk in byte_chunks for b in chunk)
69+
return raw_bytes[:-null_values] if null_values > 0 else raw_bytes
5370

5471

5572
if __name__ == "__main__":

0 commit comments

Comments
 (0)