CryptoJS源码与实现原理分析
核心架构
1. 基础数据结构
javascript
// WordArray是CryptoJS的核心数据结构
const WordArray = C_lib.WordArray = Base.extend({
init: function (words, sigBytes) {
// words是32位字的数组
words = this.words = words || [];
// sigBytes表示有效字节数
this.sigBytes = sigBytes != undefined ? sigBytes : words.length * 4;
},
// 转换为字符串
toString: function (encoder) {
return (encoder || Hex).stringify(this);
}
});
2. 类继承体系
javascript
// Base对象提供继承机制
var Base = C_lib.Base = (function () {
return {
// 创建新对象
extend: function (overrides) {
// 原型继承
var subtype = create(this);
// 复制属性
if (overrides) {
subtype.mixIn(overrides);
}
return subtype;
},
// 创建实例
create: function () {
var instance = this.extend();
instance.init.apply(instance, arguments);
return instance;
}
};
}());
AES算法实现流程
1. 密钥扩展
javascript
// 密钥扩展过程
_doReset: function () {
// 1. 获取原始密钥
var key = this._key;
var keyWords = key.words;
// 2. 计算轮密钥
var ksRows = this._keySchedule = [];
for (var ksRow = 0; ksRow < nRounds + 1; ksRow++) {
// 使用Rijndael密钥扩展算法
if (ksRow < keySize) {
ksRows[ksRow] = keyWords[ksRow];
} else {
t = ksRows[ksRow - 1];
if (!(ksRow % keySize)) {
// 密钥置换
t = (t << 8) | (t >>> 24);
t = (SBOX[t >>> 24] << 24) |
(SBOX[(t >>> 16) & 0xff] << 16) |
(SBOX[(t >>> 8) & 0xff] << 8) |
SBOX[t & 0xff];
t ^= RCON[(ksRow / keySize) | 0] << 24;
}
ksRows[ksRow] = ksRows[ksRow - keySize] ^ t;
}
}
}
2. 加密主要步骤
javascript
// 加密一个数据块
encryptBlock: function (M, offset) {
// 1. 初始轮密钥加
this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0,
SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
},
_doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0,
SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
// 2. 字节替换(SubBytes)
// 使用S-box进行非线性变换
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++) {
state[row][col] = SBOX[state[row][col]];
}
}
// 3. 行移位(ShiftRows)
// 循环左移不同的位数
for (var row = 1; row < 4; row++) {
state[row] = circularLeftShift(state[row], row);
}
// 4. 列混合(MixColumns)
// GF(2^8)上的矩阵乘法
for (var col = 0; col < 4; col++) {
mixColumn(state, col);
}
// 5. 轮密钥加(AddRoundKey)
// 与轮密钥异或
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++) {
state[row][col] ^= roundKey[row][col];
}
}
}
工作模式实现
1. CBC模式
javascript
// CBC模式实现
CBC: BlockCipherMode.extend({
// 加密
encryptBlock: function (words, offset) {
// 1. 获取IV或上一个密文块
var iv = this._iv;
// 2. 明文块与IV异或
for (var i = 0; i < blockSize; i++) {
words[offset + i] ^= iv[i];
}
// 3. 加密
this._cipher.encryptBlock(words, offset);
// 4. 更新IV
this._iv = words.slice(offset, offset + blockSize);
}
})
2. ECB模式
javascript
// ECB模式实现
ECB: BlockCipherMode.extend({
// 加密
encryptBlock: function (words, offset) {
this._cipher.encryptBlock(words, offset);
}
})
填充机制
PKCS7填充
javascript
// PKCS7填充实现
pad: function (data, blockSize) {
// 1. 计算需要填充的字节数
var paddingSize = blockSize - (data.sigBytes % blockSize);
// 2. 创建填充数组
var paddingWords = [];
for (var i = 0; i < paddingSize; i++) {
paddingWords.push(paddingSize);
}
// 3. 连接数据
return data.concat(WordArray.create(paddingWords));
}
性能优化原理
1. 查表优化
javascript
// 预计算的S-box表
var SBOX = [];
var INV_SBOX = [];
var SUB_MIX_0 = [];
var SUB_MIX_1 = [];
var SUB_MIX_2 = [];
var SUB_MIX_3 = [];
// 初始化查找表
(function () {
// 生成S-box和逆S-box
var d = [];
for (var i = 0; i < 256; i++) {
var q = ((i & 0x80) ? 0x1b : 0) ^ (i << 1);
d[i] = q;
SBOX[i] = // 计算S-box值
INV_SBOX[SBOX[i]] = i;
}
// 生成混合列查找表
for (var i = 0; i < 256; i++) {
SUB_MIX_0[i] = (d[i] << 24) | (i << 16) | (i << 8) | d[i];
SUB_MIX_1[i] = (i << 24) | (d[i] << 16) | (i << 8) | i;
SUB_MIX_2[i] = (i << 24) | (i << 16) | (d[i] << 8) | i;
SUB_MIX_3[i] = (i << 24) | (i << 16) | (i << 8) | d[i];
}
}());
2. 位运算优化
javascript
// 使用位运算代替乘法
function mixColumn(state, col) {
var s0 = state[0][col];
var s1 = state[1][col];
var s2 = state[2][col];
var s3 = state[3][col];
// 使用查表和异或运算代替GF(2^8)乘法
state[0][col] = SUB_MIX_0[s0 >>> 24] ^
SUB_MIX_1[(s1 >>> 16) & 0xff] ^
SUB_MIX_2[(s2 >>> 8) & 0xff] ^
SUB_MIX_3[s3 & 0xff];
}
面试重点
WordArray设计思想
- 为什么使用32位字数组
- sigBytes的作用
- 与TypedArray的区别
AES核心步骤
- 密钥扩展原理
- 四个变换的数学原理
- 为什么是这些特定操作
性能优化技巧
- 查表优化的原理
- 位运算的应用s
- 内存管理策略
安全性保证
- 各个工作模式的安全特性
- 填充oracle攻击的防范
- 密钥管理的最佳实践