22 January 2025 · 5 min read
Base64 is not encryption
What Base64 is for, what it costs, and why finding it in your codebase is sometimes a red flag.
Base64 turns arbitrary bytes into 64 printable ASCII characters. It exists because many systems — email headers, URLs, JSON strings, XML documents — were designed for text and mangle raw binary. It provides exactly no confidentiality.
How it works
Three bytes, twenty-four bits, are regrouped into four six-bit values, each mapped to one character of the alphabet. When the input length is not divisible by three, the output is padded with = signs. The transformation is entirely mechanical and completely reversible by anyone.
The cost
Four characters for every three bytes: about 33 per cent larger, before any protocol overhead. That matters for data URIs, where an inlined image bloats your HTML or CSS, cannot be cached separately, and cannot be fetched in parallel. Below a couple of kilobytes inlining can be a net win; above that it usually is not.
Encoding is not encryption, and it is not hashing. Encoding is reversible by design and has no key. Encryption is reversible with a key. Hashing is not reversible at all.
Where it belongs
- Binary attachments in email, which is where it originated
- Binary fields inside JSON or XML, neither of which can carry raw bytes
- Small inline images in CSS as data URIs
- HTTP Basic authentication — which is why Basic auth is only safe over TLS
- JWT segments, using the URL-safe variant so tokens survive being put in a URL
The URL-safe variant
Standard Base64 uses + and /, both of which have meaning in a URL. The URL-safe alphabet substitutes - and _ and usually drops the padding. Feeding one variant to a decoder expecting the other is a common source of "invalid base64" errors.
The red flag
Base64 in a codebase is worth a second look. Used as transport for binary data it is correct. Used to "protect" a password in a config file, a token in localStorage, or a value in a URL, it protects nothing — it just makes the value slightly less obvious to a human skimming the file, while remaining trivially readable to anyone who looks.
The same reasoning explains why malware analysis tools flag Base64 strings: obfuscation and encoding look identical from the outside. If your reason for encoding something is that you would rather people could not read it, you need encryption, not an encoding.
Tools mentioned