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的相关处理方法,可以直接调用。