Base64

Table of Contents

1. Base64 简介

有时,二进制数据不方便传输,我们想把二进制数据编译为 ascii 字符。这时,可以采用 hex 编码,它会把 1 个字节编码为 2 个 hex 字符; Base64 是一种比 hex 更省空间的编码, 它会把 3 个字节编码为 4 个 Base64 字符。

foo    ----hex---->     666f6f            // 编码后增加一倍
foo    ---base64-->     Zm9v              // 编码后增加 1/3,空间效率更高

Base64 的字符集为:

     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

1.1. Base64 基本规则

编码表中有 64 个字符,由于 2^6 = 64,所以 6 个比特位可唯一表示编码表中的任意字符。 Base64 的基本规则就是:把数据按“每 6 比特位”分割,然后分别查找对应编码即可。 实例如下:

   The following example of Base64 data is from [5], with corrections.

      Input data:  0x14fb9c03d97e
      Hex:     1   4    f   b    9   c     | 0   3    d   9    7   e
      8-bit:   00010100 11111011 10011100  | 00000011 11011001 01111110
      6-bit:   000101 001111 101110 011100 | 000000 111101 100101 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      =    pad 规则:让输出长度是 4 的倍数

      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      =      =    pad 规则:让输出长度是 4 的倍数

参考:https://datatracker.ietf.org/doc/html/rfc4648

1.2. 关于 padding

padding 规则:让输出长度是 4 的倍数。 下面是 Base64 的其它一些实例:

BASE64("") = ""
BASE64("f") = "Zg=="
BASE64("fo") = "Zm8="
BASE64("foo") = "Zm9v"
BASE64("foob") = "Zm9vYg=="
BASE64("fooba") = "Zm9vYmE="
BASE64("foobar") = "Zm9vYmFy"

仔细观察编码规则,我们可以知道 最多 2 个连续 padding 字符, 也就是不可能出现 3 个或多于 3 个 padding 字符。

此外, padding 并不是必要的,没有 padding 也可以无歧义地进行解码。 既然 padding 可有可无,那为什么还要设计 padding 呢?这是 为了方便 Base64 字符串进行 concatenation 操作, 如:

I encodes to SQ (SQ== with padding)
AM encodes to QU0 (QU0= with padding)
TJM encodes to VEpN (VEpN with padding)

如果我们把没有 padding 的 Base64 字符进行 concatenation,得到 SQQU0VEPN。这时,我们没有办法解码出原信息了。而如果有 padding,则 concatenation 后得到 SQ==QU0=VEpN,这时我们可以解码出原信息。

参考:https://stackoverflow.com/questions/4080988/why-does-base64-encoding-require-padding-if-the-input-length-is-not-divisible-by

1.3. Base64 变种

Base64 有很多变种,如图 1 所示(摘自:https://en.wikipedia.org/wiki/Base64#Variants_summary_table )。

base64_variants.png

Figure 1: Base64 变种

Author: cig01

Created: <2017-09-15 Fri>

Last updated: <2022-01-29 Sat>

Creator: Emacs 27.1 (Org mode 9.4)