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 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
- - 🔑 新增密钥交换 API(实验性)
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
- // A 所需参数:A 的秘钥对,A 的临时秘钥对,B 的公钥,B 的临时秘钥公钥,AB 的身份ID,长度
181
- const sharedKeyFromA = sm2.calculateSharedKey(keyPairA, ephemeralKeypairA, keyPairB.publicKey, ephemeralKeypairB.publicKey, 'alice@yahoo.com', 'bob@yahoo.com', 233)
182
- // B 所需参数:B 的秘钥对,B 的临时秘钥对,A 的公钥,A 的临时秘钥公钥,AB 的身份ID,长度
183
- const sharedKeyFromB = sm2.calculateSharedKey(keyPairB, ephemeralKeypairB, keyPairA.publicKey, ephemeralKeypairA.publicKey, 'alice@yahoo.com', 'bob@yahoo.com', 233)
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, idA: string | undefined, idB: string | undefined, sharedKeyLength: number): Uint8Array;
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
- const crypto = await import(
212
- /* webpackIgnore: true */
213
- "crypto"
214
- );
215
- _syncCrypto = crypto.webcrypto;
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", sharedKeyLength) {
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
- const ZA = hexToArray(idA);
687
- const ZB = hexToArray(idB);
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_ = field.add(wPow2, x1 & wPow2Sub1);
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 getHash(hashHex, publicKey, userId = "1234567812345678") {
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
- for (let i = 0; i < 4; i++) {
1225
- tmp[0] = input[4 * i] & 255;
1226
- tmp[1] = input[4 * i + 1] & 255;
1227
- tmp[2] = input[4 * i + 2] & 255;
1228
- tmp[3] = input[4 * i + 3] & 255;
1229
- x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
1230
- }
1231
- for (let r = 0, mid; r < 32; r += 4) {
1232
- mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0];
1233
- x[0] ^= l1(byteSub(mid));
1234
- mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1];
1235
- x[1] ^= l1(byteSub(mid));
1236
- mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2];
1237
- x[2] ^= l1(byteSub(mid));
1238
- mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3];
1239
- x[3] ^= l1(byteSub(mid));
1240
- }
1241
- for (let j = 0; j < 16; j += 4) {
1242
- output[j] = x[3 - j / 4] >>> 24 & 255;
1243
- output[j + 1] = x[3 - j / 4] >>> 16 & 255;
1244
- output[j + 2] = x[3 - j / 4] >>> 8 & 255;
1245
- output[j + 3] = x[3 - j / 4] & 255;
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
- for (let i = 0; i < 4; i++) {
1250
- tmp[0] = key[0 + 4 * i] & 255;
1251
- tmp[1] = key[1 + 4 * i] & 255;
1252
- tmp[2] = key[2 + 4 * i] & 255;
1253
- tmp[3] = key[3 + 4 * i] & 255;
1254
- x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
1255
- }
1256
- x[0] ^= 2746333894;
1257
- x[1] ^= 1453994832;
1258
- x[2] ^= 1736282519;
1259
- x[3] ^= 2993693404;
1260
- for (let r = 0, mid; r < 32; r += 4) {
1261
- mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0];
1262
- roundKey[r + 0] = x[0] ^= l2(byteSub(mid));
1263
- mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1];
1264
- roundKey[r + 1] = x[1] ^= l2(byteSub(mid));
1265
- mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2];
1266
- roundKey[r + 2] = x[2] ^= l2(byteSub(mid));
1267
- mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3];
1268
- roundKey[r + 3] = x[3] ^= l2(byteSub(mid));
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, mid; r < 16; r++) {
1272
- mid = roundKey[r];
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
- const crypto = await import(
184
- /* webpackIgnore: true */
185
- "crypto"
186
- );
187
- _syncCrypto = crypto.webcrypto;
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", sharedKeyLength) {
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
- const ZA = hexToArray(idA);
659
- const ZB = hexToArray(idB);
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_ = field.add(wPow2, x1 & wPow2Sub1);
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 getHash(hashHex, publicKey, userId = "1234567812345678") {
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
- for (let i = 0; i < 4; i++) {
1197
- tmp[0] = input[4 * i] & 255;
1198
- tmp[1] = input[4 * i + 1] & 255;
1199
- tmp[2] = input[4 * i + 2] & 255;
1200
- tmp[3] = input[4 * i + 3] & 255;
1201
- x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
1202
- }
1203
- for (let r = 0, mid; r < 32; r += 4) {
1204
- mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0];
1205
- x[0] ^= l1(byteSub(mid));
1206
- mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1];
1207
- x[1] ^= l1(byteSub(mid));
1208
- mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2];
1209
- x[2] ^= l1(byteSub(mid));
1210
- mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3];
1211
- x[3] ^= l1(byteSub(mid));
1212
- }
1213
- for (let j = 0; j < 16; j += 4) {
1214
- output[j] = x[3 - j / 4] >>> 24 & 255;
1215
- output[j + 1] = x[3 - j / 4] >>> 16 & 255;
1216
- output[j + 2] = x[3 - j / 4] >>> 8 & 255;
1217
- output[j + 3] = x[3 - j / 4] & 255;
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
- for (let i = 0; i < 4; i++) {
1222
- tmp[0] = key[0 + 4 * i] & 255;
1223
- tmp[1] = key[1 + 4 * i] & 255;
1224
- tmp[2] = key[2 + 4 * i] & 255;
1225
- tmp[3] = key[3 + 4 * i] & 255;
1226
- x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
1227
- }
1228
- x[0] ^= 2746333894;
1229
- x[1] ^= 1453994832;
1230
- x[2] ^= 1736282519;
1231
- x[3] ^= 2993693404;
1232
- for (let r = 0, mid; r < 32; r += 4) {
1233
- mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0];
1234
- roundKey[r + 0] = x[0] ^= l2(byteSub(mid));
1235
- mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1];
1236
- roundKey[r + 1] = x[1] ^= l2(byteSub(mid));
1237
- mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2];
1238
- roundKey[r + 2] = x[2] ^= l2(byteSub(mid));
1239
- mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3];
1240
- roundKey[r + 3] = x[3] ^= l2(byteSub(mid));
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, mid; r < 16; r++) {
1244
- mid = roundKey[r];
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sm-crypto-v2",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "sm-crypto-v2",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
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
- const ZA = hexToArray(idA)
57
- const ZB = hexToArray(idB)
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_ = field.add(wPow2, (x1 & wPow2Sub1))
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