chacha20算法

算法介绍

ChaCha20 是一个流加密算法,它通过一个伪随机数生成器(PRNG)产生一个密钥流,然后和明文进行异或(XOR)得到密文。
明文 ⊕ 密钥流 = 密文
密文 ⊕ 密钥流 = 明文
ChaCha20 的核心是一个 状态矩阵(4x4 共 16 个 32-bit 字),用以下数据初始化:

[ 常量 ][ 密钥 256-bit ][ 计数器 ][ Nonce ]
⚙️ 核心操作:Quarter Round
ChaCha 的核心计算是“Quarter Round”,它对 4 个 32-bit 的字进行一系列加法、异或、循环位移的混合操作:

a += b; d ^= a; d <<<= 16;
c += d; b ^= c; b <<<= 12;
a += b; d ^= a; d <<<= 8;
c += d; b ^= c; b <<<= 7;
这种设计既安全又高效,对现代 CPU 和嵌入式芯片都友好。

案例实战(天网)

上述是我简化的一部分的原网页是wasm的一部分节选
// 自定义 ChaCha20 加密实现 - 同步版本
function customChacha20Encrypt(key, nonce, data, prefixBytes, timestamp) {
// ChaCha20 常量 - “expand 32-byte k”
const constants = [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574];

// 准备输出缓冲区 (180字节)
const output = new Uint8Array(180);

// 初始化状态数组
const state = new Array(16).fill(0);

// 设置常量
state[0] = constants[0];
state[1] = constants[1];
state[2] = constants[2];
state[3] = constants[3];

// 设置密钥 (8个32位整数)
for (let i = 0; i < 8; i++) {
  state[4 + i] = (key[i*4] | (key[i*4+1] << 8) | (key[i*4+2] << 16) | (key[i*4+3] << 24)) >>> 0;
}

// 设置计数器为1
state[12] = 1;

// 设置nonce (3个32位整数)
state[13] = (nonce[0] | (nonce[1] << 8) | (nonce[2] << 16) | (nonce[3] << 24)) >>> 0;
state[14] = (nonce[4] | (nonce[5] << 8) | (nonce[6] << 16) | (nonce[7] << 24)) >>> 0;
state[15] = (nonce[8] | (nonce[9] << 8) | (nonce[10] << 16) | (nonce[11] << 24)) >>> 0;

// 执行 ChaCha20 核心算法
const { finalState, intermediateStates } = chacha20Rounds(state);

// 第一部分: 最终状态 (64字节)
for (let i = 0; i < 16; i++) {
  const value = finalState[i];
  output[i*4] = value & 0xFF;
  output[i*4+1] = (value >>> 8) & 0xFF;
  output[i*4+2] = (value >>> 16) & 0xFF;
  output[i*4+3] = (value >>> 24) & 0xFF;
}

// 第二部分: 状态与常量的混合 (64字节)
const specialMapping = [
  [3, 0], [0, 1], [1, 2], [2, 3],
  [7, 4], [4, 5], [5, 6], [6, 7],
  [11, 8], [8, 9], [9, 10], [10, 11],
  [15, 12], [12, 13], [13, 14], [14, 15]
];

for (let i = 0; i < specialMapping.length; i++) {
  const [srcIdx, constIdx] = specialMapping[i];
  const value = (finalState[srcIdx] + constants[constIdx % 4]) >>> 0;
  output[64 + i*4] = value & 0xFF;
  output[64 + i*4+1] = (value >>> 8) & 0xFF;
  output[64 + i*4+2] = (value >>> 16) & 0xFF;
  output[64 + i*4+3] = (value >>> 24) & 0xFF;
}

// 第三部分: 状态与中间轮值的异或 (52字节)
for (let i = 0; i < 13; i++) {
  const srcIdx = i % 16;
  const roundIdx = (i * 7) % 10; // 特殊的轮次索引计算
  const value = (finalState[srcIdx] ^ intermediateStates[roundIdx][srcIdx]) >>> 0;
  output[128 + i*4] = value & 0xFF;
  output[128 + i*4+1] = (value >>> 8) & 0xFF;
  output[128 + i*4+2] = (value >>> 16) & 0xFF;
  output[128 + i*4+3] = (value >>> 24) & 0xFF;
}

// 应用最终混合 - 使用时间戳和前缀生成特殊密钥
applyFinalMixing(output, data, prefixBytes, nonce, timestamp);

return output;

}

总结

-遇到我逻辑比较复杂的算法的时候怎么分析其算法呢,这个时候分析主要的算法痕迹就可以了
-如果算法的痕迹不是很好的跟出,我们可以的具体的分析它算法(借助AI分析可以简化其分析的流程)

感想

1.逆向的发展越来越虚拟化(wasm,jsvmp)
2.看来以后要抓紧时间去跟进