v1.1.0 - Added validation and line formatting, fixed zero-length padding. Added tests.
This commit is contained in:
+33
-12
@@ -1,18 +1,16 @@
|
||||
"""URL-safe Base64 encoding without padding.
|
||||
|
||||
This format uses only characters that are safe for URLs, filenames etc.
|
||||
Refer to Python's urlsafe_b64encode and base64.urlsafe_b64decode for more details.
|
||||
"""Base64 encoding in urlsafe format without padding.
|
||||
|
||||
Fixes Python base64 module's faults:
|
||||
- Padding "==" is optional and not produced by b64url.enc
|
||||
- Base64 type is str (stdlib is retarded and uses bytes)
|
||||
- Otherwise identical to urlsafe_b64encode/urlsafe_b64decode
|
||||
- Padding "==" is optional and not produced by base64url.enc
|
||||
- Base64 type is str (stdlib uses bytes)
|
||||
- Doesn't silently ignore invalid characters and produce garbage
|
||||
"""
|
||||
|
||||
from base64 import urlsafe_b64decode as _decode
|
||||
# We cannot use urlsafe_b64decode which misses the validation argument
|
||||
from base64 import b64decode as _decode
|
||||
from base64 import urlsafe_b64encode as _encode
|
||||
|
||||
__all__ = ["enc", "dec"]
|
||||
__all__ = ["enc", "dec", "enc_lines", "dec_lines"]
|
||||
|
||||
|
||||
def enc(data: bytes) -> str:
|
||||
@@ -20,7 +18,30 @@ def enc(data: bytes) -> str:
|
||||
return _encode(data).decode("ascii").rstrip("=")
|
||||
|
||||
|
||||
def dec(s: str) -> bytes:
|
||||
"""Decode URL-safe Base64 into bytes. Padding optional."""
|
||||
def dec(s: str, *, validate=True) -> bytes:
|
||||
"""Decode standard or urlsafe Base64, with or without padding.
|
||||
|
||||
Validation raises binascii.Error (ValueError) on invalid characters.
|
||||
If False, any unrecognized characters are silently ignored.
|
||||
"""
|
||||
# Testing whether needs padding is slower, this is the fastest way and constant time.
|
||||
return _decode(s + "=" * (4 - (len(s) % 4)))
|
||||
return _decode(s + -len(s) % 4 * "=", altchars=b"-_", validate=validate)
|
||||
|
||||
|
||||
def enc_lines(data: bytes, length: int = 76, sep="\n") -> str:
|
||||
"""Base64 encode bytes to a URL-safe string split into lines.
|
||||
|
||||
Returns a string with newlines inserted after every `length` characters.
|
||||
The value should be a multiple of 4 for best compatibility with other systems.
|
||||
"""
|
||||
s = enc(data)
|
||||
return sep.join([s[i : i + length] for i in range(0, len(s), length)])
|
||||
|
||||
|
||||
def dec_lines(s: str) -> bytes:
|
||||
"""Decode standard or urlsafe Base64 from a multiline string.
|
||||
|
||||
All whitespace is ignored to allow formatted input.
|
||||
Raises binascii.Error (ValueError) on other invalid characters.
|
||||
"""
|
||||
return dec("".join(s.split()))
|
||||
|
||||
Reference in New Issue
Block a user