14

一文读懂Base64编码

 4 years ago
source link: https://semlinker.com/master-base64/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

我们知道一个字节可表示的范围是 0 ~ 255(十六进制:0x00 ~ 0xFF), 其中 ASCII 值的范围为 0 ~ 127(十六进制:0x00 ~ 0x7F);而超过 ASCII 范围的 128~255(十六进制:0x80 ~ 0xFF)之间的值是不可见字符。

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语,而其扩展版本延伸美国标准信息交换码则可以部分支持其他西欧语言,并等同于国际标准 ISO/IEC 646。

在 ASCII 码中 0 - 31和 127 是控制字符,共 33 个。

QVV3yeu.png!web

其余 95 个,即 32 - 126 是可打印字符,包括数字、大小写字母、常用符号等。

ERrae2E.png!web

当不可见字符在网络上传输时,比如说从 A 计算机传到 B 计算机,往往要经过多个路由设备,由于不同的设备对字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这是不利于传输的。为了解决这个问题,我们可以先对数据进行编码,比如 base64 编码,变成可见字符,也就是 ASCII 码可表示的可见字符,从而确保数据可靠传输。Base64 的内容是有 0 ~ 9,a ~ z,A ~ Z,+,/ 组成,正好 64 个字符,这些字符是在 ASCII 可表示的范围内,属于 95 个可见字符的一部分。

二、什么是 base64

Base64是一种基于 64 个可打印字符来表示二进制数据的表示方法。由于 2⁶ = 64 ,所以每 6 个比特为一个单元,对应某个可打印字符。3 个字节有 24 个比特,对应于 4 个 base64 单元,即 3 个字节可由 4 个可打印字符来表示。相应的转换过程如下图所示:

uuINriy.png!web

Base64 常用于在处理文本数据的场合,表示、传输、存储一些二进制数据,包括 MIME 的电子邮件及 XML 的一些复杂数据。在 MIME 格式的电子邮件中,base64 可以用来将二进制的字节序列数据编码成 ASCII 字符序列构成的文本。使用时,在传输编码方式中指定 base64。使用的字符包括大小写拉丁字母各 26 个、数字 10 个、加号 + 和斜杠 /,共 64 个字符,等号 = 用来作为后缀用途。Base64 相应的索引表如下:

rIjqYvi.png!web

了解完上述的知识,我们以编码 Man 为例,来直观的感受一下编码过程。 Man 由 M、a 和 n 3 个字符组成,它们对应的 ASCII 码为 77、97 和 110。

yYnuIbY.jpg!web

接着我们以每 6 个比特为一个单元,进行 base64 编码操作,具体如下图所示:

q6zYVvi.jpg!web

由图可知, Man (3字节)编码的结果为 TWFu (4字节),很明显经过 base64 编码后体积会增加 1/3。 Man 这个字符串的长度刚好是 3,我们可以用 4 个 base64 单元来表示。但如果待编码的字符串长度不是 3 的整数倍时,应该如何处理呢?

如果要编码的字节数不能被 3 整除,最后会多出 1 个或 2 个字节,那么可以使用下面的方法进行处理:先使用 0 字节值在末尾补足,使其能够被 3 整除,然后再进行 base64 的编码。

以编码字符 A 为例,其所占的字节数为 1,不能被 3 整除,需要补 2 个字节,具体如下图所示:

NRnUf2e.jpg!web

由上图可知,字符 A 经过 base64 编码后的结果是 QQ== ,该结果后面的两个 = 代表补足的字节数。而最后个 1 个 base64 字节块有 4 位是 0 值。

接着我们来看另一个示例,假设需编码的字符串为 BC ,其所占字节数为 2,不能被 3 整除,需要补 1 个字节,具体如下图所示:

EzErMf7.jpg!web

由上图可知,字符串 BC 经过 base64 编码后的结果是 QkM= ,该结果后面的 1 个 = 代表补足的字节数。而最后个 1 个 base64 字节块有 2 位是 0 值。

三、base64 编码的应用

在 HTML 中嵌入 base64 编码的图片

在编写 HTML 网页时,对于一些简单图片,通常会选择将图片内容直接内嵌在网页中,从而减少不必要的网络请求,但是图片数据是二进制数据,该怎么嵌入呢?绝大多数现代浏览器都支持一种名为 Data URLs 的特性,允许使用 base64 对图片或其他文件的二进制数据进行编码,将其作为文本字符串嵌入网页中。

<img alt="logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...">

但需要注意的是:如果图片较大,图片的色彩层次比较丰富,则不适合使用这种方式,因为该图片经过 base64 编码后的字符串非常大,会明显增大 HTML 页面的大小,从而影响加载速度。除此之外,利用 HTML FileReader API,我们也可以方便的实现图片本地预览功能,具体代码如下:

<input type="file" accept="image/*" onchange="loadFile(event)">
<img id="output"/>
<script>
  const loadFile = function(event) {
    const reader = new FileReader();
    reader.onload = function(){
      const output = document.querySelector('output');
      output.src = reader.result;
    };
    reader.readAsDataURL(event.target.files[0]);
  };
</script>

在完成本地图片预览之后,可以直接把图片对应的 Data URLs 数据提交到服务器。针对这种情形,服务端需要做一些相关处理,才能正常保存上传的图片,这里以 Express 为例,具体处理代码如下:

const app = require('express')();

app.post('/upload', function(req, res){
    let imgData = req.body.imgData; // 获取POST请求中的base64图片数据
    let base64Data = imgData.replace(/^data:image\/\w+;base64,/, "");
    let dataBuffer = Buffer.from(base64Data, 'base64');
    fs.writeFile("image.png", dataBuffer, function(err) {
        if(err){
          res.send(err);
        }else{
          res.send("图片上传成功!");
        }
    });
});

MIME(多用途互联网邮件扩展)

在 MIME 协议之前,邮件的编码曾经有过 UUENCODE 等编码方式 ,但是由于 MIME 协议算法简单,并且易于扩展,现在已经成为邮件编码方式的主流,不仅是用来传输 8 位的字符,也可以用来传送二进制的文件,如邮件附件中的图像、音频等信息,而且扩展了很多基于 MIME 的应用。

四、如何进行 base64 编码和解码

在 JavaScript 中,有两个函数被分别用来处理解码和编码 base64 字符串:

  • btoa():该函数能够基于二进制数据 “字符串” 创建一个 base64 编码的 ASCII 字符串。
  • atob(): 该函数能够解码通过 base64 编码的字符串数据。

btoa 使用示例

const name = 'Semlinker';
const encodedName = btoa(name);
console.log(encodedName); // U2VtbGlua2Vy

atob 使用示例

const encodedName = 'U2VtbGlua2Vy';
const name = atob(encodedName);
console.log(name); // Semlinker

对于 atob 和 btoa 这两个方法来说,其中的 a 代表 ASCII,而 b 代表 Blob,即二进制。因此 atob 表示 ASCII 到二进制,对应的是解码操作。而 btoa 表示二进制到 ASCII,对应的是编码操作。在了解方法中 a 和 b 分别代表的意义之后,在以后的工作中,我们就不会用错了。

五、总结

Base64 是一种数据编码方式,目的是为了保障数据的安全传输。但标准的 base64 编码无需额外的信息,即可以进行解码,是完全可逆的。因此在涉及传输私密数据时,并不能直接使用 base64 编码,而是要使用专门的对称或非对称加密算法。

六、参考资源


Recommend

  • 108
    • opsdev.cn 6 years ago
    • Cache

    对称加密和Base64编码

    对称加密和Base64编码

  • 117

    * 本文作者:艾登——皮尔斯,本文属FreeBuf原创奖励计划,未经许可禁止转载 这篇文章鄙人我主要是教大家如何加密免杀国外NjRAT生成的客户端,以达到逃避360杀软检测目的,希望各位Freebuf小粉喜欢。此文章仅用于教育目的,切勿用...

  • 80

    一.概念简介Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2^6=64,所以每6个比特为一个单元,对应某个可打印字符。3个字节有24个比特,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。它可用来作为电子邮件的传输编码。在Base64中的...

  • 80
    • blog.51cto.com 5 years ago
    • Cache

    BASE64编码原理与Golang代码调用

    一.概念简介 Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2^6=64,所以每6个比特为一个单元,对应某个可打印字符。3个字节有24个比特,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。它可用来...

  • 42
    • www.jianshu.com 5 years ago
    • Cache

    了解Base64编码解码 - 简书

  • 55
    • 微信 mp.weixin.qq.com 5 years ago
    • Cache

    base64编码原理之示例分析编码的全过程

  • 75
    • 微信 mp.weixin.qq.com 5 years ago
    • Cache

    base64 编码原理之示例分析编码的全过程

    BASE64的理论知识 BASE64是由64个基本字符组成,那么是哪64个基本字符? 在全世界通用的可见字符(62+2)组成64个字符 a~z 26个 A~Z 26个 0~9 10个...

  • 24
    • www.pengrl.com 4 years ago
    • Cache

    聊聊base64编码

    二进制的数据,每个字符的取值范围都是 [0, 255] ,作为ascii码解析时,只有部分可打印。 比如,我用文本编辑器vim打开一张jpeg图片,会发现内容是乱码。以下是头两行数据: ÿØÿà^...

  • 11
    • 微信 mp.weixin.qq.com 3 years ago
    • Cache

    一文读懂base64

    一、为什么要使用 base64 我们知道一个字节可表示的范围是 0 ~ 255(十六进制:0x00 ~ 0xFF), 其中 ASCII 值的范围为 0 ~ 127(十六进制:0x00 ~ 0x7F);而超过 ASCII 范围的 128~255(十六进制:0x80 ~ 0xFF)之间...

  • 5

    先说一下,为什么写这篇文章? 最近在写一个Http协议栈当涉及CRLF控制字符写入时,发现自己对CRLF与\r\n的关系不太了解,因此决定详细学习一下;查阅资料的同时,又遇到

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK