As anyone who has been bitten by using base64
instead of base64url
is quite well aware, the "original" base64 alphabet uses alphanumeric, +
, =
(both perfectly cromulent URL characters), and the dreaded /
. I want to know how this came about, because it seems that using /
in an encoding alphabet is extremely short-sighted.
I have been able to track the origin of this through:
- RFC4648, which points to
- RFC3548, which points to
- RFC1421, at which point, the
base64
trail goes cold.
We can however look to RFC821/RFC822, the famous Simple Mail Transfer Protocol (SMTP). There is no mention of base64 encoding, or any binary-to-text encoding for that matter. I'm not even sure the idea of attaching/sending binary data via email existed at the time, and it wasn't until 1992 that the first MIME email attachment was sent.
I estimate, given the 1993 RFC, that the decision of what would go into the base64 encoding occurred sometime in the mid-80s. Borne shell and awk would have been a thing. ASCII and EBCDIC would be fairly established. I'm guessing it would have happened after uuencode was invented in 1980 (which includes _
), though it may have been made without knowledge of uuencode.
Regardless, all the folks working on this sort early tech of were surely familiar with UNIX to some degree, and the convention of using /
for path separation. Further, the use of the /
symbol as a separator of the form "something / something_else" goes way back, probably to the 18th century at least. I'm guessing this usage is probably what subconsciously influence the choice of /
as the UNIX path separator. Surely, one might consider the idea of base64blob1/base64blob2
. All this put together makes /
a really strange choice for the fledgling base64
encoding alphabet, even in a pre-URL age, especially since better alternatives like -
and _
are right there. Heck, even ,.@!$&%
are all better candidates than /
in my book. /
is literally the only character besides \0
disallowed in UNIX filenames.
I guess the motivation for this is, in my mind (as someone who started writing code in the 90s), there is a continuum of characters from "most word-like" to "most code/delimeter-like" (i.e. more like control characters than actual identifiers).
a-zA-Z
the exemplar of word-like0-9
still quite word-like, valid in identifiers_
basically the "I need a space but it needs to be an identifier"-
word-like in some contexts@#$%&+=
- vaguely word-like but also code-like!?:;.,
- definitely have that delimiter feel^*|
- more code-like than word-like""''<>[](){}
ok these are definitely delimiters/brackets\/
and backtick - unabashedly separators
I wasn't there, but a lot of these "tropes" originate in the 60's and 70's, so I would imagine 80's developers would have similar intuition. /
just "feels wrong".
So how did this come about?
Edit:
ARPA Text Internet Messages grammar gives special meaning to ()<>@,;:\.[]
, so it might make sense why those would be excluded, albeit they can be string-quoted. But that still leaves -_
, which is present in ASCII 1965 and EBCDIC. Is there some other early character encoding that lacks these that would sway the decision? Perhaps PETSCII?
Edit 2:
Let us assume that the character set needed to be common between ASCII63, EBDCIC invariant, and PETSCII. If we take the intersection of these, subtract the SMTP special characters and the obvious alphanumerics, that leaves the candidates =-%/?*&+
, of which we need 3. =+-
makes a ton of sense, has some nice symmetry to it. ?%&
also seem fairly reasonable (pre-URL). /
and *
feel like the least promising. Is there some other character set or protocol restriction out there which may have ruled out -?%&
, necessitating /
?
uuencode
seems to be from 1980. But it is not clear what is the problem. Maybe you could give an example of what it is you do not like. Evidently things work, to some extent at least.