sm-crypto-v2 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +13 -6
- package/dist/index.d.ts +4 -1
- package/dist/index.js +101 -63
- package/dist/index.mjs +101 -63
- package/package.json +1 -1
- package/src/sm2/index.ts +9 -4
- package/src/sm2/kx.ts +9 -6
- package/src/sm2/rng.ts +17 -11
- package/src/sm4/_slow.ts +286 -0
- package/src/sm4/index.ts +99 -60
- package/.babelrc +0 -3
- package/.eslintrc.js +0 -97
- package/.github/workflows/test.yml +0 -17
- package/benchmark/index.js +0 -29
- package/benchmark/package.json +0 -19
- package/benchmark/pnpm-lock.yaml +0 -32
- package/pnpm-lock.yaml +0 -3946
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,20 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
4
4
|
|
5
|
+
## [1.6.0](https://github.com/Cubelrti/sm-crypto-v2/compare/v1.5.1...v1.6.0) (2023-07-11)
|
6
|
+
|
7
|
+
|
8
|
+
### Features
|
9
|
+
|
10
|
+
* **sm4:** optimize sm4 ([031159c](https://github.com/Cubelrti/sm-crypto-v2/commit/031159c7e2889f01b499b9286ce1d93a5e55b151))
|
11
|
+
|
12
|
+
### [1.5.1](https://github.com/Cubelrti/sm-crypto-v2/compare/v1.5.0...v1.5.1) (2023-06-28)
|
13
|
+
|
14
|
+
|
15
|
+
### Bug Fixes
|
16
|
+
|
17
|
+
* **sm2/kx:** align key exchange with standard ([b4fae83](https://github.com/Cubelrti/sm-crypto-v2/commit/b4fae831ae587821a9c1fe72617420134ae7f326))
|
18
|
+
|
5
19
|
## [1.5.0](https://github.com/Cubelrti/sm-crypto-v2/compare/v1.4.0...v1.5.0) (2023-06-11)
|
6
20
|
|
7
21
|
|
package/README.md
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
- ✔️ 通过全部历史单元测试,包括 SM2、SM3 和 SM4
|
17
17
|
- 🎲 自动选择最优的安全随机数实现,避免使用 `Math.random()` 和 `Date.now()` 进行模拟
|
18
18
|
- 📚 同时导出 ES Module 和 CommonJS 两种格式,可按需使用
|
19
|
-
- 🔑
|
19
|
+
- 🔑 提供 SM2 密钥交换 API
|
20
20
|
- 🎒 未压缩大小 34kb,压缩后 17kb
|
21
21
|
|
22
22
|
## 安装
|
@@ -167,7 +167,7 @@ let decryptData = sm4.decrypt(encryptData, key, {padding: 'none', output: 'array
|
|
167
167
|
let decryptData = sm4.decrypt(encryptData, key, {mode: 'cbc', iv: 'fedcba98765432100123456789abcdef'}) // 解密,cbc 模式
|
168
168
|
```
|
169
169
|
|
170
|
-
### 密钥交换
|
170
|
+
### 密钥交换
|
171
171
|
|
172
172
|
```js
|
173
173
|
import { sm2 } from 'sm-crypto-v2'
|
@@ -177,10 +177,17 @@ const keyPairB = sm2.generateKeyPairHex() // B 的秘钥对
|
|
177
177
|
const ephemeralKeypairA = sm2.generateKeyPairHex() // A 的临时秘钥对
|
178
178
|
const ephemeralKeypairB = sm2.generateKeyPairHex() // B 的临时秘钥对
|
179
179
|
|
180
|
-
//
|
181
|
-
|
182
|
-
|
183
|
-
|
180
|
+
// 无身份的密钥交换
|
181
|
+
// A 所需参数:A 的秘钥对,A 的临时秘钥对,B 的公钥,B 的临时秘钥公钥,长度,是否为接收方(默认为 false)
|
182
|
+
const sharedKeyFromA = sm2.calculateSharedKey(keyPairA, ephemeralKeypairA, keyPairB.publicKey, ephemeralKeypairB.publicKey, 233)
|
183
|
+
// B 所需参数:B 的秘钥对,B 的临时秘钥对,A 的公钥,A 的临时秘钥公钥,长度,是否为接收方(默认为 false)
|
184
|
+
const sharedKeyFromB = sm2.calculateSharedKey(keyPairB, ephemeralKeypairB, keyPairA.publicKey, ephemeralKeypairA.publicKey, 233, true)
|
185
|
+
|
186
|
+
// 带身份的密钥交换
|
187
|
+
// A 所需参数:A 的秘钥对,A 的临时秘钥对,B 的公钥,B 的临时秘钥公钥,长度,是否为接收方(默认为 false),A 的身份,B 的身份
|
188
|
+
const sharedKeyFromA = sm2.calculateSharedKey(keyPairA, ephemeralKeypairA, keyPairB.publicKey, ephemeralKeypairB.publicKey, 233, false, 'alice@yahoo.com', 'bob@yahoo.com')
|
189
|
+
// B 所需参数:B 的秘钥对,B 的临时秘钥对,A 的公钥,A 的临时秘钥公钥,长度,是否为接收方(默认为 false),B 的身份,A 的身份
|
190
|
+
const sharedKeyFromB = sm2.calculateSharedKey(keyPairB, ephemeralKeypairB, keyPairA.publicKey, ephemeralKeypairA.publicKey, 233, true, 'bob@yahoo.com', 'alice@yahoo.com')
|
184
191
|
|
185
192
|
// expect(sharedKeyFromA).toEqual(sharedKeyFromB) => true
|
186
193
|
```
|
package/dist/index.d.ts
CHANGED
@@ -41,7 +41,7 @@ declare function comparePublicKeyHex(publicKey1: string, publicKey2: string): bo
|
|
41
41
|
|
42
42
|
declare function initRNGPool(): Promise<void>;
|
43
43
|
|
44
|
-
declare function calculateSharedKey(keypairA: KeyPair, ephemeralKeypairA: KeyPair, publicKeyB: string, ephemeralPublicKeyB: string,
|
44
|
+
declare function calculateSharedKey(keypairA: KeyPair, ephemeralKeypairA: KeyPair, publicKeyB: string, ephemeralPublicKeyB: string, sharedKeyLength: number, isRecipient?: boolean, idA?: string, idB?: string): Uint8Array;
|
45
45
|
|
46
46
|
declare const EmptyArray: Uint8Array;
|
47
47
|
/**
|
@@ -79,6 +79,7 @@ declare function doVerifySignature(msg: string | Uint8Array, signHex: string, pu
|
|
79
79
|
hash?: boolean;
|
80
80
|
userId?: string;
|
81
81
|
}): boolean;
|
82
|
+
declare function getZ(publicKey: string, userId?: string): Uint8Array;
|
82
83
|
/**
|
83
84
|
* sm3杂凑算法
|
84
85
|
*/
|
@@ -103,6 +104,7 @@ declare const index$1_doDecrypt: typeof doDecrypt;
|
|
103
104
|
type index$1_SignaturePoint = SignaturePoint;
|
104
105
|
declare const index$1_doSignature: typeof doSignature;
|
105
106
|
declare const index$1_doVerifySignature: typeof doVerifySignature;
|
107
|
+
declare const index$1_getZ: typeof getZ;
|
106
108
|
declare const index$1_getHash: typeof getHash;
|
107
109
|
declare const index$1_getPublicKeyFromPrivateKey: typeof getPublicKeyFromPrivateKey;
|
108
110
|
declare const index$1_getPoint: typeof getPoint;
|
@@ -126,6 +128,7 @@ declare namespace index$1 {
|
|
126
128
|
index$1_SignaturePoint as SignaturePoint,
|
127
129
|
index$1_doSignature as doSignature,
|
128
130
|
index$1_doVerifySignature as doVerifySignature,
|
131
|
+
index$1_getZ as getZ,
|
129
132
|
index$1_getHash as getHash,
|
130
133
|
index$1_getPublicKeyFromPrivateKey as getPublicKeyFromPrivateKey,
|
131
134
|
index$1_getPoint as getPoint,
|
package/dist/index.js
CHANGED
@@ -49,6 +49,7 @@ __export(sm2_exports, {
|
|
49
49
|
getHash: () => getHash,
|
50
50
|
getPoint: () => getPoint,
|
51
51
|
getPublicKeyFromPrivateKey: () => getPublicKeyFromPrivateKey,
|
52
|
+
getZ: () => getZ,
|
52
53
|
hexToArray: () => hexToArray,
|
53
54
|
initRNGPool: () => initRNGPool,
|
54
55
|
leftPad: () => leftPad,
|
@@ -197,7 +198,7 @@ async function initRNGPool() {
|
|
197
198
|
}
|
198
199
|
if (prngPool.length > DEFAULT_PRNG_POOL_SIZE / 2)
|
199
200
|
return;
|
200
|
-
if ("wx" in globalThis) {
|
201
|
+
if ("wx" in globalThis && "getRandomValues" in globalThis.wx) {
|
201
202
|
prngPool = await new Promise((r) => {
|
202
203
|
wx.getRandomValues({
|
203
204
|
length: DEFAULT_PRNG_POOL_SIZE,
|
@@ -208,11 +209,15 @@ async function initRNGPool() {
|
|
208
209
|
});
|
209
210
|
} else {
|
210
211
|
try {
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
212
|
+
if (globalThis.crypto) {
|
213
|
+
_syncCrypto = globalThis.crypto;
|
214
|
+
} else {
|
215
|
+
const crypto = await import(
|
216
|
+
/* webpackIgnore: true */
|
217
|
+
"crypto"
|
218
|
+
);
|
219
|
+
_syncCrypto = crypto.webcrypto;
|
220
|
+
}
|
216
221
|
const array = new Uint8Array(DEFAULT_PRNG_POOL_SIZE);
|
217
222
|
_syncCrypto.getRandomValues(array);
|
218
223
|
prngPool = array;
|
@@ -679,16 +684,19 @@ function hkdf(z, keylen) {
|
|
679
684
|
}
|
680
685
|
return msg;
|
681
686
|
}
|
682
|
-
function calculateSharedKey(keypairA, ephemeralKeypairA, publicKeyB, ephemeralPublicKeyB, idA = "1234567812345678", idB = "1234567812345678"
|
687
|
+
function calculateSharedKey(keypairA, ephemeralKeypairA, publicKeyB, ephemeralPublicKeyB, sharedKeyLength, isRecipient = false, idA = "1234567812345678", idB = "1234567812345678") {
|
683
688
|
const RA = sm2Curve.ProjectivePoint.fromHex(ephemeralKeypairA.publicKey);
|
684
689
|
const RB = sm2Curve.ProjectivePoint.fromHex(ephemeralPublicKeyB);
|
685
690
|
const PB = sm2Curve.ProjectivePoint.fromHex(publicKeyB);
|
686
|
-
|
687
|
-
|
691
|
+
let ZA = getZ(keypairA.publicKey, idA);
|
692
|
+
let ZB = getZ(publicKeyB, idB);
|
693
|
+
if (isRecipient) {
|
694
|
+
[ZA, ZB] = [ZB, ZA];
|
695
|
+
}
|
688
696
|
const rA = utils3.hexToNumber(ephemeralKeypairA.privateKey);
|
689
697
|
const dA = utils3.hexToNumber(keypairA.privateKey);
|
690
698
|
const x1 = RA.x;
|
691
|
-
const x1_ =
|
699
|
+
const x1_ = wPow2 + (x1 & wPow2Sub1);
|
692
700
|
const tA = field.add(dA, field.mulN(x1_, rA));
|
693
701
|
const x2 = RB.x;
|
694
702
|
const x2_ = field.add(wPow2, x2 & wPow2Sub1);
|
@@ -828,7 +836,7 @@ function doVerifySignature(msg, signHex, publicKey, options = {}) {
|
|
828
836
|
const R = field.add(e, x1y1.x);
|
829
837
|
return r === R;
|
830
838
|
}
|
831
|
-
function
|
839
|
+
function getZ(publicKey, userId = "1234567812345678") {
|
832
840
|
userId = utf8ToHex(userId);
|
833
841
|
const a = leftPad(utils4.numberToHexUnpadded(sm2Curve.CURVE.a), 64);
|
834
842
|
const b = leftPad(utils4.numberToHexUnpadded(sm2Curve.CURVE.b), 64);
|
@@ -847,6 +855,10 @@ function getHash(hashHex, publicKey, userId = "1234567812345678") {
|
|
847
855
|
const data = hexToArray(userId + a + b + gx + gy + px + py);
|
848
856
|
const entl = userId.length * 4;
|
849
857
|
const z = sm3(utils4.concatBytes(new Uint8Array([entl >> 8 & 255, entl & 255]), data));
|
858
|
+
return z;
|
859
|
+
}
|
860
|
+
function getHash(hashHex, publicKey, userId = "1234567812345678") {
|
861
|
+
const z = getZ(publicKey, userId);
|
850
862
|
return bytesToHex(sm3(utils4.concatBytes(z, typeof hashHex === "string" ? hexToArray(hashHex) : hashHex)));
|
851
863
|
}
|
852
864
|
function getPublicKeyFromPrivateKey(privateKey) {
|
@@ -1212,66 +1224,92 @@ var CK = new Uint32Array([
|
|
1212
1224
|
function byteSub(a) {
|
1213
1225
|
return (Sbox[a >>> 24 & 255] & 255) << 24 | (Sbox[a >>> 16 & 255] & 255) << 16 | (Sbox[a >>> 8 & 255] & 255) << 8 | Sbox[a & 255] & 255;
|
1214
1226
|
}
|
1215
|
-
function l1(b) {
|
1216
|
-
return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24);
|
1217
|
-
}
|
1218
|
-
function l2(b) {
|
1219
|
-
return b ^ rotl(b, 13) ^ rotl(b, 23);
|
1220
|
-
}
|
1221
1227
|
var x = new Uint32Array(4);
|
1222
1228
|
var tmp = new Uint32Array(4);
|
1223
1229
|
function sms4Crypt(input, output, roundKey) {
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1230
|
+
let x0 = 0, x1 = 0, x2 = 0, x3 = 0, tmp0 = 0, tmp1 = 0, tmp2 = 0, tmp3 = 0;
|
1231
|
+
tmp0 = input[0] & 255;
|
1232
|
+
tmp1 = input[1] & 255;
|
1233
|
+
tmp2 = input[2] & 255;
|
1234
|
+
tmp3 = input[3] & 255;
|
1235
|
+
x0 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
|
1236
|
+
tmp0 = input[4] & 255;
|
1237
|
+
tmp1 = input[5] & 255;
|
1238
|
+
tmp2 = input[6] & 255;
|
1239
|
+
tmp3 = input[7] & 255;
|
1240
|
+
x1 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
|
1241
|
+
tmp0 = input[8] & 255;
|
1242
|
+
tmp1 = input[9] & 255;
|
1243
|
+
tmp2 = input[10] & 255;
|
1244
|
+
tmp3 = input[11] & 255;
|
1245
|
+
x2 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
|
1246
|
+
tmp0 = input[12] & 255;
|
1247
|
+
tmp1 = input[13] & 255;
|
1248
|
+
tmp2 = input[14] & 255;
|
1249
|
+
tmp3 = input[15] & 255;
|
1250
|
+
x3 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
|
1251
|
+
for (let r = 0; r < 32; r += 4) {
|
1252
|
+
tmp0 = x1 ^ x2 ^ x3 ^ roundKey[r];
|
1253
|
+
tmp0 = byteSub(tmp0);
|
1254
|
+
x0 ^= tmp0 ^ (tmp0 << 2 | tmp0 >>> 30) ^ (tmp0 << 10 | tmp0 >>> 22) ^ (tmp0 << 18 | tmp0 >>> 14) ^ (tmp0 << 24 | tmp0 >>> 8);
|
1255
|
+
tmp1 = x2 ^ x3 ^ x0 ^ roundKey[r + 1];
|
1256
|
+
tmp1 = byteSub(tmp1);
|
1257
|
+
x1 ^= tmp1 ^ (tmp1 << 2 | tmp1 >>> 30) ^ (tmp1 << 10 | tmp1 >>> 22) ^ (tmp1 << 18 | tmp1 >>> 14) ^ (tmp1 << 24 | tmp1 >>> 8);
|
1258
|
+
tmp2 = x3 ^ x0 ^ x1 ^ roundKey[r + 2];
|
1259
|
+
tmp2 = byteSub(tmp2);
|
1260
|
+
x2 ^= tmp2 ^ (tmp2 << 2 | tmp2 >>> 30) ^ (tmp2 << 10 | tmp2 >>> 22) ^ (tmp2 << 18 | tmp2 >>> 14) ^ (tmp2 << 24 | tmp2 >>> 8);
|
1261
|
+
tmp3 = x0 ^ x1 ^ x2 ^ roundKey[r + 3];
|
1262
|
+
tmp3 = byteSub(tmp3);
|
1263
|
+
x3 ^= tmp3 ^ (tmp3 << 2 | tmp3 >>> 30) ^ (tmp3 << 10 | tmp3 >>> 22) ^ (tmp3 << 18 | tmp3 >>> 14) ^ (tmp3 << 24 | tmp3 >>> 8);
|
1246
1264
|
}
|
1265
|
+
output[0] = x3 >>> 24 & 255;
|
1266
|
+
output[1] = x3 >>> 16 & 255;
|
1267
|
+
output[2] = x3 >>> 8 & 255;
|
1268
|
+
output[3] = x3 & 255;
|
1269
|
+
output[4] = x2 >>> 24 & 255;
|
1270
|
+
output[5] = x2 >>> 16 & 255;
|
1271
|
+
output[6] = x2 >>> 8 & 255;
|
1272
|
+
output[7] = x2 & 255;
|
1273
|
+
output[8] = x1 >>> 24 & 255;
|
1274
|
+
output[9] = x1 >>> 16 & 255;
|
1275
|
+
output[10] = x1 >>> 8 & 255;
|
1276
|
+
output[11] = x1 & 255;
|
1277
|
+
output[12] = x0 >>> 24 & 255;
|
1278
|
+
output[13] = x0 >>> 16 & 255;
|
1279
|
+
output[14] = x0 >>> 8 & 255;
|
1280
|
+
output[15] = x0 & 255;
|
1247
1281
|
}
|
1248
1282
|
function sms4KeyExt(key, roundKey, cryptFlag) {
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
roundKey[r + 0] =
|
1263
|
-
mid =
|
1264
|
-
|
1265
|
-
|
1266
|
-
roundKey[r +
|
1267
|
-
mid =
|
1268
|
-
|
1283
|
+
let x0 = 0, x1 = 0, x2 = 0, x3 = 0, mid = 0;
|
1284
|
+
x0 = (key[0] & 255) << 24 | (key[1] & 255) << 16 | (key[2] & 255) << 8 | key[3] & 255;
|
1285
|
+
x1 = (key[4] & 255) << 24 | (key[5] & 255) << 16 | (key[6] & 255) << 8 | key[7] & 255;
|
1286
|
+
x2 = (key[8] & 255) << 24 | (key[9] & 255) << 16 | (key[10] & 255) << 8 | key[11] & 255;
|
1287
|
+
x3 = (key[12] & 255) << 24 | (key[13] & 255) << 16 | (key[14] & 255) << 8 | key[15] & 255;
|
1288
|
+
x0 ^= 2746333894;
|
1289
|
+
x1 ^= 1453994832;
|
1290
|
+
x2 ^= 1736282519;
|
1291
|
+
x3 ^= 2993693404;
|
1292
|
+
for (let r = 0; r < 32; r += 4) {
|
1293
|
+
mid = x1 ^ x2 ^ x3 ^ CK[r + 0];
|
1294
|
+
mid = byteSub(mid);
|
1295
|
+
x0 ^= mid ^ (mid << 13 | mid >>> 19) ^ (mid << 23 | mid >>> 9);
|
1296
|
+
roundKey[r + 0] = x0;
|
1297
|
+
mid = x2 ^ x3 ^ x0 ^ CK[r + 1];
|
1298
|
+
mid = byteSub(mid);
|
1299
|
+
x1 ^= mid ^ (mid << 13 | mid >>> 19) ^ (mid << 23 | mid >>> 9);
|
1300
|
+
roundKey[r + 1] = x1;
|
1301
|
+
mid = x3 ^ x0 ^ x1 ^ CK[r + 2];
|
1302
|
+
mid = byteSub(mid);
|
1303
|
+
x2 ^= mid ^ (mid << 13 | mid >>> 19) ^ (mid << 23 | mid >>> 9);
|
1304
|
+
roundKey[r + 2] = x2;
|
1305
|
+
mid = x0 ^ x1 ^ x2 ^ CK[r + 3];
|
1306
|
+
mid = byteSub(mid);
|
1307
|
+
x3 ^= mid ^ (mid << 13 | mid >>> 19) ^ (mid << 23 | mid >>> 9);
|
1308
|
+
roundKey[r + 3] = x3;
|
1269
1309
|
}
|
1270
1310
|
if (cryptFlag === DECRYPT) {
|
1271
|
-
for (let r = 0
|
1272
|
-
|
1273
|
-
roundKey[r] = roundKey[31 - r];
|
1274
|
-
roundKey[31 - r] = mid;
|
1311
|
+
for (let r = 0; r < 16; r++) {
|
1312
|
+
[roundKey[r], roundKey[31 - r]] = [roundKey[31 - r], roundKey[r]];
|
1275
1313
|
}
|
1276
1314
|
}
|
1277
1315
|
}
|
package/dist/index.mjs
CHANGED
@@ -21,6 +21,7 @@ __export(sm2_exports, {
|
|
21
21
|
getHash: () => getHash,
|
22
22
|
getPoint: () => getPoint,
|
23
23
|
getPublicKeyFromPrivateKey: () => getPublicKeyFromPrivateKey,
|
24
|
+
getZ: () => getZ,
|
24
25
|
hexToArray: () => hexToArray,
|
25
26
|
initRNGPool: () => initRNGPool,
|
26
27
|
leftPad: () => leftPad,
|
@@ -169,7 +170,7 @@ async function initRNGPool() {
|
|
169
170
|
}
|
170
171
|
if (prngPool.length > DEFAULT_PRNG_POOL_SIZE / 2)
|
171
172
|
return;
|
172
|
-
if ("wx" in globalThis) {
|
173
|
+
if ("wx" in globalThis && "getRandomValues" in globalThis.wx) {
|
173
174
|
prngPool = await new Promise((r) => {
|
174
175
|
wx.getRandomValues({
|
175
176
|
length: DEFAULT_PRNG_POOL_SIZE,
|
@@ -180,11 +181,15 @@ async function initRNGPool() {
|
|
180
181
|
});
|
181
182
|
} else {
|
182
183
|
try {
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
184
|
+
if (globalThis.crypto) {
|
185
|
+
_syncCrypto = globalThis.crypto;
|
186
|
+
} else {
|
187
|
+
const crypto = await import(
|
188
|
+
/* webpackIgnore: true */
|
189
|
+
"crypto"
|
190
|
+
);
|
191
|
+
_syncCrypto = crypto.webcrypto;
|
192
|
+
}
|
188
193
|
const array = new Uint8Array(DEFAULT_PRNG_POOL_SIZE);
|
189
194
|
_syncCrypto.getRandomValues(array);
|
190
195
|
prngPool = array;
|
@@ -651,16 +656,19 @@ function hkdf(z, keylen) {
|
|
651
656
|
}
|
652
657
|
return msg;
|
653
658
|
}
|
654
|
-
function calculateSharedKey(keypairA, ephemeralKeypairA, publicKeyB, ephemeralPublicKeyB, idA = "1234567812345678", idB = "1234567812345678"
|
659
|
+
function calculateSharedKey(keypairA, ephemeralKeypairA, publicKeyB, ephemeralPublicKeyB, sharedKeyLength, isRecipient = false, idA = "1234567812345678", idB = "1234567812345678") {
|
655
660
|
const RA = sm2Curve.ProjectivePoint.fromHex(ephemeralKeypairA.publicKey);
|
656
661
|
const RB = sm2Curve.ProjectivePoint.fromHex(ephemeralPublicKeyB);
|
657
662
|
const PB = sm2Curve.ProjectivePoint.fromHex(publicKeyB);
|
658
|
-
|
659
|
-
|
663
|
+
let ZA = getZ(keypairA.publicKey, idA);
|
664
|
+
let ZB = getZ(publicKeyB, idB);
|
665
|
+
if (isRecipient) {
|
666
|
+
[ZA, ZB] = [ZB, ZA];
|
667
|
+
}
|
660
668
|
const rA = utils3.hexToNumber(ephemeralKeypairA.privateKey);
|
661
669
|
const dA = utils3.hexToNumber(keypairA.privateKey);
|
662
670
|
const x1 = RA.x;
|
663
|
-
const x1_ =
|
671
|
+
const x1_ = wPow2 + (x1 & wPow2Sub1);
|
664
672
|
const tA = field.add(dA, field.mulN(x1_, rA));
|
665
673
|
const x2 = RB.x;
|
666
674
|
const x2_ = field.add(wPow2, x2 & wPow2Sub1);
|
@@ -800,7 +808,7 @@ function doVerifySignature(msg, signHex, publicKey, options = {}) {
|
|
800
808
|
const R = field.add(e, x1y1.x);
|
801
809
|
return r === R;
|
802
810
|
}
|
803
|
-
function
|
811
|
+
function getZ(publicKey, userId = "1234567812345678") {
|
804
812
|
userId = utf8ToHex(userId);
|
805
813
|
const a = leftPad(utils4.numberToHexUnpadded(sm2Curve.CURVE.a), 64);
|
806
814
|
const b = leftPad(utils4.numberToHexUnpadded(sm2Curve.CURVE.b), 64);
|
@@ -819,6 +827,10 @@ function getHash(hashHex, publicKey, userId = "1234567812345678") {
|
|
819
827
|
const data = hexToArray(userId + a + b + gx + gy + px + py);
|
820
828
|
const entl = userId.length * 4;
|
821
829
|
const z = sm3(utils4.concatBytes(new Uint8Array([entl >> 8 & 255, entl & 255]), data));
|
830
|
+
return z;
|
831
|
+
}
|
832
|
+
function getHash(hashHex, publicKey, userId = "1234567812345678") {
|
833
|
+
const z = getZ(publicKey, userId);
|
822
834
|
return bytesToHex(sm3(utils4.concatBytes(z, typeof hashHex === "string" ? hexToArray(hashHex) : hashHex)));
|
823
835
|
}
|
824
836
|
function getPublicKeyFromPrivateKey(privateKey) {
|
@@ -1184,66 +1196,92 @@ var CK = new Uint32Array([
|
|
1184
1196
|
function byteSub(a) {
|
1185
1197
|
return (Sbox[a >>> 24 & 255] & 255) << 24 | (Sbox[a >>> 16 & 255] & 255) << 16 | (Sbox[a >>> 8 & 255] & 255) << 8 | Sbox[a & 255] & 255;
|
1186
1198
|
}
|
1187
|
-
function l1(b) {
|
1188
|
-
return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24);
|
1189
|
-
}
|
1190
|
-
function l2(b) {
|
1191
|
-
return b ^ rotl(b, 13) ^ rotl(b, 23);
|
1192
|
-
}
|
1193
1199
|
var x = new Uint32Array(4);
|
1194
1200
|
var tmp = new Uint32Array(4);
|
1195
1201
|
function sms4Crypt(input, output, roundKey) {
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1202
|
+
let x0 = 0, x1 = 0, x2 = 0, x3 = 0, tmp0 = 0, tmp1 = 0, tmp2 = 0, tmp3 = 0;
|
1203
|
+
tmp0 = input[0] & 255;
|
1204
|
+
tmp1 = input[1] & 255;
|
1205
|
+
tmp2 = input[2] & 255;
|
1206
|
+
tmp3 = input[3] & 255;
|
1207
|
+
x0 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
|
1208
|
+
tmp0 = input[4] & 255;
|
1209
|
+
tmp1 = input[5] & 255;
|
1210
|
+
tmp2 = input[6] & 255;
|
1211
|
+
tmp3 = input[7] & 255;
|
1212
|
+
x1 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
|
1213
|
+
tmp0 = input[8] & 255;
|
1214
|
+
tmp1 = input[9] & 255;
|
1215
|
+
tmp2 = input[10] & 255;
|
1216
|
+
tmp3 = input[11] & 255;
|
1217
|
+
x2 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
|
1218
|
+
tmp0 = input[12] & 255;
|
1219
|
+
tmp1 = input[13] & 255;
|
1220
|
+
tmp2 = input[14] & 255;
|
1221
|
+
tmp3 = input[15] & 255;
|
1222
|
+
x3 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
|
1223
|
+
for (let r = 0; r < 32; r += 4) {
|
1224
|
+
tmp0 = x1 ^ x2 ^ x3 ^ roundKey[r];
|
1225
|
+
tmp0 = byteSub(tmp0);
|
1226
|
+
x0 ^= tmp0 ^ (tmp0 << 2 | tmp0 >>> 30) ^ (tmp0 << 10 | tmp0 >>> 22) ^ (tmp0 << 18 | tmp0 >>> 14) ^ (tmp0 << 24 | tmp0 >>> 8);
|
1227
|
+
tmp1 = x2 ^ x3 ^ x0 ^ roundKey[r + 1];
|
1228
|
+
tmp1 = byteSub(tmp1);
|
1229
|
+
x1 ^= tmp1 ^ (tmp1 << 2 | tmp1 >>> 30) ^ (tmp1 << 10 | tmp1 >>> 22) ^ (tmp1 << 18 | tmp1 >>> 14) ^ (tmp1 << 24 | tmp1 >>> 8);
|
1230
|
+
tmp2 = x3 ^ x0 ^ x1 ^ roundKey[r + 2];
|
1231
|
+
tmp2 = byteSub(tmp2);
|
1232
|
+
x2 ^= tmp2 ^ (tmp2 << 2 | tmp2 >>> 30) ^ (tmp2 << 10 | tmp2 >>> 22) ^ (tmp2 << 18 | tmp2 >>> 14) ^ (tmp2 << 24 | tmp2 >>> 8);
|
1233
|
+
tmp3 = x0 ^ x1 ^ x2 ^ roundKey[r + 3];
|
1234
|
+
tmp3 = byteSub(tmp3);
|
1235
|
+
x3 ^= tmp3 ^ (tmp3 << 2 | tmp3 >>> 30) ^ (tmp3 << 10 | tmp3 >>> 22) ^ (tmp3 << 18 | tmp3 >>> 14) ^ (tmp3 << 24 | tmp3 >>> 8);
|
1218
1236
|
}
|
1237
|
+
output[0] = x3 >>> 24 & 255;
|
1238
|
+
output[1] = x3 >>> 16 & 255;
|
1239
|
+
output[2] = x3 >>> 8 & 255;
|
1240
|
+
output[3] = x3 & 255;
|
1241
|
+
output[4] = x2 >>> 24 & 255;
|
1242
|
+
output[5] = x2 >>> 16 & 255;
|
1243
|
+
output[6] = x2 >>> 8 & 255;
|
1244
|
+
output[7] = x2 & 255;
|
1245
|
+
output[8] = x1 >>> 24 & 255;
|
1246
|
+
output[9] = x1 >>> 16 & 255;
|
1247
|
+
output[10] = x1 >>> 8 & 255;
|
1248
|
+
output[11] = x1 & 255;
|
1249
|
+
output[12] = x0 >>> 24 & 255;
|
1250
|
+
output[13] = x0 >>> 16 & 255;
|
1251
|
+
output[14] = x0 >>> 8 & 255;
|
1252
|
+
output[15] = x0 & 255;
|
1219
1253
|
}
|
1220
1254
|
function sms4KeyExt(key, roundKey, cryptFlag) {
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
roundKey[r + 0] =
|
1235
|
-
mid =
|
1236
|
-
|
1237
|
-
|
1238
|
-
roundKey[r +
|
1239
|
-
mid =
|
1240
|
-
|
1255
|
+
let x0 = 0, x1 = 0, x2 = 0, x3 = 0, mid = 0;
|
1256
|
+
x0 = (key[0] & 255) << 24 | (key[1] & 255) << 16 | (key[2] & 255) << 8 | key[3] & 255;
|
1257
|
+
x1 = (key[4] & 255) << 24 | (key[5] & 255) << 16 | (key[6] & 255) << 8 | key[7] & 255;
|
1258
|
+
x2 = (key[8] & 255) << 24 | (key[9] & 255) << 16 | (key[10] & 255) << 8 | key[11] & 255;
|
1259
|
+
x3 = (key[12] & 255) << 24 | (key[13] & 255) << 16 | (key[14] & 255) << 8 | key[15] & 255;
|
1260
|
+
x0 ^= 2746333894;
|
1261
|
+
x1 ^= 1453994832;
|
1262
|
+
x2 ^= 1736282519;
|
1263
|
+
x3 ^= 2993693404;
|
1264
|
+
for (let r = 0; r < 32; r += 4) {
|
1265
|
+
mid = x1 ^ x2 ^ x3 ^ CK[r + 0];
|
1266
|
+
mid = byteSub(mid);
|
1267
|
+
x0 ^= mid ^ (mid << 13 | mid >>> 19) ^ (mid << 23 | mid >>> 9);
|
1268
|
+
roundKey[r + 0] = x0;
|
1269
|
+
mid = x2 ^ x3 ^ x0 ^ CK[r + 1];
|
1270
|
+
mid = byteSub(mid);
|
1271
|
+
x1 ^= mid ^ (mid << 13 | mid >>> 19) ^ (mid << 23 | mid >>> 9);
|
1272
|
+
roundKey[r + 1] = x1;
|
1273
|
+
mid = x3 ^ x0 ^ x1 ^ CK[r + 2];
|
1274
|
+
mid = byteSub(mid);
|
1275
|
+
x2 ^= mid ^ (mid << 13 | mid >>> 19) ^ (mid << 23 | mid >>> 9);
|
1276
|
+
roundKey[r + 2] = x2;
|
1277
|
+
mid = x0 ^ x1 ^ x2 ^ CK[r + 3];
|
1278
|
+
mid = byteSub(mid);
|
1279
|
+
x3 ^= mid ^ (mid << 13 | mid >>> 19) ^ (mid << 23 | mid >>> 9);
|
1280
|
+
roundKey[r + 3] = x3;
|
1241
1281
|
}
|
1242
1282
|
if (cryptFlag === DECRYPT) {
|
1243
|
-
for (let r = 0
|
1244
|
-
|
1245
|
-
roundKey[r] = roundKey[31 - r];
|
1246
|
-
roundKey[31 - r] = mid;
|
1283
|
+
for (let r = 0; r < 16; r++) {
|
1284
|
+
[roundKey[r], roundKey[31 - r]] = [roundKey[31 - r], roundKey[r]];
|
1247
1285
|
}
|
1248
1286
|
}
|
1249
1287
|
}
|
package/package.json
CHANGED
package/src/sm2/index.ts
CHANGED
@@ -209,10 +209,7 @@ export function doVerifySignature(msg: string | Uint8Array, signHex: string, pub
|
|
209
209
|
return r === R
|
210
210
|
}
|
211
211
|
|
212
|
-
|
213
|
-
* sm3杂凑算法
|
214
|
-
*/
|
215
|
-
export function getHash(hashHex: string | Uint8Array, publicKey: string, userId = '1234567812345678') {
|
212
|
+
export function getZ(publicKey: string, userId = '1234567812345678') {
|
216
213
|
// z = hash(entl || userId || a || b || gx || gy || px || py)
|
217
214
|
userId = utf8ToHex(userId)
|
218
215
|
const a = leftPad(utils.numberToHexUnpadded(sm2Curve.CURVE.a), 64)
|
@@ -241,6 +238,14 @@ export function getHash(hashHex: string | Uint8Array, publicKey: string, userId
|
|
241
238
|
|
242
239
|
const z = sm3(utils.concatBytes(new Uint8Array([entl >> 8 & 0x00ff, entl & 0x00ff]), data))
|
243
240
|
|
241
|
+
return z
|
242
|
+
}
|
243
|
+
|
244
|
+
/**
|
245
|
+
* sm3杂凑算法
|
246
|
+
*/
|
247
|
+
export function getHash(hashHex: string | Uint8Array, publicKey: string, userId = '1234567812345678') {
|
248
|
+
const z = getZ(publicKey, userId)
|
244
249
|
// e = hash(z || msg)
|
245
250
|
return bytesToHex(sm3(utils.concatBytes(z, typeof hashHex === 'string' ? hexToArray(hashHex) : hashHex)))
|
246
251
|
}
|
package/src/sm2/kx.ts
CHANGED
@@ -2,7 +2,7 @@ import { field, sm2Curve } from './ec';
|
|
2
2
|
import { KeyPair, hexToArray, leftPad } from './utils';
|
3
3
|
import * as utils from '@noble/curves/abstract/utils';
|
4
4
|
import { sm3 } from './sm3';
|
5
|
-
import { EmptyArray } from '.';
|
5
|
+
import { EmptyArray, getZ } from '.';
|
6
6
|
|
7
7
|
|
8
8
|
// 用到的常数
|
@@ -39,28 +39,31 @@ function hkdf(z: Uint8Array, keylen: number) {
|
|
39
39
|
return msg
|
40
40
|
}
|
41
41
|
|
42
|
-
|
43
42
|
export function calculateSharedKey(
|
44
43
|
keypairA: KeyPair,
|
45
44
|
ephemeralKeypairA: KeyPair,
|
46
45
|
publicKeyB: string,
|
47
46
|
ephemeralPublicKeyB: string,
|
47
|
+
sharedKeyLength: number,
|
48
|
+
isRecipient = false,
|
48
49
|
idA: string = '1234567812345678',
|
49
50
|
idB: string = '1234567812345678',
|
50
|
-
sharedKeyLength: number,
|
51
51
|
) {
|
52
52
|
const RA = sm2Curve.ProjectivePoint.fromHex(ephemeralKeypairA.publicKey)
|
53
53
|
const RB = sm2Curve.ProjectivePoint.fromHex(ephemeralPublicKeyB)
|
54
54
|
// const PA = sm2Curve.ProjectivePoint.fromHex(keypairA.publicKey) // 用不到
|
55
55
|
const PB = sm2Curve.ProjectivePoint.fromHex(publicKeyB)
|
56
|
-
|
57
|
-
|
56
|
+
let ZA = getZ(keypairA.publicKey, idA)
|
57
|
+
let ZB = getZ(publicKeyB, idB)
|
58
|
+
if (isRecipient) {
|
59
|
+
[ZA, ZB] = [ZB, ZA];
|
60
|
+
}
|
58
61
|
const rA = utils.hexToNumber(ephemeralKeypairA.privateKey)
|
59
62
|
const dA = utils.hexToNumber(keypairA.privateKey)
|
60
63
|
// 1.先算 tA
|
61
64
|
const x1 = RA.x
|
62
65
|
// x1_ = 2^w + (x1 & (2^w - 1))
|
63
|
-
const x1_ =
|
66
|
+
const x1_ = wPow2 + (x1 & wPow2Sub1)
|
64
67
|
// tA = (dA + x1b * rA) mod n
|
65
68
|
const tA = field.add(dA, field.mulN(x1_, rA))
|
66
69
|
|