bpo-31116: Add Z85 variant to base64 (GH-30598)

Z85  specification: https://rfc.zeromq.org/spec/32/
This commit is contained in:
Matan Perelman 2024-02-25 19:17:54 +02:00 committed by GitHub
parent 9402ea63f7
commit c40b5b97fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 141 additions and 2 deletions

View file

@ -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.