虽然本篇文章的前缀是 加密算法,但是希望大家不要误解,Base64 并不是一种加密算法

可能有朋友在不了解 Base64 的情况下,将其误用于数据加密或数据校验。乍一看,Base64 编码过的字符串有一种被加密的感觉,但是该字符串会存在许多 Base64 的特征,例如字符串中会出现 +\ 两种字符,末尾通常会有一个到两个 =。只要发现了这些特征,那么这个字符串大概率就是一个经过 Base64 编码后的字符串,此时无需任何额外信息即可轻松解码得出原始文本。

Base64 由来

我们知道在计算机中任何数据都是按字节存储的,一个字可表示的范围是 0 ~ 255,其中 ascii 值的范围为 0 ~ 127,而超越 ascii 范围的 128 ~ 255 之间的值是不可见字符,同时 ascii 中也包含部分不可见字符。

当不可见字符在网络上传输的时候,往往要经过多个路由设备,由于不同的设备(特指老的路由设备)对字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这是不利于传输的。所以就先把数据做一个 base64 编码,统统变为可见字符,也就是 ascii 可表示的可见字符,确保数据可靠传输。

对于现在的路由设备,只要是文本字符都可以直接在网络上传输。但是对于二进制格式的数据(图片,音频,视频等),我们一般都要把这些二进制数据转为文本字符后进行网络传输。

Base64 简介

之所以称为 Base64,是因为其使用了 64 个字符来对任意数据进行编码,同理还有 Base32Base58用于产生 Bitcoin 的钱包地址)等编码。

一个标准的 Base64 使用的 64 个字符为:

A-Z
a-z
0-9
+, /

这 64 个字符是各种字符编码(例如 ASCII)基本字符集。

编码原理

使用 Base64 进行编码,大致可以分为 4 步:

  1. 将原始数据每三个字节作为一组,一共是 24 个 bit
  2. 将 24 个 bit 分为四组,每组 6 个 bit
  3. 在每组前面加两个 00,扩展成 32 个 bit,即四个字节
  4. 根据下标,得到扩展后每个字节的对应符号

因为,Base64 将三个字节转化成四个字节,因此 Base64 编码后的文本,会比原文本大出三分之一左右。

英文编码

  • 第一步,LoL 的 ASCII 值分别是 76、111、76,对应的二进制值是 01001100、01101111、01001100,将它们连成一个 24 位的二进制字符串 010011000110111101001100
  • 第二步,将这个 24 为的二进制字符串分成 4 组,每组 6 个二进制位:010011、000110、111101、001100
  • 第三步,在每组前面加两个 00,扩展成 32 个二进制位,即四个字节:00010011、00000110、00111101、00001100,它们的十进制分别是 19、6、61、12
  • 第四步,根据上表,得到每个值对应 Base64 编码,即 TG9M

中文编码

汉字 如果转化成 Base64 编码?

需要注意的是,汉字本身具有很多种编码,例如 gb2312utf-8gbk等,每一种编码的 Base64 对应值都不一样。下面的例子以 utf-8 为例:

首先, 的 utf-8 编码为 E6A38B,写成二进制就是三字节的 11100110 10100011 10001011。将这个二进制字符串按照上边的规则,转换成四组一共 32 位的二进制值 00111001 00101010 00001110 00001011,相应的十进制数为 57、42、14、11,它对应的 Base64 值就是 5qOL

补码

  • 两个字节

    例如英文字符 PY,我们仅能得到 2 个字节,也就是 16个二进制位。首先,按照上面的规则,转成三组,最后一组除了前面加两个 0 以外,后面也要加两个 0,这样就得到了一个三位的 Base64 编码,最后在结尾补上一个 =

  • 一个字节

    一个字节的情况:将这一个字节的 8 个二进制位,按照上面的规则转成两组,最后一组除了前面加两个 0 之外,后面再加 4 个 0。这样得到一个二位的 Base64 编码,再在末尾补上两个 =

解码

解码就是对编码的逆向操作,但是需要注意一点:对于最后的两个 = 字符,转换成两个 A 字符,再转成对应的两个 6 比特二进制值,接着转成原始字符之前,需要将最后的两个 6 比特二进制值丢弃,因为它们实际上不携带有效信息

特殊变种

标准的 Base64 并不适合直接放在 URL 里传输,因为 URL 编码器会把标准 Base64 中的 /+ 字符转变为 %XX 的形式,而这些 % 号在存入数据库中时还需要再进行转换,因为 ANSI SQL 中已将 % 号用作通配符

  • 用于URL的改进Base64

    它不在末尾填充 = 号,并将标准 Base64 中的 +/ 分别改成了 -_,这样就免去了在 URL 编解码和数据库存储时所要做的转换,避免了编码信息长度在此过程中的增加

  • 用于正则表达式的改进Base64

    +/ 改成了 !-,因为 +, * 在正则表达式中都有可能具有特殊含义

参考