您的位置:

什么是base64?

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