sm-crypto-v2 0.3.13 → 1.2.2
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 +32 -0
- package/README.md +9 -0
- package/dist/index.d.ts +5 -224
- package/dist/index.js +305 -435
- package/dist/index.mjs +298 -434
- package/package.json +4 -5
- package/pnpm-lock.yaml +12 -12
- package/src/sm2/asn1.ts +15 -12
- package/src/sm2/bn.ts +4 -0
- package/src/sm2/ec.ts +80 -317
- package/src/sm2/index.ts +83 -54
- package/src/sm2/utils.ts +29 -57
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "sm-crypto-v2",
|
3
|
-
"version": "
|
3
|
+
"version": "1.2.2",
|
4
4
|
"description": "sm-crypto-v2",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"module": "dist/index.mjs",
|
@@ -8,10 +8,10 @@
|
|
8
8
|
"scripts": {
|
9
9
|
"prepublish": "npm run build",
|
10
10
|
"lint": "eslint \"src/**/*.js\" --fix",
|
11
|
-
"build": "tsup",
|
11
|
+
"build": "vitest run && tsup",
|
12
12
|
"watch": "tsup --watch",
|
13
13
|
"test": "vitest",
|
14
|
-
"release": "
|
14
|
+
"release": "npm run build && standard-version && git push --follow-tags origin master",
|
15
15
|
"coverage": "vitest run --coverage"
|
16
16
|
},
|
17
17
|
"repository": {
|
@@ -30,8 +30,7 @@
|
|
30
30
|
"author": "june_01",
|
31
31
|
"license": "MIT",
|
32
32
|
"dependencies": {
|
33
|
-
"@
|
34
|
-
"jsbn": "^1.1.0"
|
33
|
+
"@noble/curves": "^1.1.0"
|
35
34
|
},
|
36
35
|
"devDependencies": {
|
37
36
|
"@swc/core": "^1.3.62",
|
package/pnpm-lock.yaml
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
lockfileVersion: '6.0'
|
2
2
|
|
3
3
|
dependencies:
|
4
|
-
'@
|
5
|
-
specifier: ^1.2.30
|
6
|
-
version: 1.2.30
|
7
|
-
jsbn:
|
4
|
+
'@noble/curves':
|
8
5
|
specifier: ^1.1.0
|
9
6
|
version: 1.1.0
|
10
7
|
|
@@ -581,6 +578,17 @@ packages:
|
|
581
578
|
'@jridgewell/sourcemap-codec': 1.4.14
|
582
579
|
dev: true
|
583
580
|
|
581
|
+
/@noble/curves@1.1.0:
|
582
|
+
resolution: {integrity: sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==}
|
583
|
+
dependencies:
|
584
|
+
'@noble/hashes': 1.3.1
|
585
|
+
dev: false
|
586
|
+
|
587
|
+
/@noble/hashes@1.3.1:
|
588
|
+
resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==}
|
589
|
+
engines: {node: '>= 16'}
|
590
|
+
dev: false
|
591
|
+
|
584
592
|
/@nodelib/fs.scandir@2.1.5:
|
585
593
|
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
586
594
|
engines: {node: '>= 8'}
|
@@ -732,10 +740,6 @@ packages:
|
|
732
740
|
resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==}
|
733
741
|
dev: true
|
734
742
|
|
735
|
-
/@types/jsbn@1.2.30:
|
736
|
-
resolution: {integrity: sha512-VZouplBofjq3YOIHLNRBDxILs/nAArdTZ2QP1ooflyhS+yPExWsFE+i2paBIBb7OI3NJShfcde/nogqk4SPB/Q==}
|
737
|
-
dev: false
|
738
|
-
|
739
743
|
/@types/json-schema@7.0.12:
|
740
744
|
resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
|
741
745
|
dev: true
|
@@ -2480,10 +2484,6 @@ packages:
|
|
2480
2484
|
argparse: 2.0.1
|
2481
2485
|
dev: true
|
2482
2486
|
|
2483
|
-
/jsbn@1.1.0:
|
2484
|
-
resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==}
|
2485
|
-
dev: false
|
2486
|
-
|
2487
2487
|
/jsesc@2.5.2:
|
2488
2488
|
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
|
2489
2489
|
engines: {node: '>=4'}
|
package/src/sm2/asn1.ts
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
/* eslint-disable class-methods-use-this */
|
2
2
|
|
3
|
-
import
|
3
|
+
import * as utils from '@noble/curves/abstract/utils';
|
4
|
+
import { ONE } from './bn';
|
4
5
|
|
5
|
-
export function bigintToValue(bigint:
|
6
|
+
export function bigintToValue(bigint: bigint) {
|
6
7
|
let h = bigint.toString(16)
|
7
8
|
if (h[0] !== '-') {
|
8
9
|
// 正数
|
@@ -10,18 +11,18 @@ export function bigintToValue(bigint: BigInteger) {
|
|
10
11
|
else if (!h.match(/^[0-7]/)) h = '00' + h // 非0开头,则补一个全0字节
|
11
12
|
} else {
|
12
13
|
// 负数
|
13
|
-
h = h.
|
14
|
-
|
14
|
+
h = h.substring(1)
|
15
15
|
let len = h.length
|
16
16
|
if (len % 2 === 1) len += 1 // 补齐到整字节
|
17
17
|
else if (!h.match(/^[0-7]/)) len += 2 // 非0开头,则补一个全0字节
|
18
18
|
|
19
19
|
let maskString = ''
|
20
20
|
for (let i = 0; i < len; i++) maskString += 'f'
|
21
|
-
let mask =
|
21
|
+
let mask = utils.hexToNumber(maskString)
|
22
22
|
|
23
23
|
// 对绝对值取反,加1
|
24
|
-
|
24
|
+
|
25
|
+
let output = (mask ^ bigint) + ONE
|
25
26
|
h = output.toString(16).replace(/^-/, '')
|
26
27
|
}
|
27
28
|
return h
|
@@ -68,7 +69,7 @@ class ASN1Object {
|
|
68
69
|
}
|
69
70
|
|
70
71
|
class DERInteger extends ASN1Object {
|
71
|
-
constructor(bigint:
|
72
|
+
constructor(bigint: bigint) {
|
72
73
|
super()
|
73
74
|
|
74
75
|
this.t = '02' // 整型标签说明
|
@@ -109,9 +110,9 @@ function getL(str: string, start: number) {
|
|
109
110
|
const l = str.substring(start + 2, start + 2 + len * 2)
|
110
111
|
|
111
112
|
if (!l) return -1
|
112
|
-
const bigint = +l[0] < 8 ?
|
113
|
+
const bigint = +l[0] < 8 ? utils.hexToNumber(l): utils.hexToNumber(l.substring(2))
|
113
114
|
|
114
|
-
return bigint.
|
115
|
+
return +bigint.toString()
|
115
116
|
}
|
116
117
|
|
117
118
|
/**
|
@@ -125,7 +126,7 @@ function getStartOfV(str: string, start: number) {
|
|
125
126
|
/**
|
126
127
|
* ASN.1 der 编码,针对 sm2 签名
|
127
128
|
*/
|
128
|
-
export function encodeDer(r:
|
129
|
+
export function encodeDer(r: bigint, s: bigint) {
|
129
130
|
const derR = new DERInteger(r)
|
130
131
|
const derS = new DERInteger(s)
|
131
132
|
const derSeq = new DERSequence([derR, derS])
|
@@ -151,8 +152,10 @@ export function decodeDer(input: string) {
|
|
151
152
|
const lS = getL(input, nextStart)
|
152
153
|
const vS = input.substring(vIndexS, vIndexS + lS * 2)
|
153
154
|
|
154
|
-
const r = new BigInteger(vR, 16)
|
155
|
-
const s = new BigInteger(vS, 16)
|
155
|
+
// const r = new BigInteger(vR, 16)
|
156
|
+
// const s = new BigInteger(vS, 16)
|
157
|
+
const r = utils.hexToNumber(vR)
|
158
|
+
const s = utils.hexToNumber(vS)
|
156
159
|
|
157
160
|
return { r, s }
|
158
161
|
}
|
package/src/sm2/bn.ts
ADDED
package/src/sm2/ec.ts
CHANGED
@@ -1,333 +1,96 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
import {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
*
|
8
|
-
* Basic Javascript Elliptic Curve implementation
|
9
|
-
* Ported loosely from BouncyCastle's Java EC code
|
10
|
-
* Only Fp curves implemented for now
|
11
|
-
*/
|
12
|
-
|
13
|
-
const TWO = new BigInteger('2')
|
14
|
-
const THREE = new BigInteger('3')
|
1
|
+
import { weierstrass } from '@noble/curves/abstract/weierstrass';
|
2
|
+
import { Field } from '@noble/curves/abstract/modular'; // finite field for mod arithmetics
|
3
|
+
import { hmac, sm3 } from './sm3'
|
4
|
+
import { utf8ToArray } from '@/sm3';
|
5
|
+
import { concatArray } from './utils';
|
6
|
+
import { ONE } from './bn';
|
15
7
|
|
16
8
|
/**
|
17
|
-
*
|
9
|
+
* 安全随机数发生器
|
10
|
+
* 如果有原生同步接口,直接使用。否则维护一个随机数池,使用异步接口实现。
|
11
|
+
* Web: webcrypto 原生同步接口
|
12
|
+
* Node: Node v18 之前需要引入 crypto 模块,这里使用异步 import
|
13
|
+
* 小程序:异步接口
|
18
14
|
*/
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
/**
|
25
|
-
* 判断相等
|
26
|
-
*/
|
27
|
-
equals(other: ECFieldElementFp) {
|
28
|
-
if (other === this) return true
|
29
|
-
return (this.q.equals(other.q) && this.x.equals(other.x))
|
30
|
-
}
|
31
|
-
|
32
|
-
/**
|
33
|
-
* 返回具体数值
|
34
|
-
*/
|
35
|
-
toBigInteger() {
|
36
|
-
return this.x
|
37
|
-
}
|
38
|
-
|
39
|
-
/**
|
40
|
-
* 取反
|
41
|
-
*/
|
42
|
-
negate() {
|
43
|
-
return new ECFieldElementFp(this.q, this.x.negate().mod(this.q))
|
44
|
-
}
|
45
|
-
|
46
|
-
/**
|
47
|
-
* 相加
|
48
|
-
*/
|
49
|
-
add(b) {
|
50
|
-
return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q))
|
51
|
-
}
|
52
|
-
|
53
|
-
/**
|
54
|
-
* 相减
|
55
|
-
*/
|
56
|
-
subtract(b) {
|
57
|
-
return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q))
|
58
|
-
}
|
59
|
-
|
60
|
-
/**
|
61
|
-
* 相乘
|
62
|
-
*/
|
63
|
-
multiply(b) {
|
64
|
-
return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q))
|
65
|
-
}
|
66
|
-
|
67
|
-
/**
|
68
|
-
* 相除
|
69
|
-
*/
|
70
|
-
divide(b) {
|
71
|
-
return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q))
|
72
|
-
}
|
73
|
-
|
74
|
-
/**
|
75
|
-
* 平方
|
76
|
-
*/
|
77
|
-
square() {
|
78
|
-
return new ECFieldElementFp(this.q, this.x.square().mod(this.q))
|
79
|
-
}
|
15
|
+
declare module wx {
|
16
|
+
function getRandomValues(options: {
|
17
|
+
length: number;
|
18
|
+
success: (res: { randomValues: ArrayBuffer }) => void;
|
19
|
+
}): void;
|
80
20
|
}
|
81
21
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
if (other === this) return true
|
109
|
-
if (this.isInfinity()) return other.isInfinity()
|
110
|
-
if (other.isInfinity()) return this.isInfinity()
|
111
|
-
|
112
|
-
// u = y2 * z1 - y1 * z2
|
113
|
-
const u = other.y!.toBigInteger().multiply(this.z).subtract(this.y!.toBigInteger().multiply(other.z)).mod(this.curve.q)
|
114
|
-
if (!u.equals(BigInteger.ZERO)) return false
|
115
|
-
|
116
|
-
// v = x2 * z1 - x1 * z2
|
117
|
-
const v = other.x!.toBigInteger().multiply(this.z).subtract(this.x!.toBigInteger().multiply(other.z)).mod(this.curve.q)
|
118
|
-
return v.equals(BigInteger.ZERO)
|
119
|
-
}
|
120
|
-
|
121
|
-
/**
|
122
|
-
* 是否是无穷远点
|
123
|
-
*/
|
124
|
-
isInfinity() {
|
125
|
-
if ((this.x === null) && (this.y === null)) return true
|
126
|
-
return this.z.equals(BigInteger.ZERO) && !this.y!.toBigInteger().equals(BigInteger.ZERO)
|
127
|
-
}
|
128
|
-
|
129
|
-
/**
|
130
|
-
* 取反,x 轴对称点
|
131
|
-
*/
|
132
|
-
negate() {
|
133
|
-
return new ECPointFp(this.curve, this.x, this.y!.negate(), this.z)
|
134
|
-
}
|
135
|
-
|
136
|
-
/**
|
137
|
-
* 相加
|
138
|
-
*
|
139
|
-
* 标准射影坐标系:
|
140
|
-
*
|
141
|
-
* λ1 = x1 * z2
|
142
|
-
* λ2 = x2 * z1
|
143
|
-
* λ3 = λ1 − λ2
|
144
|
-
* λ4 = y1 * z2
|
145
|
-
* λ5 = y2 * z1
|
146
|
-
* λ6 = λ4 − λ5
|
147
|
-
* λ7 = λ1 + λ2
|
148
|
-
* λ8 = z1 * z2
|
149
|
-
* λ9 = λ3^2
|
150
|
-
* λ10 = λ3 * λ9
|
151
|
-
* λ11 = λ8 * λ6^2 − λ7 * λ9
|
152
|
-
* x3 = λ3 * λ11
|
153
|
-
* y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10
|
154
|
-
* z3 = λ10 * λ8
|
155
|
-
*/
|
156
|
-
add(b: ECPointFp) {
|
157
|
-
if (this.isInfinity()) return b
|
158
|
-
if (b.isInfinity()) return this
|
159
|
-
|
160
|
-
const x1 = this.x!.toBigInteger()
|
161
|
-
const y1 = this.y!.toBigInteger()
|
162
|
-
const z1 = this.z
|
163
|
-
const x2 = b.x!.toBigInteger()
|
164
|
-
const y2 = b.y!.toBigInteger()
|
165
|
-
const z2 = b.z
|
166
|
-
const q = this.curve.q
|
167
|
-
|
168
|
-
const w1 = x1.multiply(z2).mod(q)
|
169
|
-
const w2 = x2.multiply(z1).mod(q)
|
170
|
-
const w3 = w1.subtract(w2)
|
171
|
-
const w4 = y1.multiply(z2).mod(q)
|
172
|
-
const w5 = y2.multiply(z1).mod(q)
|
173
|
-
const w6 = w4.subtract(w5)
|
174
|
-
|
175
|
-
if (BigInteger.ZERO.equals(w3)) {
|
176
|
-
if (BigInteger.ZERO.equals(w6)) {
|
177
|
-
return this.twice() // this == b,计算自加
|
178
|
-
}
|
179
|
-
return this.curve.infinity // this == -b,则返回无穷远点
|
180
|
-
}
|
181
|
-
|
182
|
-
const w7 = w1.add(w2)
|
183
|
-
const w8 = z1.multiply(z2).mod(q)
|
184
|
-
const w9 = w3.square().mod(q)
|
185
|
-
const w10 = w3.multiply(w9).mod(q)
|
186
|
-
const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q)
|
187
|
-
|
188
|
-
const x3 = w3.multiply(w11).mod(q)
|
189
|
-
const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q)
|
190
|
-
const z3 = w10.multiply(w8).mod(q)
|
191
|
-
|
192
|
-
return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
|
193
|
-
}
|
194
|
-
|
195
|
-
/**
|
196
|
-
* 自加
|
197
|
-
*
|
198
|
-
* 标准射影坐标系:
|
199
|
-
*
|
200
|
-
* λ1 = 3 * x1^2 + a * z1^2
|
201
|
-
* λ2 = 2 * y1 * z1
|
202
|
-
* λ3 = y1^2
|
203
|
-
* λ4 = λ3 * x1 * z1
|
204
|
-
* λ5 = λ2^2
|
205
|
-
* λ6 = λ1^2 − 8 * λ4
|
206
|
-
* x3 = λ2 * λ6
|
207
|
-
* y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3
|
208
|
-
* z3 = λ2 * λ5
|
209
|
-
*/
|
210
|
-
twice() {
|
211
|
-
if (this.isInfinity()) return this
|
212
|
-
if (!this.y!.toBigInteger().signum()) return this.curve.infinity
|
213
|
-
|
214
|
-
const x1 = this.x!.toBigInteger()
|
215
|
-
const y1 = this.y!.toBigInteger()
|
216
|
-
const z1 = this.z
|
217
|
-
const q = this.curve.q
|
218
|
-
const a = this.curve.a.toBigInteger()
|
219
|
-
|
220
|
-
const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q)
|
221
|
-
const w2 = y1.shiftLeft(1).multiply(z1).mod(q)
|
222
|
-
const w3 = y1.square().mod(q)
|
223
|
-
const w4 = w3.multiply(x1).multiply(z1).mod(q)
|
224
|
-
const w5 = w2.square().mod(q)
|
225
|
-
const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q)
|
226
|
-
|
227
|
-
const x3 = w2.multiply(w6).mod(q)
|
228
|
-
const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q)
|
229
|
-
const z3 = w2.multiply(w5).mod(q)
|
230
|
-
|
231
|
-
return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
|
232
|
-
}
|
233
|
-
|
234
|
-
/**
|
235
|
-
* 倍点计算
|
236
|
-
*/
|
237
|
-
multiply(k: BigInteger) {
|
238
|
-
if (this.isInfinity()) return this
|
239
|
-
if (!k.signum()) return this.curve.infinity
|
240
|
-
|
241
|
-
// 使用加减法
|
242
|
-
const k3 = k.multiply(THREE)
|
243
|
-
const neg = this.negate()
|
244
|
-
let Q: ECPointFp = this
|
245
|
-
|
246
|
-
for (let i = k3.bitLength() - 2; i > 0; i--) {
|
247
|
-
Q = Q.twice()
|
248
|
-
|
249
|
-
const k3Bit = k3.testBit(i)
|
250
|
-
const kBit = k.testBit(i)
|
251
|
-
|
252
|
-
if (k3Bit !== kBit) {
|
253
|
-
Q = Q.add(k3Bit ? this : neg)
|
254
|
-
}
|
22
|
+
const DEFAULT_PRNG_POOL_SIZE = 4096
|
23
|
+
let prngPool = new Uint8Array(0)
|
24
|
+
|
25
|
+
async function FillPRNGPoolIfNeeded() {
|
26
|
+
if ('crypto' in globalThis) return // no need to use pooling
|
27
|
+
if (prngPool.length > DEFAULT_PRNG_POOL_SIZE / 2) return // there is sufficient number
|
28
|
+
// we always populate full pool size
|
29
|
+
// since numbers may be consumed during micro tasks.
|
30
|
+
if ('wx' in globalThis) {
|
31
|
+
prngPool = await new Promise(r => {
|
32
|
+
wx.getRandomValues({
|
33
|
+
length: DEFAULT_PRNG_POOL_SIZE,
|
34
|
+
success(res) {
|
35
|
+
r(new Uint8Array(res.randomValues));
|
36
|
+
}
|
37
|
+
});
|
38
|
+
});
|
39
|
+
} else {
|
40
|
+
// check if node, use webcrypto if available
|
41
|
+
try {
|
42
|
+
const crypto = await import(/* webpackIgnore: true */ 'crypto');
|
43
|
+
const array = new Uint8Array(DEFAULT_PRNG_POOL_SIZE);
|
44
|
+
crypto.webcrypto.getRandomValues(array);
|
45
|
+
prngPool = array;
|
46
|
+
} catch (error) {
|
47
|
+
throw new Error('no available csprng, abort.');
|
255
48
|
}
|
256
|
-
|
257
|
-
return Q
|
258
49
|
}
|
259
50
|
}
|
260
51
|
|
261
|
-
|
262
|
-
* 椭圆曲线 y^2 = x^3 + ax + b
|
263
|
-
*/
|
264
|
-
export class ECCurveFp {
|
265
|
-
infinity: ECPointFp
|
266
|
-
a: ECFieldElementFp
|
267
|
-
b: ECFieldElementFp
|
268
|
-
constructor(public q: BigInteger, a: BigInteger, b: BigInteger) {
|
269
|
-
this.q = q
|
270
|
-
this.a = this.fromBigInteger(a)
|
271
|
-
this.b = this.fromBigInteger(b)
|
272
|
-
this.infinity = new ECPointFp(this, null, null) // 无穷远点
|
273
|
-
}
|
274
|
-
|
275
|
-
/**
|
276
|
-
* 判断两个椭圆曲线是否相等
|
277
|
-
*/
|
278
|
-
equals(other: ECCurveFp) {
|
279
|
-
if (other === this) return true
|
280
|
-
return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b))
|
281
|
-
}
|
52
|
+
FillPRNGPoolIfNeeded()
|
282
53
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
54
|
+
function consumePool(length: number): Uint8Array {
|
55
|
+
if (prngPool.length > length) {
|
56
|
+
const prng = prngPool.slice(0, length)
|
57
|
+
prngPool = prngPool.slice(length)
|
58
|
+
FillPRNGPoolIfNeeded()
|
59
|
+
return prng
|
60
|
+
} else {
|
61
|
+
throw new Error('random number pool is insufficient, prevent getting too long random values or too often.')
|
288
62
|
}
|
63
|
+
}
|
289
64
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
return this.infinity
|
298
|
-
case 2:
|
299
|
-
case 3:
|
300
|
-
// 压缩
|
301
|
-
const x = this.fromBigInteger(new BigInteger(s.substring(2), 16))
|
302
|
-
// 对 p ≡ 3 (mod4),即存在正整数 u,使得 p = 4u + 3
|
303
|
-
// 计算 y = (√ (x^3 + ax + b) % p)^(u + 1) modp
|
304
|
-
let y = this.fromBigInteger(x.multiply(x.square()).add(
|
305
|
-
x.multiply(this.a)
|
306
|
-
).add(this.b).toBigInteger()
|
307
|
-
.modPow(
|
308
|
-
this.q.divide(new BigInteger('4')).add(BigInteger.ONE), this.q
|
309
|
-
))
|
310
|
-
// 算出结果 2 进制最后 1 位不等于第 1 个字节减 2 则取反
|
311
|
-
if (!y.toBigInteger().mod(TWO).equals(new BigInteger(s.substring(0, 2), 16).subtract(TWO))) {
|
312
|
-
y = y.negate()
|
313
|
-
}
|
314
|
-
return new ECPointFp(this, x, y)
|
315
|
-
case 4:
|
316
|
-
case 6:
|
317
|
-
case 7:
|
318
|
-
const len = (s.length - 2) / 2
|
319
|
-
const xHex = s.substring(2, 2 + len)
|
320
|
-
const yHex = s.substring(len + 2, len + 2 + len)
|
321
|
-
|
322
|
-
return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16)))
|
323
|
-
default:
|
324
|
-
// 不支持
|
325
|
-
return null
|
326
|
-
}
|
65
|
+
export function randomBytes(length = 0): Uint8Array {
|
66
|
+
const array = new Uint8Array(length);
|
67
|
+
if ('crypto' in globalThis) {
|
68
|
+
return globalThis.crypto.getRandomValues(array);
|
69
|
+
} else {
|
70
|
+
const result = consumePool(length)
|
71
|
+
return result
|
327
72
|
}
|
328
73
|
}
|
329
74
|
|
330
|
-
export
|
331
|
-
|
332
|
-
|
75
|
+
export function createHash() {
|
76
|
+
const hashC = (msg: Uint8Array | string): Uint8Array => sm3(typeof msg === 'string' ? utf8ToArray(msg) : msg)
|
77
|
+
hashC.outputLen = 256;
|
78
|
+
hashC.blockLen = 512;
|
79
|
+
hashC.create = () => sm3(Uint8Array.from([]));
|
80
|
+
return hashC;
|
333
81
|
}
|
82
|
+
|
83
|
+
export const sm2Fp = Field(BigInt('115792089210356248756420345214020892766250353991924191454421193933289684991999'))
|
84
|
+
export const sm2Curve = weierstrass({
|
85
|
+
// sm2: short weierstrass.
|
86
|
+
a: BigInt('115792089210356248756420345214020892766250353991924191454421193933289684991996'),
|
87
|
+
b: BigInt('18505919022281880113072981827955639221458448578012075254857346196103069175443'),
|
88
|
+
Fp: sm2Fp,
|
89
|
+
h: ONE,
|
90
|
+
n: BigInt('115792089210356248756420345214020892766061623724957744567843809356293439045923'),
|
91
|
+
Gx: BigInt('22963146547237050559479531362550074578802567295341616970375194840604139615431'),
|
92
|
+
Gy: BigInt('85132369209828568825618990617112496413088388631904505083283536607588877201568'),
|
93
|
+
hash: createHash(),
|
94
|
+
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(concatArray(...msgs), key),
|
95
|
+
randomBytes,
|
96
|
+
});
|