aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/base64.py
diff options
context:
space:
mode:
authorMatan Perelman <matan1008@gmail.com>2024-02-25 19:17:54 +0200
committerGitHub <noreply@github.com>2024-02-25 19:17:54 +0200
commitc40b5b97fdac5099f670589b42c9038d7b23f2e5 (patch)
treed9eaf0d9c846588b08cef6d7ade487dfcc73208e /Lib/base64.py
parent9402ea63f7897ecda7036f667949ad17f4208e5b (diff)
downloadcpython-c40b5b97fdac5099f670589b42c9038d7b23f2e5.tar.gz
cpython-c40b5b97fdac5099f670589b42c9038d7b23f2e5.zip
bpo-31116: Add Z85 variant to base64 (GH-30598)
Z85 specification: https://rfc.zeromq.org/spec/32/
Diffstat (limited to 'Lib/base64.py')
-rwxr-xr-xLib/base64.py29
1 files changed, 28 insertions, 1 deletions
diff --git a/Lib/base64.py b/Lib/base64.py
index e3e983b3064..25164d1a1df 100755
--- a/Lib/base64.py
+++ b/Lib/base64.py
@@ -18,7 +18,7 @@ __all__ = [
'b64encode', 'b64decode', 'b32encode', 'b32decode',
'b32hexencode', 'b32hexdecode', 'b16encode', 'b16decode',
# Base85 and Ascii85 encodings
- 'b85encode', 'b85decode', 'a85encode', 'a85decode',
+ 'b85encode', 'b85decode', 'a85encode', 'a85decode', 'z85encode', 'z85decode',
# Standard Base64 encoding
'standard_b64encode', 'standard_b64decode',
# Some common Base64 alternatives. As referenced by RFC 3458, see thread
@@ -497,6 +497,33 @@ def b85decode(b):
result = result[:-padding]
return result
+_z85alphabet = (b'0123456789abcdefghijklmnopqrstuvwxyz'
+ b'ABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#')
+# Translating b85 valid but z85 invalid chars to b'\x00' is required
+# to prevent them from being decoded as b85 valid chars.
+_z85_b85_decode_diff = b';_`|~'
+_z85_decode_translation = bytes.maketrans(
+ _z85alphabet + _z85_b85_decode_diff,
+ _b85alphabet + b'\x00' * len(_z85_b85_decode_diff)
+)
+_z85_encode_translation = bytes.maketrans(_b85alphabet, _z85alphabet)
+
+def z85encode(s):
+ """Encode bytes-like object b in z85 format and return a bytes object."""
+ return b85encode(s).translate(_z85_encode_translation)
+
+def z85decode(s):
+ """Decode the z85-encoded bytes-like object or ASCII string b
+
+ The result is returned as a bytes object.
+ """
+ s = _bytes_from_decode_data(s)
+ s = s.translate(_z85_decode_translation)
+ try:
+ return b85decode(s)
+ except ValueError as e:
+ raise ValueError(e.args[0].replace('base85', 'z85')) from None
+
# Legacy interface. This code could be cleaned up since I don't believe
# binascii has any line length limitations. It just doesn't seem worth it
# though. The files should be opened in binary mode.