A Base64 encoder and decoder (RFC 4648) written from scratch in pure Python, working directly on bits. The point is not to replace the standard library -- it is to have an implementation whose every step is visible and, more importantly, checked against independent references so that a claim that nothing verifies cannot quietly rot into a falsehood.
b64encode(data: bytes) -> bytes-- encodes bytes to standard Base64, three input bytes at a time, grouped into 6-bit units, with correct=padding.b64decode(data: bytes) -> bytes-- strict decoder: it rejects input whose length is not a multiple of 4, characters outside the alphabet, misplaced padding, and non-canonical (non-zero) padding bits.- Standard alphabet
A-Za-z0-9+/. - Optional URL-safe alphabet
A-Za-z0-9-_viaurlsafe=Trueon both functions. - Pure standard library. The implementation does not import Python's
base64module.
- No MIME / PEM style behaviour: it does not insert line breaks and does not wrap output at 64 or 76 columns by default (in fact it never wraps).
- It does not accept or ignore whitespace/newlines inside the encoded input; such input is rejected by the strict decoder.
- No lenient / "validate=False" mode: there is no option to silently skip invalid characters.
- Only Base64. No Base32, Base16/hex, or Base64 variants beyond standard and URL-safe.
- Not tuned for very large inputs or streaming; it operates on whole
bytesobjects in memory.
import base64_scratch
base64_scratch.b64encode(b"foobar") # b"Zm9vYmFy"
base64_scratch.b64decode(b"Zm9vYmFy") # b"foobar"
base64_scratch.b64encode(b"\xfb\xef", urlsafe=True) # URL-safe alphabetThese are verified by the test suite (RFCVectorTests):
| input | Base64 |
|---|---|
"" |
"" |
"f" |
Zg== |
"fo" |
Zm8= |
"foo" |
Zm9v |
"foob" |
Zm9vYg== |
"fooba" |
Zm9vYmE= |
"foobar" |
Zm9vYmFy |
Run the tests:
python3 -m unittest -v
The suite checks the from-scratch code against three independent references:
- RFC 4648 vectors -- hand-written ground truth for encode and decode.
- Fuzz vs. the
base64module -- 2000+ random byte inputs per test, assertingb64encode == base64.b64encode(andurlsafe_b64encode), plus ab64decode(b64encode(x)) == xroundtrip. - Interop vs.
/usr/bin/base64-- our encoding equals the system CLI's output, andbase64 -ddecodes our output byte-for-byte. This group is skipped automatically (skipUnless) if no systembase64is found.
The strict decoder is exercised with bad lengths, non-alphabet characters, misplaced padding, and non-canonical padding bits.
MIT -- see LICENSE.