| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- // 消息扩展
- const W = new Uint32Array(68)
- const M = new Uint32Array(64) // W'
- /**
- * 循环左移
- */
- function rotl(x, n) {
- const s = n & 31
- return (x << s) | (x >>> (32 - s))
- }
- /**
- * 二进制异或运算
- */
- function xor(x, y) {
- const result = []
- for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] ^ y[i]) & 0xff
- return result
- }
- /**
- * 压缩函数中的置换函数 P0(X) = X xor (X <<< 9) xor (X <<< 17)
- */
- function P0(X) {
- return (X ^ rotl(X, 9)) ^ rotl(X, 17)
- }
- /**
- * 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)
- */
- function P1(X) {
- return (X ^ rotl(X, 15)) ^ rotl(X, 23)
- }
- /**
- * sm3 本体
- */
- function sm3(array) {
- let len = array.length * 8
- // k 是满足 len + 1 + k = 448mod512 的最小的非负整数
- let k = len % 512
- // 如果 448 <= (512 % len) < 512,需要多补充 (len % 448) 比特'0'以满足总比特长度为512的倍数
- k = k >= 448 ? 512 - (k % 448) - 1 : 448 - k - 1
- // 填充
- const kArr = new Array((k - 7) / 8)
- const lenArr = new Array(8)
- for (let i = 0, len = kArr.length; i < len; i++) kArr[i] = 0
- for (let i = 0, len = lenArr.length; i < len; i++) lenArr[i] = 0
- len = len.toString(2)
- for (let i = 7; i >= 0; i--) {
- if (len.length > 8) {
- const start = len.length - 8
- lenArr[i] = parseInt(len.substr(start), 2)
- len = len.substr(0, start)
- } else if (len.length > 0) {
- lenArr[i] = parseInt(len, 2)
- len = ''
- }
- }
- const m = new Uint8Array([...array, 0x80, ...kArr, ...lenArr])
- const dataView = new DataView(m.buffer, 0)
- // 迭代压缩
- const n = m.length / 64
- const V = new Uint32Array([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e])
- for (let i = 0; i < n; i++) {
- W.fill(0)
- M.fill(0)
- // 将消息分组B划分为 16 个字 W0, W1,……,W15
- const start = 16 * i
- for (let j = 0; j < 16; j++) {
- W[j] = dataView.getUint32((start + j) * 4, false)
- }
- // W16 ~ W67:W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6]
- for (let j = 16; j < 68; j++) {
- W[j] = (P1((W[j - 16] ^ W[j - 9]) ^ rotl(W[j - 3], 15)) ^ rotl(W[j - 13], 7)) ^ W[j - 6]
- }
- // W′0 ~ W′63:W′[j] = W[j] xor W[j+4]
- for (let j = 0; j < 64; j++) {
- M[j] = W[j] ^ W[j + 4]
- }
- // 压缩
- const T1 = 0x79cc4519
- const T2 = 0x7a879d8a
- // 字寄存器
- let A = V[0]
- let B = V[1]
- let C = V[2]
- let D = V[3]
- let E = V[4]
- let F = V[5]
- let G = V[6]
- let H = V[7]
- // 中间变量
- let SS1
- let SS2
- let TT1
- let TT2
- let T
- for (let j = 0; j < 64; j++) {
- T = j >= 0 && j <= 15 ? T1 : T2
- SS1 = rotl(rotl(A, 12) + E + rotl(T, j), 7)
- SS2 = SS1 ^ rotl(A, 12)
- TT1 = (j >= 0 && j <= 15 ? ((A ^ B) ^ C) : (((A & B) | (A & C)) | (B & C))) + D + SS2 + M[j]
- TT2 = (j >= 0 && j <= 15 ? ((E ^ F) ^ G) : ((E & F) | ((~E) & G))) + H + SS1 + W[j]
- D = C
- C = rotl(B, 9)
- B = A
- A = TT1
- H = G
- G = rotl(F, 19)
- F = E
- E = P0(TT2)
- }
- V[0] ^= A
- V[1] ^= B
- V[2] ^= C
- V[3] ^= D
- V[4] ^= E
- V[5] ^= F
- V[6] ^= G
- V[7] ^= H
- }
- // 转回 uint8
- const result = []
- for (let i = 0, len = V.length; i < len; i++) {
- const word = V[i]
- result.push((word & 0xff000000) >>> 24, (word & 0xff0000) >>> 16, (word & 0xff00) >>> 8, word & 0xff)
- }
- return result
- }
- /**
- * hmac 实现
- */
- const blockLen = 64
- const iPad = new Uint8Array(blockLen)
- const oPad = new Uint8Array(blockLen)
- for (let i = 0; i < blockLen; i++) {
- iPad[i] = 0x36
- oPad[i] = 0x5c
- }
- function hmac(input, key) {
- // 密钥填充
- if (key.length > blockLen) key = sm3(key)
- while (key.length < blockLen) key.push(0)
- const iPadKey = xor(key, iPad)
- const oPadKey = xor(key, oPad)
- const hash = sm3([...iPadKey, ...input])
- return sm3([...oPadKey, ...hash])
- }
- module.exports = {
- sm3,
- hmac,
- }
|