diff options
author | Matan Perelman <matan1008@gmail.com> | 2024-02-25 19:17:54 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-25 19:17:54 +0200 |
commit | c40b5b97fdac5099f670589b42c9038d7b23f2e5 (patch) | |
tree | d9eaf0d9c846588b08cef6d7ade487dfcc73208e /Lib/base64.py | |
parent | 9402ea63f7897ecda7036f667949ad17f4208e5b (diff) | |
download | cpython-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-x | Lib/base64.py | 29 |
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. |