sm-crypto-v2 1.3.0 → 1.4.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 +7 -0
- package/README.md +25 -7
- package/dist/index.d.ts +11 -4
- package/dist/index.js +67 -20
- package/dist/index.mjs +67 -20
- package/package.json +1 -1
- package/src/sm2/index.ts +1 -0
- package/src/sm2/kx.ts +76 -0
- package/src/sm2/utils.ts +6 -1
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@
|
|
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.4.0](https://github.com/Cubelrti/sm-crypto-v2/compare/v1.3.0...v1.4.0) (2023-06-09)
|
6
|
+
|
7
|
+
|
8
|
+
### Features
|
9
|
+
|
10
|
+
* **sm2:** add experimental key agreement ([cdd00b4](https://github.com/Cubelrti/sm-crypto-v2/commit/cdd00b4e42bb5072e1dcb6e0301b6a2f18f53614))
|
11
|
+
|
5
12
|
## [1.3.0](https://github.com/Cubelrti/sm-crypto-v2/compare/v1.2.2...v1.3.0) (2023-06-07)
|
6
13
|
|
7
14
|
|
package/README.md
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
# sm-crypto-v2
|
2
2
|
|
3
|
-
[](https://
|
3
|
+
[](https://www.npmjs.com/package/sm-crypto-v2)
|
4
4
|
[](https://github.com/cubelrti/sm-crypto-v2/actions)
|
5
5
|
[](https://github.com/cubelrti/sm-crypto-v2/actions)
|
6
6
|
|
7
|
-
|
8
7
|
国密算法 sm2、sm3 和 sm4 的 TypeScript 实现。参数支持 TypedArray,导出 esm/cjs。
|
9
8
|
|
10
9
|
## 特性
|
11
10
|
|
12
|
-
-
|
13
|
-
-
|
14
|
-
- 移除原有 `jsbn` 依赖,改用原生 BigInt
|
15
|
-
-
|
16
|
-
-
|
11
|
+
- ⚡ 基于 [`noble-curves` Abstract API](https://github.com/paulmillr/noble-curves#abstract-api) 重构 SM2,性能提升近4倍。详见 [noble-curves 文档](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/)
|
12
|
+
- 📘 使用 TypeScript 实现,提供全面的类型支持
|
13
|
+
- 🔄 移除原有 `jsbn` 依赖,改用原生 BigInt
|
14
|
+
- ✔️ 通过全部历史单元测试,包括 SM2、SM3 和 SM4
|
15
|
+
- 🎲 自动选择最优的安全随机数实现,避免使用 `Math.random` 和 `Date.now` 进行模拟
|
16
|
+
- 📚 同时导出 ES Module 和 CommonJS 两种格式,可按需使用
|
17
17
|
|
18
18
|
## 安装
|
19
19
|
|
@@ -163,6 +163,24 @@ let decryptData = sm4.decrypt(encryptData, key, {padding: 'none', output: 'array
|
|
163
163
|
let decryptData = sm4.decrypt(encryptData, key, {mode: 'cbc', iv: 'fedcba98765432100123456789abcdef'}) // 解密,cbc 模式
|
164
164
|
```
|
165
165
|
|
166
|
+
### 密钥交换(实验性)
|
167
|
+
|
168
|
+
```js
|
169
|
+
import { sm2 } from 'sm-crypto-v2'
|
170
|
+
|
171
|
+
const keyPairA = sm2.generateKeyPairHex() // A 的秘钥对
|
172
|
+
const keyPairB = sm2.generateKeyPairHex() // B 的秘钥对
|
173
|
+
const ephemeralKeypairA = sm2.generateKeyPairHex() // A 的临时秘钥对
|
174
|
+
const ephemeralKeypairB = sm2.generateKeyPairHex() // B 的临时秘钥对
|
175
|
+
|
176
|
+
// A 所需参数:A 的秘钥对,A 的临时秘钥对,B 的公钥,B 的临时秘钥公钥,AB 的身份ID,长度
|
177
|
+
const sharedKeyFromA = sm2.calculateSharedKey(keyPairA, ephemeralKeypairA, keyPairB.publicKey, ephemeralKeypairB.publicKey, undefined, undefined, 233)
|
178
|
+
// A 所需参数:B 的秘钥对,B 的临时秘钥对,A 的公钥,A 的临时秘钥公钥,AB 的身份ID,长度
|
179
|
+
const sharedKeyFromB = sm2.calculateSharedKey(keyPairB, ephemeralKeypairB, keyPairA.publicKey, ephemeralKeypairA.publicKey, undefined, undefined, 233)
|
180
|
+
|
181
|
+
// expect(sharedKeyFromA).toEqual(sharedKeyFromB) => true
|
182
|
+
```
|
183
|
+
|
166
184
|
## 其他实现
|
167
185
|
|
168
186
|
* 原 js 版本:[https://github.com/JuneAndGreen/sm-crypto](https://github.com/JuneAndGreen/sm-crypto)
|
package/dist/index.d.ts
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
interface KeyPair {
|
2
|
+
privateKey: string;
|
3
|
+
publicKey: string;
|
4
|
+
}
|
1
5
|
/**
|
2
6
|
* 生成密钥对:publicKey = privateKey * G
|
3
7
|
*/
|
4
|
-
declare function generateKeyPairHex(str?: string):
|
5
|
-
privateKey: string;
|
6
|
-
publicKey: string;
|
7
|
-
};
|
8
|
+
declare function generateKeyPairHex(str?: string): KeyPair;
|
8
9
|
/**
|
9
10
|
* 生成压缩公钥
|
10
11
|
*/
|
@@ -41,6 +42,8 @@ declare function concatArray(...arrays: Uint8Array[]): Uint8Array;
|
|
41
42
|
|
42
43
|
declare function initRNGPool(): Promise<void>;
|
43
44
|
|
45
|
+
declare function calculateSharedKey(keypairA: KeyPair, ephemeralKeypairA: KeyPair, publicKeyB: string, ephemeralPublicKeyB: string, idA: string | undefined, idB: string | undefined, sharedKeyLength: number): Uint8Array;
|
46
|
+
|
44
47
|
/**
|
45
48
|
* 加密
|
46
49
|
*/
|
@@ -103,6 +106,8 @@ declare const index$2_getHash: typeof getHash;
|
|
103
106
|
declare const index$2_getPublicKeyFromPrivateKey: typeof getPublicKeyFromPrivateKey;
|
104
107
|
declare const index$2_getPoint: typeof getPoint;
|
105
108
|
declare const index$2_initRNGPool: typeof initRNGPool;
|
109
|
+
declare const index$2_calculateSharedKey: typeof calculateSharedKey;
|
110
|
+
type index$2_KeyPair = KeyPair;
|
106
111
|
declare const index$2_generateKeyPairHex: typeof generateKeyPairHex;
|
107
112
|
declare const index$2_compressPublicKeyHex: typeof compressPublicKeyHex;
|
108
113
|
declare const index$2_utf8ToHex: typeof utf8ToHex;
|
@@ -124,6 +129,8 @@ declare namespace index$2 {
|
|
124
129
|
index$2_getPublicKeyFromPrivateKey as getPublicKeyFromPrivateKey,
|
125
130
|
index$2_getPoint as getPoint,
|
126
131
|
index$2_initRNGPool as initRNGPool,
|
132
|
+
index$2_calculateSharedKey as calculateSharedKey,
|
133
|
+
index$2_KeyPair as KeyPair,
|
127
134
|
index$2_generateKeyPairHex as generateKeyPairHex,
|
128
135
|
index$2_compressPublicKeyHex as compressPublicKeyHex,
|
129
136
|
index$2_utf8ToHex as utf8ToHex,
|
package/dist/index.js
CHANGED
@@ -37,6 +37,7 @@ var sm2_exports = {};
|
|
37
37
|
__export(sm2_exports, {
|
38
38
|
arrayToHex: () => arrayToHex,
|
39
39
|
arrayToUtf8: () => arrayToUtf8,
|
40
|
+
calculateSharedKey: () => calculateSharedKey,
|
40
41
|
comparePublicKeyHex: () => comparePublicKeyHex,
|
41
42
|
compressPublicKeyHex: () => compressPublicKeyHex,
|
42
43
|
concatArray: () => concatArray,
|
@@ -544,19 +545,65 @@ function concatArray(...arrays) {
|
|
544
545
|
|
545
546
|
// src/sm2/index.ts
|
546
547
|
var mod2 = __toESM(require("@noble/curves/abstract/modular"));
|
548
|
+
var utils4 = __toESM(require("@noble/curves/abstract/utils"));
|
549
|
+
|
550
|
+
// src/sm2/kx.ts
|
547
551
|
var utils3 = __toESM(require("@noble/curves/abstract/utils"));
|
552
|
+
var import_modular3 = require("@noble/curves/abstract/modular");
|
553
|
+
var field = (0, import_modular3.Field)(BigInt(sm2Curve.CURVE.n));
|
554
|
+
var wPow2 = utils3.hexToNumber("80000000000000000000000000000000");
|
555
|
+
var wPow2Sub1 = utils3.hexToNumber("7fffffffffffffffffffffffffffffff");
|
556
|
+
function hkdf(z, keylen) {
|
557
|
+
let t = new Uint8Array();
|
558
|
+
let msg = new Uint8Array(keylen);
|
559
|
+
let ct = 1;
|
560
|
+
let offset = 0;
|
561
|
+
const nextT = () => {
|
562
|
+
t = sm3(Uint8Array.from([...z, ct >> 24 & 255, ct >> 16 & 255, ct >> 8 & 255, ct & 255]));
|
563
|
+
ct++;
|
564
|
+
offset = 0;
|
565
|
+
};
|
566
|
+
nextT();
|
567
|
+
for (let i = 0, len = msg.length; i < len; i++) {
|
568
|
+
if (offset === t.length)
|
569
|
+
nextT();
|
570
|
+
msg[i] = t[offset++] & 255;
|
571
|
+
}
|
572
|
+
return msg;
|
573
|
+
}
|
574
|
+
function calculateSharedKey(keypairA, ephemeralKeypairA, publicKeyB, ephemeralPublicKeyB, idA = "1234567812345678", idB = "1234567812345678", sharedKeyLength) {
|
575
|
+
const RA = sm2Curve.ProjectivePoint.fromHex(ephemeralKeypairA.publicKey);
|
576
|
+
const RB = sm2Curve.ProjectivePoint.fromHex(ephemeralPublicKeyB);
|
577
|
+
const PB = sm2Curve.ProjectivePoint.fromHex(publicKeyB);
|
578
|
+
const ZA = hexToArray(idA);
|
579
|
+
const ZB = hexToArray(idB);
|
580
|
+
const rA = utils3.hexToNumber(ephemeralKeypairA.privateKey);
|
581
|
+
const dA = utils3.hexToNumber(keypairA.privateKey);
|
582
|
+
const x1 = RA.x;
|
583
|
+
const x1_ = field.add(wPow2, x1 & wPow2Sub1);
|
584
|
+
const tA = field.add(dA, field.mul(x1_, rA));
|
585
|
+
const x2 = RB.x;
|
586
|
+
const x2_ = field.add(wPow2, x2 & wPow2Sub1);
|
587
|
+
const U = RB.multiply(x2_).add(PB).multiply(tA);
|
588
|
+
const xU = hexToArray(leftPad2(utils3.numberToHexUnpadded(U.x), 64));
|
589
|
+
const yU = hexToArray(leftPad2(utils3.numberToHexUnpadded(U.y), 64));
|
590
|
+
const KA = hkdf(concatArray(xU, yU, ZA, ZB), sharedKeyLength);
|
591
|
+
return KA;
|
592
|
+
}
|
593
|
+
|
594
|
+
// src/sm2/index.ts
|
548
595
|
var C1C2C3 = 0;
|
549
596
|
function doEncrypt(msg, publicKey, cipherMode = 1) {
|
550
597
|
const msgArr = typeof msg === "string" ? hexToArray(utf8ToHex(msg)) : Uint8Array.from(msg);
|
551
598
|
const publicKeyPoint = sm2Curve.ProjectivePoint.fromHex(publicKey);
|
552
599
|
const keypair = generateKeyPairHex();
|
553
|
-
const k =
|
600
|
+
const k = utils4.hexToNumber(keypair.privateKey);
|
554
601
|
let c1 = keypair.publicKey;
|
555
602
|
if (c1.length > 128)
|
556
603
|
c1 = c1.substring(c1.length - 128);
|
557
604
|
const p = publicKeyPoint.multiply(k);
|
558
|
-
const x2 = hexToArray(leftPad2(
|
559
|
-
const y2 = hexToArray(leftPad2(
|
605
|
+
const x2 = hexToArray(leftPad2(utils4.numberToHexUnpadded(p.x), 64));
|
606
|
+
const y2 = hexToArray(leftPad2(utils4.numberToHexUnpadded(p.y), 64));
|
560
607
|
const c3 = arrayToHex(Array.from(sm3(concatArray(x2, msgArr, y2))));
|
561
608
|
let ct = 1;
|
562
609
|
let offset = 0;
|
@@ -579,7 +626,7 @@ function doEncrypt(msg, publicKey, cipherMode = 1) {
|
|
579
626
|
function doDecrypt(encryptData, privateKey, cipherMode = 1, {
|
580
627
|
output = "string"
|
581
628
|
} = {}) {
|
582
|
-
const privateKeyInteger =
|
629
|
+
const privateKeyInteger = utils4.hexToNumber(privateKey);
|
583
630
|
let c3 = encryptData.substring(128, 128 + 64);
|
584
631
|
let c2 = encryptData.substring(128 + 64);
|
585
632
|
if (cipherMode === C1C2C3) {
|
@@ -589,8 +636,8 @@ function doDecrypt(encryptData, privateKey, cipherMode = 1, {
|
|
589
636
|
const msg = hexToArray(c2);
|
590
637
|
const c1 = sm2Curve.ProjectivePoint.fromHex("04" + encryptData.substring(0, 128));
|
591
638
|
const p = c1.multiply(privateKeyInteger);
|
592
|
-
const x2 = hexToArray(leftPad2(
|
593
|
-
const y2 = hexToArray(leftPad2(
|
639
|
+
const x2 = hexToArray(leftPad2(utils4.numberToHexUnpadded(p.x), 64));
|
640
|
+
const y2 = hexToArray(leftPad2(utils4.numberToHexUnpadded(p.y), 64));
|
594
641
|
let ct = 1;
|
595
642
|
let offset = 0;
|
596
643
|
let t = new Uint8Array();
|
@@ -626,8 +673,8 @@ function doSignature(msg, privateKey, options = {}) {
|
|
626
673
|
publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey);
|
627
674
|
hashHex = getHash(hashHex, publicKey, userId);
|
628
675
|
}
|
629
|
-
const dA =
|
630
|
-
const e =
|
676
|
+
const dA = utils4.hexToNumber(privateKey);
|
677
|
+
const e = utils4.hexToNumber(hashHex);
|
631
678
|
let k = null;
|
632
679
|
let r = null;
|
633
680
|
let s = null;
|
@@ -646,7 +693,7 @@ function doSignature(msg, privateKey, options = {}) {
|
|
646
693
|
} while (s === ZERO);
|
647
694
|
if (der)
|
648
695
|
return encodeDer(r, s);
|
649
|
-
return leftPad2(
|
696
|
+
return leftPad2(utils4.numberToHexUnpadded(r), 64) + leftPad2(utils4.numberToHexUnpadded(s), 64);
|
650
697
|
}
|
651
698
|
function doVerifySignature(msg, signHex, publicKey, options = {}) {
|
652
699
|
let hashHex;
|
@@ -667,11 +714,11 @@ function doVerifySignature(msg, signHex, publicKey, options = {}) {
|
|
667
714
|
r = decodeDerObj.r;
|
668
715
|
s = decodeDerObj.s;
|
669
716
|
} else {
|
670
|
-
r =
|
671
|
-
s =
|
717
|
+
r = utils4.hexToNumber(signHex.substring(0, 64));
|
718
|
+
s = utils4.hexToNumber(signHex.substring(64));
|
672
719
|
}
|
673
720
|
const PA = sm2Curve.ProjectivePoint.fromHex(publicKey);
|
674
|
-
const e =
|
721
|
+
const e = utils4.hexToNumber(hashHex);
|
675
722
|
const t = mod2.mod(r + s, sm2Curve.CURVE.n);
|
676
723
|
if (t === ZERO)
|
677
724
|
return false;
|
@@ -681,10 +728,10 @@ function doVerifySignature(msg, signHex, publicKey, options = {}) {
|
|
681
728
|
}
|
682
729
|
function getHash(hashHex, publicKey, userId = "1234567812345678") {
|
683
730
|
userId = utf8ToHex(userId);
|
684
|
-
const a = leftPad2(
|
685
|
-
const b = leftPad2(
|
686
|
-
const gx = leftPad2(
|
687
|
-
const gy = leftPad2(
|
731
|
+
const a = leftPad2(utils4.numberToHexUnpadded(sm2Curve.CURVE.a), 64);
|
732
|
+
const b = leftPad2(utils4.numberToHexUnpadded(sm2Curve.CURVE.b), 64);
|
733
|
+
const gx = leftPad2(utils4.numberToHexUnpadded(sm2Curve.ProjectivePoint.BASE.x), 64);
|
734
|
+
const gy = leftPad2(utils4.numberToHexUnpadded(sm2Curve.ProjectivePoint.BASE.y), 64);
|
688
735
|
let px;
|
689
736
|
let py;
|
690
737
|
if (publicKey.length === 128) {
|
@@ -692,8 +739,8 @@ function getHash(hashHex, publicKey, userId = "1234567812345678") {
|
|
692
739
|
py = publicKey.substring(64, 128);
|
693
740
|
} else {
|
694
741
|
const point = sm2Curve.ProjectivePoint.fromHex(publicKey);
|
695
|
-
px = leftPad2(
|
696
|
-
py = leftPad2(
|
742
|
+
px = leftPad2(utils4.numberToHexUnpadded(point.x), 64);
|
743
|
+
py = leftPad2(utils4.numberToHexUnpadded(point.y), 64);
|
697
744
|
}
|
698
745
|
const data = hexToArray(userId + a + b + gx + gy + px + py);
|
699
746
|
const entl = userId.length * 4;
|
@@ -702,13 +749,13 @@ function getHash(hashHex, publicKey, userId = "1234567812345678") {
|
|
702
749
|
}
|
703
750
|
function getPublicKeyFromPrivateKey(privateKey) {
|
704
751
|
const pubKey = sm2Curve.getPublicKey(privateKey, false);
|
705
|
-
const pubPad = leftPad2(
|
752
|
+
const pubPad = leftPad2(utils4.bytesToHex(pubKey), 64);
|
706
753
|
return pubPad;
|
707
754
|
}
|
708
755
|
function getPoint() {
|
709
756
|
const keypair = generateKeyPairHex();
|
710
757
|
const PA = sm2Curve.ProjectivePoint.fromHex(keypair.publicKey);
|
711
|
-
const k =
|
758
|
+
const k = utils4.hexToNumber(keypair.privateKey);
|
712
759
|
return {
|
713
760
|
...keypair,
|
714
761
|
k,
|
package/dist/index.mjs
CHANGED
@@ -9,6 +9,7 @@ var sm2_exports = {};
|
|
9
9
|
__export(sm2_exports, {
|
10
10
|
arrayToHex: () => arrayToHex,
|
11
11
|
arrayToUtf8: () => arrayToUtf8,
|
12
|
+
calculateSharedKey: () => calculateSharedKey,
|
12
13
|
comparePublicKeyHex: () => comparePublicKeyHex,
|
13
14
|
compressPublicKeyHex: () => compressPublicKeyHex,
|
14
15
|
concatArray: () => concatArray,
|
@@ -516,19 +517,65 @@ function concatArray(...arrays) {
|
|
516
517
|
|
517
518
|
// src/sm2/index.ts
|
518
519
|
import * as mod2 from "@noble/curves/abstract/modular";
|
520
|
+
import * as utils4 from "@noble/curves/abstract/utils";
|
521
|
+
|
522
|
+
// src/sm2/kx.ts
|
519
523
|
import * as utils3 from "@noble/curves/abstract/utils";
|
524
|
+
import { Field as Field2 } from "@noble/curves/abstract/modular";
|
525
|
+
var field = Field2(BigInt(sm2Curve.CURVE.n));
|
526
|
+
var wPow2 = utils3.hexToNumber("80000000000000000000000000000000");
|
527
|
+
var wPow2Sub1 = utils3.hexToNumber("7fffffffffffffffffffffffffffffff");
|
528
|
+
function hkdf(z, keylen) {
|
529
|
+
let t = new Uint8Array();
|
530
|
+
let msg = new Uint8Array(keylen);
|
531
|
+
let ct = 1;
|
532
|
+
let offset = 0;
|
533
|
+
const nextT = () => {
|
534
|
+
t = sm3(Uint8Array.from([...z, ct >> 24 & 255, ct >> 16 & 255, ct >> 8 & 255, ct & 255]));
|
535
|
+
ct++;
|
536
|
+
offset = 0;
|
537
|
+
};
|
538
|
+
nextT();
|
539
|
+
for (let i = 0, len = msg.length; i < len; i++) {
|
540
|
+
if (offset === t.length)
|
541
|
+
nextT();
|
542
|
+
msg[i] = t[offset++] & 255;
|
543
|
+
}
|
544
|
+
return msg;
|
545
|
+
}
|
546
|
+
function calculateSharedKey(keypairA, ephemeralKeypairA, publicKeyB, ephemeralPublicKeyB, idA = "1234567812345678", idB = "1234567812345678", sharedKeyLength) {
|
547
|
+
const RA = sm2Curve.ProjectivePoint.fromHex(ephemeralKeypairA.publicKey);
|
548
|
+
const RB = sm2Curve.ProjectivePoint.fromHex(ephemeralPublicKeyB);
|
549
|
+
const PB = sm2Curve.ProjectivePoint.fromHex(publicKeyB);
|
550
|
+
const ZA = hexToArray(idA);
|
551
|
+
const ZB = hexToArray(idB);
|
552
|
+
const rA = utils3.hexToNumber(ephemeralKeypairA.privateKey);
|
553
|
+
const dA = utils3.hexToNumber(keypairA.privateKey);
|
554
|
+
const x1 = RA.x;
|
555
|
+
const x1_ = field.add(wPow2, x1 & wPow2Sub1);
|
556
|
+
const tA = field.add(dA, field.mul(x1_, rA));
|
557
|
+
const x2 = RB.x;
|
558
|
+
const x2_ = field.add(wPow2, x2 & wPow2Sub1);
|
559
|
+
const U = RB.multiply(x2_).add(PB).multiply(tA);
|
560
|
+
const xU = hexToArray(leftPad2(utils3.numberToHexUnpadded(U.x), 64));
|
561
|
+
const yU = hexToArray(leftPad2(utils3.numberToHexUnpadded(U.y), 64));
|
562
|
+
const KA = hkdf(concatArray(xU, yU, ZA, ZB), sharedKeyLength);
|
563
|
+
return KA;
|
564
|
+
}
|
565
|
+
|
566
|
+
// src/sm2/index.ts
|
520
567
|
var C1C2C3 = 0;
|
521
568
|
function doEncrypt(msg, publicKey, cipherMode = 1) {
|
522
569
|
const msgArr = typeof msg === "string" ? hexToArray(utf8ToHex(msg)) : Uint8Array.from(msg);
|
523
570
|
const publicKeyPoint = sm2Curve.ProjectivePoint.fromHex(publicKey);
|
524
571
|
const keypair = generateKeyPairHex();
|
525
|
-
const k =
|
572
|
+
const k = utils4.hexToNumber(keypair.privateKey);
|
526
573
|
let c1 = keypair.publicKey;
|
527
574
|
if (c1.length > 128)
|
528
575
|
c1 = c1.substring(c1.length - 128);
|
529
576
|
const p = publicKeyPoint.multiply(k);
|
530
|
-
const x2 = hexToArray(leftPad2(
|
531
|
-
const y2 = hexToArray(leftPad2(
|
577
|
+
const x2 = hexToArray(leftPad2(utils4.numberToHexUnpadded(p.x), 64));
|
578
|
+
const y2 = hexToArray(leftPad2(utils4.numberToHexUnpadded(p.y), 64));
|
532
579
|
const c3 = arrayToHex(Array.from(sm3(concatArray(x2, msgArr, y2))));
|
533
580
|
let ct = 1;
|
534
581
|
let offset = 0;
|
@@ -551,7 +598,7 @@ function doEncrypt(msg, publicKey, cipherMode = 1) {
|
|
551
598
|
function doDecrypt(encryptData, privateKey, cipherMode = 1, {
|
552
599
|
output = "string"
|
553
600
|
} = {}) {
|
554
|
-
const privateKeyInteger =
|
601
|
+
const privateKeyInteger = utils4.hexToNumber(privateKey);
|
555
602
|
let c3 = encryptData.substring(128, 128 + 64);
|
556
603
|
let c2 = encryptData.substring(128 + 64);
|
557
604
|
if (cipherMode === C1C2C3) {
|
@@ -561,8 +608,8 @@ function doDecrypt(encryptData, privateKey, cipherMode = 1, {
|
|
561
608
|
const msg = hexToArray(c2);
|
562
609
|
const c1 = sm2Curve.ProjectivePoint.fromHex("04" + encryptData.substring(0, 128));
|
563
610
|
const p = c1.multiply(privateKeyInteger);
|
564
|
-
const x2 = hexToArray(leftPad2(
|
565
|
-
const y2 = hexToArray(leftPad2(
|
611
|
+
const x2 = hexToArray(leftPad2(utils4.numberToHexUnpadded(p.x), 64));
|
612
|
+
const y2 = hexToArray(leftPad2(utils4.numberToHexUnpadded(p.y), 64));
|
566
613
|
let ct = 1;
|
567
614
|
let offset = 0;
|
568
615
|
let t = new Uint8Array();
|
@@ -598,8 +645,8 @@ function doSignature(msg, privateKey, options = {}) {
|
|
598
645
|
publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey);
|
599
646
|
hashHex = getHash(hashHex, publicKey, userId);
|
600
647
|
}
|
601
|
-
const dA =
|
602
|
-
const e =
|
648
|
+
const dA = utils4.hexToNumber(privateKey);
|
649
|
+
const e = utils4.hexToNumber(hashHex);
|
603
650
|
let k = null;
|
604
651
|
let r = null;
|
605
652
|
let s = null;
|
@@ -618,7 +665,7 @@ function doSignature(msg, privateKey, options = {}) {
|
|
618
665
|
} while (s === ZERO);
|
619
666
|
if (der)
|
620
667
|
return encodeDer(r, s);
|
621
|
-
return leftPad2(
|
668
|
+
return leftPad2(utils4.numberToHexUnpadded(r), 64) + leftPad2(utils4.numberToHexUnpadded(s), 64);
|
622
669
|
}
|
623
670
|
function doVerifySignature(msg, signHex, publicKey, options = {}) {
|
624
671
|
let hashHex;
|
@@ -639,11 +686,11 @@ function doVerifySignature(msg, signHex, publicKey, options = {}) {
|
|
639
686
|
r = decodeDerObj.r;
|
640
687
|
s = decodeDerObj.s;
|
641
688
|
} else {
|
642
|
-
r =
|
643
|
-
s =
|
689
|
+
r = utils4.hexToNumber(signHex.substring(0, 64));
|
690
|
+
s = utils4.hexToNumber(signHex.substring(64));
|
644
691
|
}
|
645
692
|
const PA = sm2Curve.ProjectivePoint.fromHex(publicKey);
|
646
|
-
const e =
|
693
|
+
const e = utils4.hexToNumber(hashHex);
|
647
694
|
const t = mod2.mod(r + s, sm2Curve.CURVE.n);
|
648
695
|
if (t === ZERO)
|
649
696
|
return false;
|
@@ -653,10 +700,10 @@ function doVerifySignature(msg, signHex, publicKey, options = {}) {
|
|
653
700
|
}
|
654
701
|
function getHash(hashHex, publicKey, userId = "1234567812345678") {
|
655
702
|
userId = utf8ToHex(userId);
|
656
|
-
const a = leftPad2(
|
657
|
-
const b = leftPad2(
|
658
|
-
const gx = leftPad2(
|
659
|
-
const gy = leftPad2(
|
703
|
+
const a = leftPad2(utils4.numberToHexUnpadded(sm2Curve.CURVE.a), 64);
|
704
|
+
const b = leftPad2(utils4.numberToHexUnpadded(sm2Curve.CURVE.b), 64);
|
705
|
+
const gx = leftPad2(utils4.numberToHexUnpadded(sm2Curve.ProjectivePoint.BASE.x), 64);
|
706
|
+
const gy = leftPad2(utils4.numberToHexUnpadded(sm2Curve.ProjectivePoint.BASE.y), 64);
|
660
707
|
let px;
|
661
708
|
let py;
|
662
709
|
if (publicKey.length === 128) {
|
@@ -664,8 +711,8 @@ function getHash(hashHex, publicKey, userId = "1234567812345678") {
|
|
664
711
|
py = publicKey.substring(64, 128);
|
665
712
|
} else {
|
666
713
|
const point = sm2Curve.ProjectivePoint.fromHex(publicKey);
|
667
|
-
px = leftPad2(
|
668
|
-
py = leftPad2(
|
714
|
+
px = leftPad2(utils4.numberToHexUnpadded(point.x), 64);
|
715
|
+
py = leftPad2(utils4.numberToHexUnpadded(point.y), 64);
|
669
716
|
}
|
670
717
|
const data = hexToArray(userId + a + b + gx + gy + px + py);
|
671
718
|
const entl = userId.length * 4;
|
@@ -674,13 +721,13 @@ function getHash(hashHex, publicKey, userId = "1234567812345678") {
|
|
674
721
|
}
|
675
722
|
function getPublicKeyFromPrivateKey(privateKey) {
|
676
723
|
const pubKey = sm2Curve.getPublicKey(privateKey, false);
|
677
|
-
const pubPad = leftPad2(
|
724
|
+
const pubPad = leftPad2(utils4.bytesToHex(pubKey), 64);
|
678
725
|
return pubPad;
|
679
726
|
}
|
680
727
|
function getPoint() {
|
681
728
|
const keypair = generateKeyPairHex();
|
682
729
|
const PA = sm2Curve.ProjectivePoint.fromHex(keypair.publicKey);
|
683
|
-
const k =
|
730
|
+
const k = utils4.hexToNumber(keypair.privateKey);
|
684
731
|
return {
|
685
732
|
...keypair,
|
686
733
|
k,
|
package/package.json
CHANGED
package/src/sm2/index.ts
CHANGED
package/src/sm2/kx.ts
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
import { sm2Curve } from './ec';
|
2
|
+
import { KeyPair, concatArray, hexToArray, leftPad } from './utils';
|
3
|
+
import * as utils from '@noble/curves/abstract/utils';
|
4
|
+
import { Field } from '@noble/curves/abstract/modular';
|
5
|
+
import { sm3 } from './sm3';
|
6
|
+
|
7
|
+
export const field = Field(BigInt(sm2Curve.CURVE.n))
|
8
|
+
|
9
|
+
// 用到的常数
|
10
|
+
const wPow2 = utils.hexToNumber('80000000000000000000000000000000')
|
11
|
+
const wPow2Sub1 = utils.hexToNumber('7fffffffffffffffffffffffffffffff')
|
12
|
+
|
13
|
+
// from sm2 sign part, extracted for code reusable.
|
14
|
+
function hkdf(z: Uint8Array, keylen: number) {
|
15
|
+
let t = new Uint8Array() // 256 位
|
16
|
+
let msg = new Uint8Array(keylen)
|
17
|
+
let ct = 1
|
18
|
+
let offset = 0
|
19
|
+
const nextT = () => {
|
20
|
+
// (1) Hai = hash(z || ct)
|
21
|
+
// (2) ct++
|
22
|
+
t = sm3(Uint8Array.from([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff]))
|
23
|
+
ct++
|
24
|
+
offset = 0
|
25
|
+
}
|
26
|
+
nextT() // 先生成 Ha1
|
27
|
+
|
28
|
+
for (let i = 0, len = msg.length; i < len; i++) {
|
29
|
+
// t = Ha1 || Ha2 || Ha3 || Ha4
|
30
|
+
if (offset === t.length) nextT()
|
31
|
+
|
32
|
+
// c2 = msg ^ t
|
33
|
+
msg[i] = t[offset++] & 0xff
|
34
|
+
}
|
35
|
+
return msg
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
export function calculateSharedKey(
|
40
|
+
keypairA: KeyPair,
|
41
|
+
ephemeralKeypairA: KeyPair,
|
42
|
+
publicKeyB: string,
|
43
|
+
ephemeralPublicKeyB: string,
|
44
|
+
idA: string = '1234567812345678',
|
45
|
+
idB: string = '1234567812345678',
|
46
|
+
sharedKeyLength: number,
|
47
|
+
) {
|
48
|
+
const RA = sm2Curve.ProjectivePoint.fromHex(ephemeralKeypairA.publicKey)
|
49
|
+
const RB = sm2Curve.ProjectivePoint.fromHex(ephemeralPublicKeyB)
|
50
|
+
// const PA = sm2Curve.ProjectivePoint.fromHex(keypairA.publicKey) // 暂时用不到
|
51
|
+
const PB = sm2Curve.ProjectivePoint.fromHex(publicKeyB)
|
52
|
+
const ZA = hexToArray(idA)
|
53
|
+
const ZB = hexToArray(idB)
|
54
|
+
const rA = utils.hexToNumber(ephemeralKeypairA.privateKey)
|
55
|
+
const dA = utils.hexToNumber(keypairA.privateKey)
|
56
|
+
// 1.先算tA
|
57
|
+
const x1 = RA.x
|
58
|
+
// x1_ = 2^w + (x1 & (2^w - 1))
|
59
|
+
const x1_ = field.add(wPow2, (x1 & wPow2Sub1))
|
60
|
+
// tA = (dA + x1b * rA) mod n
|
61
|
+
const tA = field.add(dA, field.mul(x1_, rA))
|
62
|
+
|
63
|
+
// 2.算 U
|
64
|
+
// x2_ = 2^w + (x2 & (2^w - 1))
|
65
|
+
const x2 = RB.x
|
66
|
+
const x2_ = field.add(wPow2, (x2 & wPow2Sub1))
|
67
|
+
// U = [h * tA](PB + x2_ * RB)
|
68
|
+
const U = RB.multiply(x2_).add(PB).multiply(tA)
|
69
|
+
|
70
|
+
// 3.算 KDF
|
71
|
+
// KA = KDF(xU || yU || ZA || ZB, kLen)
|
72
|
+
const xU = hexToArray(leftPad(utils.numberToHexUnpadded(U.x), 64))
|
73
|
+
const yU = hexToArray(leftPad(utils.numberToHexUnpadded(U.y), 64))
|
74
|
+
const KA = hkdf(concatArray(xU, yU, ZA, ZB), sharedKeyLength)
|
75
|
+
return KA
|
76
|
+
}
|
package/src/sm2/utils.ts
CHANGED
@@ -5,10 +5,15 @@ import { sm2Curve, sm2Fp } from './ec';
|
|
5
5
|
import { mod } from '@noble/curves/abstract/modular';
|
6
6
|
import { ONE, TWO, ZERO } from './bn';
|
7
7
|
|
8
|
+
export interface KeyPair {
|
9
|
+
privateKey: string
|
10
|
+
publicKey: string
|
11
|
+
}
|
12
|
+
|
8
13
|
/**
|
9
14
|
* 生成密钥对:publicKey = privateKey * G
|
10
15
|
*/
|
11
|
-
export function generateKeyPairHex(str?: string) {
|
16
|
+
export function generateKeyPairHex(str?: string): KeyPair {
|
12
17
|
const privateKey = str ? utils.numberToBytesBE((mod(BigInt(str), ONE) + ONE), 32) : sm2Curve.utils.randomPrivateKey()
|
13
18
|
// const random = typeof a === 'string' ? new BigInteger(a, b) :
|
14
19
|
// a ? new BigInteger(a, b!, c!) : new BigInteger(n.bitLength(), rng)
|