UNPKG

mima-kit

Version:

mima-kit is a cryptographic suite implemented in TypeScript. The goal is to provide an easy-to-use cryptographic library. mima-kit 是一个使用 TypeScript 实现的密码学套件。目标是提供一个简单易用的密码学库。

107 lines (106 loc) 3.75 kB
import { createHash } from '../core/hash'; import { U8, rotateL32 } from '../core/utils'; // * Function const FF = (X, Y, Z, j) => j < 16 ? X ^ Y ^ Z : (X & Y) | (X & Z) | (Y & Z); const GG = (X, Y, Z, j) => j < 16 ? X ^ Y ^ Z : (X & Y) | (~X & Z); const P0 = (X) => X ^ rotateL32(X, 9) ^ rotateL32(X, 17); const P1 = (X) => X ^ rotateL32(X, 15) ^ rotateL32(X, 23); // * Algorithm function digest(message) { // * 初始化 const state = new U8(32); const state_view = state.view(4); state_view.set(0, 0x7380166fn); state_view.set(1, 0x4914b2b9n); state_view.set(2, 0x172442d7n); state_view.set(3, 0xda8a0600n); state_view.set(4, 0xa96f30bcn); state_view.set(5, 0x163138aan); state_view.set(6, 0xe38dee4dn); state_view.set(7, 0xb0fb0e4en); const m_byte = message.length; const m_bit = BigInt(m_byte) << 3n; const block_size = 64; // ceil((M_BYTE + 9) / 64) const block_total = (m_byte + 9 + 63) >> 6; // * 填充 const p = new U8(block_total * block_size); p.set(message); // appending the bit '1' to the message p[m_byte] = 0x80; // appending length const p_view = new DataView(p.buffer); p_view.setBigUint64(p.length - 8, m_bit, false); // * 迭代压缩 for (let offset = 0; offset < p.length; offset += block_size) { /** B(n) = p[offset:offset + block_size] */ // 准备状态字 const H0 = Number(state_view.get(0)); const H1 = Number(state_view.get(1)); const H2 = Number(state_view.get(2)); const H3 = Number(state_view.get(3)); const H4 = Number(state_view.get(4)); const H5 = Number(state_view.get(5)); const H6 = Number(state_view.get(6)); const H7 = Number(state_view.get(7)); let A = H0; let B = H1; let C = H2; let D = H3; let E = H4; let F = H5; let G = H6; let H = H7; // 合并执行 扩展 & 压缩 const W = new Uint32Array(68); const W1 = new Uint32Array(64); for (let i = 0; i < 68; i++) { // 拓展 W if (i < 16) { // W[i] = B(n)[i] W[i] = p_view.getUint32(offset + (i << 2), false); } else { W[i] = P1(W[i - 16] ^ W[i - 9] ^ rotateL32(W[i - 3], 15)) ^ rotateL32(W[i - 13], 7) ^ W[i - 6]; } // W1 拓展 & 压缩 if (i > 3) { // W1 拓展 const j = i - 4; // W1[j] = W[j] ^ W[j + 4] W1[j] = W[j] ^ W[i]; // 压缩 const T = j < 16 ? 0x79CC4519 : 0x7A879D8A; const SS1 = rotateL32(rotateL32(A, 12) + E + rotateL32(T, j), 7); const SS2 = SS1 ^ rotateL32(A, 12); const TT1 = FF(A, B, C, j) + D + SS2 + W1[j]; const TT2 = GG(E, F, G, j) + H + SS1 + W[j]; D = C; C = rotateL32(B, 9); B = A; A = TT1; H = G; G = rotateL32(F, 19); F = E; E = P0(TT2); } } // 更新状态字 state_view.set(0, BigInt(H0 ^ A)); state_view.set(1, BigInt(H1 ^ B)); state_view.set(2, BigInt(H2 ^ C)); state_view.set(3, BigInt(H3 ^ D)); state_view.set(4, BigInt(H4 ^ E)); state_view.set(5, BigInt(H5 ^ F)); state_view.set(6, BigInt(H6 ^ G)); state_view.set(7, BigInt(H7 ^ H)); } // * 截断输出 return state; } export const sm3 = createHash(digest, { ALGORITHM: 'SM3', BLOCK_SIZE: 64, DIGEST_SIZE: 32, OID: '1.2.156.10197.1.401', });