Comparing version 0.2.5 to 0.2.6
@@ -0,1 +1,5 @@ | ||
## 0.2.6 | ||
* 优化 sm3 性能 | ||
## 0.2.5 | ||
@@ -2,0 +6,0 @@ |
{ | ||
"name": "sm-crypto", | ||
"version": "0.2.5", | ||
"version": "0.2.6", | ||
"description": "sm-crypto", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
/** | ||
* 左补 0 到指定长度 | ||
* 字节数组转 16 进制串 | ||
*/ | ||
function leftPad(input, num) { | ||
if (input.length >= num) return input | ||
return (new Array(num - input.length + 1)).join('0') + input | ||
function ArrayToHex(arr) { | ||
return arr.map(item => { | ||
item = item.toString(16) | ||
return item.length === 1 ? '0' + item : item | ||
}).join('') | ||
} | ||
/** | ||
* 二进制转化为十六进制 | ||
* utf8 串转字节数组 | ||
*/ | ||
function binary2hex(binary) { | ||
const binaryLength = 8 | ||
let hex = '' | ||
for (let i = 0; i < binary.length / binaryLength; i++) { | ||
hex += leftPad(parseInt(binary.substr(i * binaryLength, binaryLength), 2).toString(16), 2) | ||
} | ||
return hex | ||
} | ||
function utf8ToArray(str) { | ||
const arr = [] | ||
/** | ||
* 十六进制转化为二进制 | ||
*/ | ||
function hex2binary(hex) { | ||
const hexLength = 2 | ||
let binary = '' | ||
for (let i = 0; i < hex.length / hexLength; i++) { | ||
binary += leftPad(parseInt(hex.substr(i * hexLength, hexLength), 16).toString(2), 8) | ||
} | ||
return binary | ||
} | ||
/** | ||
* 普通字符串转化为二进制 | ||
*/ | ||
function str2binary(str) { | ||
let binary = '' | ||
for (let i = 0, len = str.length; i < len; i++) { | ||
@@ -45,22 +22,22 @@ const point = str.codePointAt(i) | ||
// 单字节,标量值:00000000 00000000 0zzzzzzz | ||
binary += leftPad(point.toString(2), 8) | ||
arr.push(point) | ||
} else if (point <= 0x07ff) { | ||
// 双字节,标量值:00000000 00000yyy yyzzzzzz | ||
binary += leftPad((0xc0 | (point >>> 6)).toString(2), 8) // 110yyyyy(0xc0-0xdf) | ||
binary += leftPad((0x80 | (point & 0x3f)).toString(2), 8) // 10zzzzzz(0x80-0xbf) | ||
arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf) | ||
arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf) | ||
} else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) { | ||
// 三字节:标量值:00000000 xxxxyyyy yyzzzzzz | ||
binary += leftPad((0xe0 | (point >>> 12)).toString(2), 8) // 1110xxxx(0xe0-0xef) | ||
binary += leftPad((0x80 | ((point >>> 6) & 0x3f)).toString(2), 8) // 10yyyyyy(0x80-0xbf) | ||
binary += leftPad((0x80 | (point & 0x3f)).toString(2), 8) // 10zzzzzz(0x80-0xbf) | ||
arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef) | ||
arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf) | ||
arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf) | ||
} else if (point >= 0x010000 && point <= 0x10FFFF) { | ||
// 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz | ||
i++ | ||
binary += leftPad((0xf0 | ((point >>> 18) & 0x1c)).toString(2), 8) // 11110www(0xf0-0xf7) | ||
binary += leftPad((0x80 | ((point >>> 12) & 0x3f)).toString(2), 8) // 10xxxxxx(0x80-0xbf) | ||
binary += leftPad((0x80 | ((point >>> 6) & 0x3f)).toString(2), 8) // 10yyyyyy(0x80-0xbf) | ||
binary += leftPad((0x80 | (point & 0x3f)).toString(2), 8) // 10zzzzzz(0x80-0xbf) | ||
arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7) | ||
arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf) | ||
arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf) | ||
arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf) | ||
} else { | ||
// 五、六字节,暂时不支持 | ||
binary += leftPad(point.toString(2), 8) | ||
arr.push(point) | ||
throw new Error('input is not supported') | ||
@@ -70,33 +47,17 @@ } | ||
return binary | ||
return arr | ||
} | ||
/** | ||
* 数组转为二进制 | ||
*/ | ||
function array2binary(arr) { | ||
return arr.reduce((temp, item) => temp + leftPad(item.toString(2), 8), '') | ||
} | ||
/** | ||
* 循环左移 | ||
*/ | ||
function rol(str, n) { | ||
return str.substring(n % str.length) + str.substr(0, n % str.length) | ||
} | ||
/** | ||
* 二进制运算 | ||
*/ | ||
function binaryCal(x, y, method) { | ||
const a = x || '' | ||
const b = y || '' | ||
function rotl(x, n) { | ||
const result = [] | ||
let prevResult | ||
for (let i = a.length - 1; i >= 0; i--) { // 大端 | ||
prevResult = method(a[i], b[i], prevResult) | ||
result[i] = prevResult[0] | ||
const a = ~~(n / 8) // 偏移 a 字节 | ||
const b = n % 8 // 偏移 b 位 | ||
for (let i = 0, len = x.length; i < len; i++) { | ||
// current << b + (current + 1) >>> (8 - b) | ||
result[i] = ((x[(i + a) % len] << b )& 0xff) + ((x[(i + a + 1) % len] >>> (8 - b)) & 0xff) | ||
} | ||
return result.join('') | ||
return result | ||
} | ||
@@ -108,3 +69,5 @@ | ||
function xor(x, y) { | ||
return binaryCal(x, y, (a, b) => [(a === b ? '0' : '1')]) | ||
const result = [] | ||
for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] ^ y[i]) & 0xff | ||
return result | ||
} | ||
@@ -116,3 +79,5 @@ | ||
function and(x, y) { | ||
return binaryCal(x, y, (a, b) => [(a === '1' && b === '1' ? '1' : '0')]) | ||
const result = [] | ||
for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] & y[i]) & 0xff | ||
return result | ||
} | ||
@@ -124,3 +89,5 @@ | ||
function or(x, y) { | ||
return binaryCal(x, y, (a, b) => [(a === '1' || b === '1' ? '1' : '0')]) // a === '0' && b === '0' ? '0' : '1' | ||
const result = [] | ||
for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] | y[i]) & 0xff | ||
return result | ||
} | ||
@@ -132,12 +99,14 @@ | ||
function add(x, y) { | ||
const result = binaryCal(x, y, (a, b, prevResult) => { | ||
const carry = prevResult ? prevResult[1] : '0' || '0' | ||
// a, b 不等时,carry 不变,结果与 carry 相反 | ||
// a, b 相等时,结果等于原 carry,新 carry 等于 a | ||
if (a !== b) return [carry === '0' ? '1' : '0', carry] | ||
return [carry, a] | ||
}) | ||
const result = [] | ||
let temp = 0 | ||
for (let i = x.length - 1; i >= 0; i--) { | ||
const sum = x[i] + y[i] + temp | ||
if (sum > 0xff) { | ||
temp = 1 | ||
result[i] = sum & 0xff | ||
} else { | ||
temp = 0 | ||
result[i] = sum & 0xff | ||
} | ||
} | ||
return result | ||
@@ -150,9 +119,7 @@ } | ||
function not(x) { | ||
return binaryCal(x, undefined, a => [a === '1' ? '0' : '1']) | ||
const result = [] | ||
for (let i = x.length - 1; i >= 0; i--) result[i] = (~x[i]) & 0xff | ||
return result | ||
} | ||
function calMulti(method) { | ||
return (...arr) => arr.reduce((prev, curr) => method(prev, curr)) | ||
} | ||
/** | ||
@@ -162,3 +129,3 @@ * 压缩函数中的置换函数 P1(X) = X xor (X <<< 9) xor (X <<< 17) | ||
function P0(X) { | ||
return calMulti(xor)(X, rol(X, 9), rol(X, 17)) | ||
return xor(xor(X, rotl(X, 9)), rotl(X, 17)) | ||
} | ||
@@ -170,17 +137,19 @@ | ||
function P1(X) { | ||
return calMulti(xor)(X, rol(X, 15), rol(X, 23)) | ||
return xor(xor(X, rotl(X, 15)), rotl(X, 23)) | ||
} | ||
/** | ||
* 布尔函数 FF | ||
*/ | ||
function FF(X, Y, Z, j) { | ||
return j >= 0 && j <= 15 ? calMulti(xor)(X, Y, Z) : calMulti(or)(and(X, Y), and(X, Z), and(Y, Z)) | ||
return j >= 0 && j <= 15 ? xor(xor(X, Y), Z) : or(or(and(X, Y), and(X, Z)), and(Y, Z)) | ||
} | ||
/** | ||
* 布尔函数 GG | ||
*/ | ||
function GG(X, Y, Z, j) { | ||
return j >= 0 && j <= 15 ? calMulti(xor)(X, Y, Z) : or(and(X, Y), and(not(X), Z)) | ||
return j >= 0 && j <= 15 ? xor(xor(X, Y), Z) : or(and(X, Y), and(not(X), Z)) | ||
} | ||
function T(j) { | ||
return j >= 0 && j <= 15 ? hex2binary('79cc4519') : hex2binary('7a879d8a') | ||
} | ||
/** | ||
@@ -191,16 +160,23 @@ * 压缩函数 | ||
// 消息扩展 | ||
const wordLength = 32 | ||
const W = [] | ||
const M = [] // W' | ||
// 将消息分组B划分为16个字W0, W1,…… ,W15 (字为长度为32的比特串) | ||
// 将消息分组B划分为 16 个字 W0, W1,……,W15 | ||
for (let i = 0; i < 16; i++) { | ||
W.push(Bi.substr(i * wordLength, wordLength)) | ||
const start = i * 4 | ||
W.push(Bi.slice(start, start + 4)) | ||
} | ||
// W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6] | ||
// 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.push(calMulti(xor)( | ||
P1(calMulti(xor)(W[j - 16], W[j - 9], rol(W[j - 3], 15))), | ||
rol(W[j - 13], 7), | ||
W.push(xor( | ||
xor( | ||
P1( | ||
xor( | ||
xor(W[j - 16], W[j - 9]), | ||
rotl(W[j - 3], 15) | ||
) | ||
), | ||
rotl(W[j - 13], 7) | ||
), | ||
W[j - 6] | ||
@@ -210,3 +186,3 @@ )) | ||
// W′[j] = W[j] xor W[j+4] | ||
// W′0 ~ W′63:W′[j] = W[j] xor W[j+4] | ||
for (let j = 0; j < 64; j++) { | ||
@@ -217,16 +193,13 @@ M.push(xor(W[j], W[j + 4])) | ||
// 压缩 | ||
const wordRegister = [] // 字寄存器 | ||
for (let j = 0; j < 8; j++) { | ||
wordRegister.push(V.substr(j * wordLength, wordLength)) | ||
} | ||
let A = wordRegister[0] | ||
let B = wordRegister[1] | ||
let C = wordRegister[2] | ||
let D = wordRegister[3] | ||
let E = wordRegister[4] | ||
let F = wordRegister[5] | ||
let G = wordRegister[6] | ||
let H = wordRegister[7] | ||
const T1 = [0x79, 0xcc, 0x45, 0x19] | ||
const T2 = [0x7a, 0x87, 0x9d, 0x8a] | ||
// 字寄存器 | ||
let A = V.slice(0, 4) | ||
let B = V.slice(4, 8) | ||
let C = V.slice(8, 12) | ||
let D = V.slice(12, 16) | ||
let E = V.slice(16, 20) | ||
let F = V.slice(20, 24) | ||
let G = V.slice(24, 28) | ||
let H = V.slice(28, 32) | ||
// 中间变量 | ||
@@ -238,14 +211,18 @@ let SS1 | ||
for (let j = 0; j < 64; j++) { | ||
SS1 = rol(calMulti(add)(rol(A, 12), E, rol(T(j), j)), 7) | ||
SS2 = xor(SS1, rol(A, 12)) | ||
const T = j >= 0 && j <= 15 ? T1 : T2 | ||
SS1 = rotl(add( | ||
add(rotl(A, 12), E), | ||
rotl(T, j) | ||
), 7) | ||
SS2 = xor(SS1, rotl(A, 12)) | ||
TT1 = calMulti(add)(FF(A, B, C, j), D, SS2, M[j]) | ||
TT2 = calMulti(add)(GG(E, F, G, j), H, SS1, W[j]) | ||
TT1 = add(add(add(FF(A, B, C, j), D), SS2), M[j]) | ||
TT2 = add(add(add(GG(E, F, G, j), H), SS1), W[j]) | ||
D = C | ||
C = rol(B, 9) | ||
C = rotl(B, 9) | ||
B = A | ||
A = TT1 | ||
H = G | ||
G = rol(F, 19) | ||
G = rotl(F, 19) | ||
F = E | ||
@@ -255,28 +232,45 @@ E = P0(TT2) | ||
return xor([A, B, C, D, E, F, G, H].join(''), V) | ||
return xor([].concat(A, B, C, D, E, F, G, H), V) | ||
} | ||
module.exports = function (str) { | ||
const binary = typeof str === 'string' ? str2binary(str) : array2binary(str) | ||
module.exports = function (input) { | ||
const array = typeof input === 'string' ? utf8ToArray(input) : Array.prototype.slice.call(input) | ||
// 填充 | ||
const len = binary.length | ||
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 m = `${binary}1${leftPad('', k)}${leftPad(len.toString(2), 64)}`.toString() // k个0 | ||
// 填充 | ||
const kArr = new Array((k - 7) / 8) | ||
for (let i = 0, len = kArr.length; i < len; i++) kArr[i] = 0 | ||
const lenArr = [] | ||
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 = '' | ||
} else { | ||
lenArr[i] = 0 | ||
} | ||
} | ||
const m = [].concat(array, [0x80], kArr, lenArr) | ||
// 迭代压缩 | ||
const n = (len + k + 65) / 512 | ||
let V = hex2binary('7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e') | ||
for (let i = 0; i <= n - 1; i++) { | ||
const B = m.substr(512 * i, 512) | ||
const n = m.length / 64 | ||
let V = [0x73, 0x80, 0x16, 0x6f, 0x49, 0x14, 0xb2, 0xb9, 0x17, 0x24, 0x42, 0xd7, 0xda, 0x8a, 0x06, 0x00, 0xa9, 0x6f, 0x30, 0xbc, 0x16, 0x31, 0x38, 0xaa, 0xe3, 0x8d, 0xee, 0x4d, 0xb0, 0xfb, 0x0e, 0x4e] | ||
for (let i = 0; i < n; i++) { | ||
const start = 64 * i | ||
const B = m.slice(start, start + 64) | ||
V = CF(V, B) | ||
} | ||
return binary2hex(V) | ||
return ArrayToHex(V) | ||
} | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1828
110947