RFC 3548
The Base16, Base32, and Base64 Data Encodings
The Base16, Base32, and Base64 Data Encodings π
Okay bestie, let's get into it. This one is by S. Josefsson, Ed. (the "Ed." means editor π ), it's dated July 2003, and it's filed under Category: Informational, so it's giving "here's some good info" and not "this is a binding standard" π¦. The title block doesn't have any Obsoletes or Updates line, so it doesn't claim to replace or amend anything else πΈ.
Status of this Memo π
This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited β¨.
Copyright Notice π
Copyright (C) The Internet Society (2003). All Rights Reserved.
Abstract π
So the big picture: this document describes the commonly used base 64, base 32, and base 16 encoding schemes π. It also talks about line-feeds in encoded data, padding in encoded data, non-alphabet characters in encoded data, and using different encoding alphabets. Very cute, very organized π§.
Table of Contents ποΈ
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Implementation discrepancies . . . . . . . . . . . . . . . . . 2
2.1. Line feeds in encoded data . . . . . . . . . . . . . . . 2
2.2. Padding of encoded data . . . . . . . . . . . . . . . . 3
2.3. Interpretation of non-alphabet characters in encoded
data . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.4. Choosing the alphabet . . . . . . . . . . . . . . . . . 3
3. Base 64 Encoding . . . . . . . . . . . . . . . . . . . . . . . 4
4. Base 64 Encoding with URL and Filename Safe Alphabet . . . . . 6
5. Base 32 Encoding . . . . . . . . . . . . . . . . . . . . . . . 6
6. Base 16 Encoding . . . . . . . . . . . . . . . . . . . . . . . 8
7. Illustrations and examples . . . . . . . . . . . . . . . . . . 9
8. Security Considerations . . . . . . . . . . . . . . . . . . . 10
9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 11
9.1. Normative References . . . . . . . . . . . . . . . . . . 11
9.2. Informative References . . . . . . . . . . . . . . . . . 11
10. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 11
11. Editor's Address . . . . . . . . . . . . . . . . . . . . . . . 12
12. Full Copyright Statement . . . . . . . . . . . . . . . . . . . 13
1. Introduction πΈ
Base encoding is how you store or transfer data in environments that, maybe for legacy reasons, are only comfy with US-ASCII [9] data. It's also useful in brand-new apps with no legacy baggage, because it means you can poke at the objects with a plain old text editor π.
Different applications have had different requirements over time, so they sometimes implemented base encodings in slightly different ways π. Protocol specs also tend to use base encodings in general, and "base64" in particular, without a precise description or reference. MIME [3] gets used as the go-to reference for base64 without anyone really thinking through the line-wrapping or non-alphabet character consequences. So the goal of this spec is to lock in a common alphabet and common encoding considerations π . Hopefully that cuts down on ambiguity in other documents and leads to better interoperability π«Ά.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [1] β¨.
2. Implementation discrepancies π
Here we talk through the discrepancies between base encoding implementations in the past, and where it makes sense, we set a specific recommended behavior going forward π.
2.1. Line feeds in encoded data
MIME [3] is often used as a reference for base 64 encoding. But here's the tea: MIME doesn't define "base 64" per se. It defines a "base 64 Content-Transfer-Encoding" for use within MIME π. So MIME enforces a limit on line length of base 64 encoded data of 76 characters. MIME inherits the encoding from PEM [2], calling it "virtually identical," but PEM uses a line length of 64 characters. Both the MIME and PEM limits come from limits within SMTP π¬.
Implementations MUST NOT not add line feeds to base encoded data unless the specification referring to this document explicitly directs base encoders to add line feeds after a specific number of characters π«.
2.2. Padding of encoded data
Sometimes the use of padding ("=") in base encoded data isn't required or used at all π€·ββοΈ. In the general case, though, when you can't make assumptions about the size of the transported data, padding is required to yield correct decoded data π .
Implementations MUST include appropriate pad characters at the end of encoded data unless the specification referring to this document explicitly states otherwise π«Ά.
2.3. Interpretation of non-alphabet characters in encoded data
Base encodings use a specific, reduced alphabet to encode binary data π€. Non-alphabet characters could show up in base encoded data, either from data corruption or by design. They can be exploited as a "covert channel," where non-protocol data gets smuggled through for nefarious purposes π. They might also be sent to exploit implementation errors that lead to, e.g., buffer overflow attacks π.
Implementations MUST reject the encoding if it contains characters outside the base alphabet when interpreting base encoded data, unless the specification referring to this document explicitly states otherwise. Such specifications may, as MIME does, instead state that characters outside the base encoding alphabet should simply be ignored when interpreting data ("be liberal in what you accept") π·. Note that this means any CRLF counts as a "non-alphabet character" and gets ignored π. Furthermore, such specifications may treat the pad character, "=", as not part of the base alphabet until the end of the string. If more than the allowed number of pad characters show up at the end of the string, e.g., a base 64 string ending in "===", the excess pad characters could be ignored π§.
Reject by default, unless the spec you're reading says otherwise. That's the vibe β οΈ.
2.4. Choosing the alphabet
Different applications have different requirements for the characters in the alphabet π. Here are a few requirements that decide which alphabet should be used:
- Handled by humans. Characters "0", "O" are easily swapped, and so are "1", "l" and "I". In the base32 alphabet below, where 0 (zero) and 1 (one) aren't present, a decoder may interpret 0 as O, and 1 as I or L depending on case. (However, by default it should not, see previous section.) π
- Encoded into structures that place other requirements. For base 16 and base 32, this decides whether you use upper- or lowercase alphabets. For base 64, non-alphanumeric characters (in particular "/") may be problematic in file names and URLs π.
- Used as identifiers. Certain characters, notably "+" and "/" in the base 64 alphabet, get treated as word-breaks by legacy text search/index tools π.
There is no universally accepted alphabet that fulfills all the requirements π©. In this document, we document and name some alphabets that are currently in use π¦.
3. Base 64 Encoding β¨
The following description of base 64 is due to [2], [3], [4] and [5] π.
Base 64 encoding is designed to represent arbitrary sequences of octets in a form that requires case sensitivity but doesn't need to be humanly readable π€.
A 65-character subset of US-ASCII is used, which lets you represent 6 bits per printable character. (The extra 65th character, "=", is used to signify a special processing function π§.)
The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Going left to right, a 24-bit input group is formed by concatenating 3 8-bit input groups. Those 24 bits then get treated as 4 concatenated 6-bit groups, and each one gets translated into a single digit in the base 64 alphabet π’.
Each 6-bit group is used as an index into an array of 64 printable characters. The character referenced by the index goes into the output string π.
Here's the full base 64 alphabet, for the table lovers out there:
Table 1: The Base 64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
Special processing kicks in if fewer than 24 bits are available at the end of the data being encoded πΈ. A full encoding quantum is always completed at the end of a quantity. When fewer than 24 input bits are available in an input group, zero bits get added (on the right) to form an integral number of 6-bit groups. Padding at the end of the data is done with the "=" character π«§. Since all base 64 input is an integral number of octets, only the following cases can happen:
- The final quantum of encoding input is an integral multiple of 24 bits. Here, the final unit of encoded output will be an integral multiple of 4 characters with no "=" padding π.
- The final quantum of encoding input is exactly 8 bits. Here, the final unit of encoded output will be two characters followed by two "=" padding characters π·.
- The final quantum of encoding input is exactly 16 bits. Here, the final unit of encoded output will be three characters followed by one "=" padding character π.
4. Base 64 Encoding with URL and Filename Safe Alphabet β¨
Okay so the URL and filename safe version of base 64 has already been used in [8] π¦
There's an alternative alphabet that someone suggested, and it uses "~" as the 63rd character π«Ά But "~" has special meaning in some file system environments π So the encoding in this section is the one that's recommended instead π
This encoding should not be treated as the same thing as "base64", and you should not call it just "base64" π Unless it's made clear otherwise, "base64" means the base 64 from the previous section π
Technically, this encoding is identical to the previous one, except for the 62nd and 63rd alphabet characters π You can see the difference in table 2 below β¨
Table 2: The "URL and Filename safe" Base 64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 - (minus)
12 M 29 d 46 u 63 _ (understrike)
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
5. Base 32 Encoding πΈ
The description of base 32 below comes from [7], with some corrections β¨
Base 32 is designed to represent arbitrary sequences of octets in a form that's case insensitive, but it doesn't need to be easy for humans to read π
It uses a 33-character subset of US-ASCII, so each printable character carries 5 bits π¦ (The extra 33rd character, "=", is there to signal a special processing function π)
The encoding process turns 40-bit groups of input bits into output strings of 8 encoded characters π You go from left to right and glue together 5 8-bit input groups to make one 40-bit input group π«Ά Those 40 bits then get treated as 8 5-bit groups, and each one gets translated into a single digit in the base 32 alphabet π₯ When you encode a bit stream in base 32, the stream has to be treated as most-significant-bit first π So the first bit is the high-order bit of the first 8-bit byte, the eighth bit is the low-order bit of that first byte, and so on π§
Each 5-bit group works as an index into an array of 32 printable characters π The character at that index goes into the output string β¨ These characters, listed in Table 2 below, are picked from US-ASCII digits and uppercase letters π
Table 3: The Base 32 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 9 J 18 S 27 3
1 B 10 K 19 T 28 4
2 C 11 L 20 U 29 5
3 D 12 M 21 V 30 6
4 E 13 N 22 W 31 7
5 F 14 O 23 X
6 G 15 P 24 Y (pad) =
7 H 16 Q 25 Z
8 I 17 R 26 2
Special processing kicks in when fewer than 40 bits are left at the end of the data being encoded π A full encoding quantum is always finished at the end of a body π
So if there are fewer than 40 input bits in an input group, zero bits get added on the right to make a whole number of 5-bit groups π Padding at the end is done with the "=" character π¦ Since all base 32 input is a whole number of octets, only these cases can happen:
- The final quantum of encoding input is an integral multiple of 40 bits. Here, the final unit of encoded output is an integral multiple of 8 characters with no "=" padding π
- The final quantum of encoding input is exactly 8 bits. Here, the final unit of encoded output is two characters followed by six "=" padding characters π
- The final quantum of encoding input is exactly 16 bits. Here, the final unit of encoded output is four characters followed by four "=" padding characters π
- The final quantum of encoding input is exactly 24 bits. Here, the final unit of encoded output is five characters followed by three "=" padding characters, or π§
- The final quantum of encoding input is exactly 32 bits. Here, the final unit of encoded output is seven characters followed by one "=" padding character π
6. Base 16 Encoding π₯
This description is original, but it's built the same way as the earlier ones π Basically, base 16 is the standard case insensitive hex encoding, and you can call it "base16" or "hex" π
It uses a 16-character subset of US-ASCII, so each printable character carries 4 bits πΈ
The encoding process turns 8-bit groups (octets) of input bits into output strings of 2 encoded characters β¨ You go from left to right and take an 8-bit input from the input data π¦ Those 8 bits are treated as 2 concatenated 4-bit groups, and each group gets translated into a single digit in the base 16 alphabet π
Each 4-bit group works as an index into an array of 16 printable characters π«Ά The character at that index goes into the output string π
Table 5: The Base 16 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 0 4 4 8 8 12 C
1 1 5 5 9 9 13 D
2 2 6 6 10 A 14 E
3 3 7 7 11 B 15 F
Unlike base 32 and base 64, base 16 doesn't need any special padding, because a full code word is always there π
7. Illustrations and examples π§
To translate between binary and a base encoding, you store the input in a structure and then pull out the output π¦ The base 64 case is shown in the figure below, borrowed from [4] β¨
+--first octet--+-second octet--+--third octet--+
|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
+-----------+---+-------+-------+---+-----------+
|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|
+--1.index--+--2.index--+--3.index--+--4.index--+
The base 32 case is shown in the figure below, borrowed from [6] πΈ Each character in a base-32 value represents 5 bits of the underlying octet sequence, one after another π So every group of 8 characters represents a sequence of 5 octets (40 bits) π
1 2 3
01234567 89012345 67890123 45678901 23456789
+--------+--------+--------+--------+--------+
|< 1 >< 2| >< 3 ><|.4 >< 5.|>< 6 ><.|7 >< 8 >|
+--------+--------+--------+--------+--------+
<===> 8th character
<====> 7th character
<===> 6th character
<====> 5th character
<====> 4th character
<===> 3rd character
<====> 2nd character
<===> 1st character
Here's a base 64 example from [4] π
Input data: 0x14fb9c03d97e
Hex: 1 4 f b 9 c | 0 3 d 9 7 e
8-bit: 00010100 11111011 10011100 | 00000011 11011001
11111110
6-bit: 000101 001111 101110 011100 | 000000 111101 100111
111110
Decimal: 5 15 46 28 0 61 37 62
Output: F P u c A 9 l +
Input data: 0x14fb9c03d9
Hex: 1 4 f b 9 c | 0 3 d 9
8-bit: 00010100 11111011 10011100 | 00000011 11011001
pad with 00
6-bit: 000101 001111 101110 011100 | 000000 111101 100100
Decimal: 5 15 46 28 0 61 36
pad with =
Output: F P u c A 9 k =
Input data: 0x14fb9c03
Hex: 1 4 f b 9 c | 0 3
8-bit: 00010100 11111011 10011100 | 00000011
pad with 0000
6-bit: 000101 001111 101110 011100 | 000000 110000
Decimal: 5 15 46 28 0 48
pad with = =
Output: F P u c A w = =
8. Security Considerations π₯
This part is serious, bestie ππ¨ Please read it properly!
When you implement base encoding and decoding, you have to be careful not to introduce buffer overflow vulnerabilities or other attacks on the implementation π A decoder should not break on invalid input, including, for example, embedded NUL characters (ASCII 0) π‘οΈ
If non-alphabet characters get ignored instead of causing the whole encoding to be rejected (which is the recommended behaviour), a covert channel that can be used to "leak" information becomes possible π΅οΈββοΈ The implications should be understood by applications that don't follow the recommended practice π Likewise, when the base 16 and base 32 alphabets are handled case insensitively, changing the case can be used to leak information π¬
Base encoding visually hides information that would otherwise be easy to recognise, such as passwords, but it does not provide any computational confidentiality π This has been known to cause security incidents. For example, a user might report details of a network protocol exchange (maybe to illustrate some other problem) and accidentally reveal the password, because she doesn't realise that base encoding doesn't protect the password π
9. References π
9.1. Normative References
[1] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
9.2. Informative References
[2] Linn, J., "Privacy Enhancement for Internet Electronic Mail: Part I: Message Encryption and Authentication Procedures", RFC 1421, February 1993.
[3] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
[4] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer, "OpenPGP Message Format", RFC 2440, November 1998.
[5] Eastlake, D., "Domain Name System Security Extensions", RFC 2535, March 1999.
[6] Klyne, G. and L. Masinter, "Identifying Composite Media Features", RFC 2938, September 2000.
[7] Myers, J., "SASL GSSAPI mechanisms", Work in Progress.
[8] Wilcox-O'Hearn, B., "Post to P2P-hackers mailing list", World Wide Web http://zgp.org/pipermail/p2p-hackers/2001-September/000315.html, September 2001.
[9] Cerf, V., "ASCII format for Network Interchange", RFC 20, October 1969.
10. Acknowledgements β¨
okay bestie, big thank-you moment π«Ά Tony Hansen, Gordon Mohr, John Myers, Chris Newman, and Andrew Sieber all gave comments and suggestions, and the doc is so much better for it π The text is also based on earlier RFCs that described specific ways of using base encodings, so shoutout to those authors too π And the author says thank you to RSA Laboratories for supporting the work that led to this doc π§ͺπ
11. Editor's Address π
Simon Josefsson EMail: simon@josefsson.org
12. Full Copyright Statement βοΈ
Copyright (C) The Internet Society (2003). All Rights Reserved. πΈ
okay so the rules for copying this doc are pretty chill but also very specific π€ You can copy it and share it with others, and you can make derivative works that comment on or explain it or help with implementing it. You can publish and distribute those too, in whole or in part, without any restriction of any kind π¦ The one catch is that the above copyright notice and this paragraph have to be included on all such copies and derivative works π
The doc itself, though, may not be modified in any way, like removing the copyright notice or the references to the Internet Society or other Internet organizations π ββοΈ The exceptions are if you need it to develop Internet standards, in which case you follow the copyright procedures defined in the Internet Standards process, or if you need to translate it into languages other than English π
The limited permissions above are perpetual and will not be revoked by the Internet Society or its successors or assignees βΎοΈβ¨
And the legal disclaimer, which is very serious but still needs to be said:
This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Acknowledgement π
Funding for the RFC Editor function is currently provided by the Internet Society. π
π¦ where this page comes from
- ietf: rfc3548 2003-07
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms