Base64是一种可以将任意二进制数据编码成可打印字符的编码方式。这种编码方式可在HTTP等系统下使用,并且在传输过程中能够保证数据的完整性。
一、base64的历史
在早期的电子邮件系统中,只支持ASCII字符集,无法传输二进制数据。因此,将二进制数据转换为ASCII字符集字符的编码方式成为了当时的需求。 Base64编码方式正是在这种背景下出现的。它最早在RFC 3548文档中被定义,然后在RFC 4648文档中被标准化,至今仍然被广泛使用。 Base64编码方式使用了64个可打印的ASCII字符来进行编码,使用一组固定的字符对每3个字节的数据进行编码,得到4个字符。这种编码方式不存在字节顺序问题,可以跨平台、跨语言地使用。
二、base64的编码方式
Base64编码方式使用了64个可打印的ASCII字符来进行编码,包括大写字母、小写字母、数字和+
、/
两个符号,共64个字符。编码的基本思路是将3个字节的数据编码成4个字符。如下图所示:
+--------+--------+--------+
|AAAAAABB|BBBBCCCC|CCDDDDDD|
+--------+--------+--------+
+--------+--------+--------+--------+
|ABCDEFGH|IJKLMNOP|QRSTUVWX|YZabcdef|
+--------+--------+--------+--------+
这里将每个6位二进制数作为一个索引,以此索引一个固定的64个字符的表格。这个表格是由可打印的ASCII字符构成的,因此可以在各种网络和电子邮件系统中传输。 每个字符使用8位二进制数表示,因此每3个字节的数据编码成4个字符后,总大小会增加1/3。例如,3字节的数据用Base64编码后,会变成4个字符的数据。
三、base64的应用场景
Base64编码方式虽然增加了数据传输的大小,但是可以在不改变数据内容的基础上,将二进制数据转换为可打印字符集,从而在邮件等协议中传输。在开发中,以下是几个常见的应用场景:
1. 在HTTP请求中传输二进制数据
在HTTP请求中,只支持文本格式,因此不能直接传输二进制数据。这时可以使用Base64编码方式将二进制数据转换为可打印的ASCII字符集,然后在HTTP请求中传输。
POST /api/upload HTTP/1.1
Content-Type: application/json
{
"data": "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="
}
2. 在数据存储中使用base64编码
在某些情况下,数据的存储格式要求使用文本格式。此时可以使用Base64编码方式进行编码,然后存储在数据库中。例如,将图片等二进制数据存储到数据库中。
CREATE TABLE user (
id INT PRIMARY KEY,
avatar TEXT
);
INSERT INTO user VALUES (1, 'data:image/jpeg;base64,/9j/4AAQSk...');
3. 数字签名
数字签名是指对数据进行加密处理,从而验证数据来源和完整性。来自于其他计算机或者网络的数据在收到之后,需要进行验证。数字签名通常将原始数据进行Hash计算得到信息摘要,然后使用Base64编码方式,对信息摘要进行编码并传输。接收方收到数据后,可以验证数据的完整性是否发生变化。
const crypto = require('crypto');
const data = 'Hello World!';
const secret = 'my_secret_key';
const sha1 = crypto.createHmac('sha1', secret).update(data).digest();
const signature = sha1.toString('base64');
// 发送数据
// http.post('/api/data', { data, signature });
四、base64的实现
在现代编程语言中,Base64编码方式通常都有相应的实现方式。以下是在JavaScript中进行Base64编码的实现过程:
// Base64编码表格
const BASE64_TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
// 对数据进行Base64编码
function base64Encode(data) {
let result = '';
let i = 0;
while (i < data.length) {
// 取3个字节
const byte1 = i < data.length ? data.charCodeAt(i++) : 0;
const byte2 = i < data.length ? data.charCodeAt(i++) : 0;
const byte3 = i < data.length ? data.charCodeAt(i++) : 0;
// 拼接24位二进制数
const code = (byte1 << 16) | (byte2 << 8) | byte3;
// 分割成4个6位二进制数
const char1 = code >> 18;
const char2 = (code >> 12) & 0x3f;
const char3 = (code >> 6) & 0x3f;
const char4 = code & 0x3f;
// 根据索引获取Base64字符
result += BASE64_TABLE.charAt(char1) + BASE64_TABLE.charAt(char2) + BASE64_TABLE.charAt(char3) + BASE64_TABLE.charAt(char4);
}
// 补齐
if (data.length % 3 === 1) {
result = result.slice(0, -2) + '==';
} else if (data.length % 3 === 2) {
result = result.slice(0, -1) + '=';
}
return result;
}
以上是在JavaScript中进行Base64编码的实现过程,其他语言的实现方式也大同小异。当然,大多数现代编程语言都已经内置了Base64的相关处理方法,可以直接调用。