文章目录
一、Base64编码的起源
Base64 编码并非一种加密算法,它的起源可追溯到电子邮件诞生初期。在当时,电子邮件只能传输 ASCII 字符,而二进制文件(像图片、音频等)无法直接传输。为解决该问题,Base64编码应运而生,它将二进制数据转换为一种由64个可打印字符组成的字符串表示,从而方便在文本环境中传输复杂的数据。
二、Base64的应用场景
- 电子邮件附件:早期的电子邮件系统通过Base64编码来传输二进制附件。
- JSON数据传输:在网络通信中,将二进制数据(如图片、文件)的Base64编码嵌入到JSON对象中,便于跨域传输。
- URL编码:Base64编码常用于对URL中的参数进行编码,以确保参数的合法性。
- 数据存储:在某些需要存储二进制数据的系统中,先将其转换为Base64编码的字符串,可以简化存储和管理。
- 加密与解密:虽然Base64本身不是加密算法,但它常被用于加密数据的传输或存储前的编码处理。
三、Base64的编码与解码过程
3.1 Base64编码过程
-
分组:把原始二进制数据按每 3 个字节(即 24 位)一组进行划分。
-
拆分:每组 24 位再拆分成 4 个 6 位的小组。
-
补位:每个 6 位小组前面补 2 个 0,使其变成 8 位。
-
映射:将每个 8 位小组的值映射到 Base64 字符集里对应的字符。
-
填充:若原始数据长度不是 3 的倍数,剩余部分用=填充。
3.2 Base64解码过程
-
去除填充:把 Base64 编码字符串末尾的=去除。
-
映射:将每个 Base64 字符映射回对应的 6 位二进制值。
-
合并:把这些 6 位二进制值合并成 24 位一组。
-
拆分:每组 24 位拆分成 3 个 8 位字节。
四、如何一眼看出Base64编码?
4.1 验证字符集
检查密文字符串是否仅包含,Base64编码使用的字符集(64个字符):
A-Z:24个大写字母
a-z:24个小写字母
0-9
+
/
=:用作填充字符
URL安全变种:在 URL 安全的 Base64 编码中,+和/分别被-和_替代,并且填充字符=会被省略。
4.2 长度判断
验证密文长度:是否为4的倍数(或补齐后为4的倍数)。
4.3 搜索特征码
-
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ -
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
4.4 使用工具验证
百度搜索Base64编码解码:通过解码工具或代码快速确认。
4.5 示例
下面是一些 Base64 编码字符串示例,你可以观察其特征:
SGVsbG8sIFdvcmxkIQ==:长度为 20(是 4 的倍数),由 Base64 字符集内的字符组成,末尾有两个填充字符 =。dGVzdA==:长度为 8(是 4 的倍数),由 Base64 字符集内的字符组成,末尾有两个填充字符 =。TWFu:长度为 4(是 4 的倍数),由 Base64 字符集内的字符组成,没有填充字符。
五、JavaScript实现Base64编码和解码
5.1 JavaScript原生实现Base64编码解码
编码函数 base64Encode
- 把输入字符串转换为 UTF - 8 字节数组。
- 每次处理 3 个字节的数据,将其组合成一个 24 位的组。
- 把 24 位的组拆分成 4 个 6 位的组,再将每个 6 位组映射到 Base64 字符集对应的字符。
- 若输入数据的长度并非 3 的倍数,使用 = 进行填充。
解码函数 base64Decode
- 构建一个 Base64 字符到索引的映射表。
- 去掉输入字符串末尾的填充字符 =。
- 每次处理 4 个 Base64 字符,将它们转换为一个 24 位的组。
- 把 24 位的组拆分成 3 个 8 位的字节。
- 依据是否有填充字符,决定是否添加相应的字节到输出字符串。
- 最后把输出字符串从 UTF - 8 字节数组转换回原始字符串。
function base64Encode(input) {
const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
let output = '';
let i = 0;
// 将输入字符串转换为 UTF-8 字节数组
const utf8Bytes = unescape(encodeURIComponent(input));
while (i < utf8Bytes.length) {
const byte1 = utf8Bytes.charCodeAt(i++);
const byte2 = i < utf8Bytes.length ? utf8Bytes.charCodeAt(i++) : NaN;
const byte3 = i < utf8Bytes.length ? utf8Bytes.charCodeAt(i++) : NaN;
const group = (byte1 << 16) | ((byte2 || 0) << 8) | (byte3 || 0);
const char1 = (group >> 18) & 63;
const char2 = (group >> 12) & 63;
const char3 = (group >> 6) & 63;
const char4 = group & 63;
output += base64Chars[char1];
output += base64Chars[char2];
output += isNaN(byte2) ? '=' : base64Chars[char3];
output += isNaN(byte3) ? '=' : base64Chars[char4];
}
return output;
}
function base64Decode(input) {
const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
const base64Map = {};
for (let i = 0; i < base64Chars.length; i++) {
base64Map[base64Chars[i]] = i;
}
input = input.replace(/=+$/, '');
let output = '';
let i = 0;
while (i < input.length) {
const char1 = base64Map[input[i++]];
const char2 = base64Map[input[i++]];
const char3 = base64Map[input[i++]];
const char4 = base64Map[input[i++]];
const group = (char1 << 18) | (char2 << 12) | ((char3 || 0) << 6) | (char4 || 0);
const byte1 = (group >> 16) & 255;
const byte2 = (group >> 8) & 255;
const byte3 = group & 255;
if (char3!== undefined) {
output += String.fromCharCode(byte1);
}
if (char4!== undefined) {
output += String.fromCharCode(byte2);
output += String.fromCharCode(byte3);
}
}
return decodeURIComponent(escape(output));
}
// 测试示例
const testString = 'Hello, World!';
const encoded = base64Encode(testString);
console.log('编码后:', encoded);
const decoded = base64Decode(encoded);
console.log('解码后:', decoded);
运行结果:
编码后: SGVsbG8sIFdvcmxkIQ==
解码后: Hello, World
特征码(重点):ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
5.2 内置API实现Base64编码解码
JavaScript提供了内置的btoa()和atob()函数,分别用于Base64编码和解码。
// 待编码的二进制数据(字符串形式)
const binaryData = "Hello, World!";
// 使用 btoa() 进行 Base64 编码
const encodedData = btoa(binaryData);
console.log("编码后:", encodedData);
// 使用 atob() 进行 Base64 解码
const decodedData = atob(encodedData);
console.log("解码后:", decodedData);
运行结果:
编码后: SGVsbG8sIFdvcmxkIQ==
解码后: Hello, World!
5.3 Buffer实现Base64编码解码
除了JavaScript内置的API外,许多第三方库也提供了Base64编码功能,如Node.js中内置的Buffer对象。
// Node.js 中使用 Buffer 对象进行 Base64 编码和解码
const binaryData = "Hello, World!";
// 编码
const buffer = Buffer.from(binaryData, 'utf8');
const encodedData = buffer.toString('base64');
console.log("编码后:", encodedData);
// 解码
const decodedBuffer = Buffer.from(encodedData, 'base64');
const decodedData = decodedBuffer.toString('utf8');
console.log("解码后:", decodedData);
运行结果:
编码后: SGVsbG8sIFdvcmxkIQ==
解码后: Hello, World!
5.4 CryptoJS实现Base64编码解码
// 引入 CryptoJS 库
const CryptoJS = require('crypto-js');
// 待编码的二进制数据(字符串形式)
const binaryData = "Hello, World!";
// 使用 CryptoJS 进行 Base64 编码
const wordArray = CryptoJS.enc.Utf8.parse(binaryData);
const encodedData = CryptoJS.enc.Base64.stringify(wordArray);
console.log("编码后:", encodedData);
// 使用 CryptoJS 进行 Base64 解码
const decodedWordArray = CryptoJS.enc.Base64.parse(encodedData);
const decodedData = decodedWordArray.toString(CryptoJS.enc.Utf8);
console.log("解码后:", decodedData);
运行结果:
编码后: SGVsbG8sIFdvcmxkIQ==
解码后: Hello, World!
5.5 Python实现Base64编码解码
Python中可以使用 base64 库对字符串进行 Base64 编码和解码:
import base64
# 待编码的二进制数据(字符串形式)
binary_data = "Hello, World!"
# 将字符串转换为字节类型
byte_data = binary_data.encode('utf-8')
# 使用 base64 进行编码
encoded_data = base64.b64encode(byte_data)
print("编码后:", encoded_data.decode('utf-8'))
# 使用 base64 进行解码
decoded_data = base64.b64decode(encoded_data)
print("解码后:", decoded_data.decode('utf-8'))
运行结果:
编码后: SGVsbG8sIFdvcmxkIQ==
解码后: Hello, World!
六、Base64小技巧扩展
个人经验总结:AES DES RSA加密最后都会调用一下Base64,那么在Base64(AES DES RSA)编码位置 或者 特征码位置 下断点,是不是就可以往前跟栈找到加密函数了???!!!
979

被折叠的 条评论
为什么被折叠?



