sm-crypto-v2 1.8.0 → 1.9.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/package.json CHANGED
@@ -1,17 +1,20 @@
1
1
  {
2
2
  "name": "sm-crypto-v2",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "sm-crypto-v2",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
+ "miniprogram": "miniprogram_dist",
7
8
  "types": "dist/index.d.ts",
8
9
  "scripts": {
9
10
  "prepublish": "npm run build",
10
11
  "lint": "eslint \"src/**/*.js\" --fix",
11
- "build": "vitest run && tsup",
12
+ "prerelease": "vitest run && npm run build && npm run build-mp",
13
+ "build": "tsup",
14
+ "build-mp": "tsup --config=tsup.config.miniprogram.ts",
12
15
  "watch": "tsup --watch",
13
16
  "test": "vitest",
14
- "release": "npm run build && standard-version && git push --follow-tags origin master",
17
+ "release": "npm run prerelease && standard-version && git push --follow-tags origin master",
15
18
  "coverage": "vitest run --coverage"
16
19
  },
17
20
  "repository": {
@@ -44,12 +47,13 @@
44
47
  "@vitest/runner": "^0.33.0",
45
48
  "@vitest/ui": "^0.31.0",
46
49
  "conventional-changelog-cli": "^2.2.2",
50
+ "esbuild": "^0.19.10",
47
51
  "eslint": "^8.15.0",
48
52
  "eslint-config-prettier": "^8.3.0",
49
53
  "eslint-plugin-prettier": "^4.0.0",
50
54
  "prettier": "^2.6.2",
51
55
  "standard-version": "^9.5.0",
52
- "tsup": "^5.12.7",
56
+ "tsup": "^8.0.1",
53
57
  "typescript": "^4.7.2",
54
58
  "vite": "^4.3.9",
55
59
  "vitest": "^0.31.0"
@@ -3,15 +3,20 @@ import { defineConfig } from 'tsup';
3
3
  export default defineConfig({
4
4
  entry: ['./src/index.ts'],
5
5
  clean: true,
6
- outDir: 'dist',
6
+ outDir: 'miniprogram_dist',
7
7
  dts: true,
8
8
  // we need to keep minify false, since webpack magic comments
9
9
  // will be stripped if minify.
10
10
  minify: false,
11
- format: ['esm', 'cjs'],
12
- target: 'esnext',
11
+ format: ['cjs'],
12
+ target: 'es5',
13
+ noExternal: ['@noble/curves'],
13
14
  tsconfig: 'tsconfig.json',
14
15
  esbuildOptions(options) {
15
- options.define.__BUILD_TS__ = Date.now();
16
+ options.define.__BUILD_TS__ = Date.now().toString();
17
+ options.define.import = 'require';
18
+ options.supported = {
19
+ 'dynamic-import': false,
20
+ }
16
21
  }
17
22
  });
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export * as sm2 from './sm2/index'
2
- export { sm3 } from './sm3/index'
3
- export * as sm4 from './sm4/index'
package/src/sm2/asn1.ts DELETED
@@ -1,210 +0,0 @@
1
- /* eslint-disable class-methods-use-this */
2
-
3
- import * as utils from '@noble/curves/abstract/utils';
4
- import { ONE } from './bn';
5
- import { utf8ToHex } from './utils';
6
-
7
- export function bigintToValue(bigint: bigint) {
8
- let h = bigint.toString(16)
9
- if (h[0] !== '-') {
10
- // 正数
11
- if (h.length % 2 === 1) h = '0' + h // 补齐到整字节
12
- else if (!h.match(/^[0-7]/)) h = '00' + h // 非0开头,则补一个全0字节
13
- } else {
14
- // 负数
15
- h = h.substring(1)
16
- let len = h.length
17
- if (len % 2 === 1) len += 1 // 补齐到整字节
18
- else if (!h.match(/^[0-7]/)) len += 2 // 非0开头,则补一个全0字节
19
-
20
- let maskString = ''
21
- for (let i = 0; i < len; i++) maskString += 'f'
22
- let mask = utils.hexToNumber(maskString)
23
-
24
- // 对绝对值取反,加1
25
-
26
- let output = (mask ^ bigint) + ONE
27
- h = output.toString(16).replace(/^-/, '')
28
- }
29
- return h
30
- }
31
-
32
- class ASN1Object {
33
- constructor(
34
- public tlv: string | null = null,
35
- public t = '00',
36
- public l = '00',
37
- public v = ''
38
- ) { }
39
-
40
- /**
41
- * 获取 der 编码比特流16进制串
42
- */
43
- getEncodedHex() {
44
- if (!this.tlv) {
45
- this.v = this.getValue()
46
- this.l = this.getLength()
47
- this.tlv = this.t + this.l + this.v
48
- }
49
- return this.tlv
50
- }
51
-
52
- getLength() {
53
- const n = this.v.length / 2 // 字节数
54
- let nHex = n.toString(16)
55
- if (nHex.length % 2 === 1) nHex = '0' + nHex // 补齐到整字节
56
-
57
- if (n < 128) {
58
- // 短格式,以 0 开头
59
- return nHex
60
- } else {
61
- // 长格式,以 1 开头
62
- const head = 128 + nHex.length / 2 // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度
63
- return head.toString(16) + nHex
64
- }
65
- }
66
-
67
- getValue() {
68
- return ''
69
- }
70
- }
71
-
72
- class DERInteger extends ASN1Object {
73
- constructor(bigint: bigint) {
74
- super()
75
-
76
- this.t = '02' // 整型标签说明
77
- if (bigint) this.v = bigintToValue(bigint)
78
- }
79
-
80
- getValue() {
81
- return this.v
82
- }
83
- }
84
-
85
- class DEROctetString extends ASN1Object {
86
- public hV: string = ''
87
- constructor(public s: string) {
88
- super()
89
-
90
- this.t = '04' // octstr 标签说明
91
- if (s) this.v = s.toLowerCase()
92
- }
93
-
94
- getValue() {
95
- return this.v
96
- }
97
- }
98
-
99
- class DERSequence extends ASN1Object {
100
- public t = '30'
101
- constructor(public asn1Array: ASN1Object[]) {
102
- super()
103
- }
104
-
105
- getValue() {
106
- this.v = this.asn1Array.map(asn1Object => asn1Object.getEncodedHex()).join('')
107
- return this.v
108
- }
109
- }
110
-
111
- /**
112
- * 获取 l 占用字节数
113
- */
114
- function getLenOfL(str: string, start: number) {
115
- if (+str[start + 2] < 8) return 1 // l 以0开头,则表示短格式,只占一个字节
116
- return +str.substring(start + 2, start + 4) & 0x7f + 1 // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身
117
- }
118
-
119
- /**
120
- * 获取 l
121
- */
122
- function getL(str: string, start: number) {
123
- // 获取 l
124
- const len = getLenOfL(str, start)
125
- const l = str.substring(start + 2, start + 2 + len * 2)
126
-
127
- if (!l) return -1
128
- const bigint = +l[0] < 8 ? utils.hexToNumber(l): utils.hexToNumber(l.substring(2))
129
-
130
- return +bigint.toString()
131
- }
132
-
133
- /**
134
- * 获取 v 的位置
135
- */
136
- function getStartOfV(str: string, start: number) {
137
- const len = getLenOfL(str, start)
138
- return start + (len + 1) * 2
139
- }
140
-
141
- /**
142
- * ASN.1 der 编码,针对 sm2 签名
143
- */
144
- export function encodeDer(r: bigint, s: bigint) {
145
- const derR = new DERInteger(r)
146
- const derS = new DERInteger(s)
147
- const derSeq = new DERSequence([derR, derS])
148
-
149
- return derSeq.getEncodedHex()
150
- }
151
-
152
- export function encodeEnc(x: bigint, y: bigint, hash: string, cipher: string) {
153
- const derX = new DERInteger(x)
154
- const derY = new DERInteger(y)
155
- const derHash = new DEROctetString(hash)
156
- const derCipher = new DEROctetString(cipher)
157
- const derSeq = new DERSequence([derX, derY, derHash, derCipher])
158
- return derSeq.getEncodedHex()
159
- }
160
- /**
161
- * 解析 ASN.1 der,针对 sm2 验签
162
- */
163
- export function decodeDer(input: string) {
164
- // 结构:
165
- // input = | tSeq | lSeq | vSeq |
166
- // vSeq = | tR | lR | vR | tS | lS | vS |
167
- const start = getStartOfV(input, 0)
168
-
169
- const vIndexR = getStartOfV(input, start)
170
- const lR = getL(input, start)
171
- const vR = input.substring(vIndexR, vIndexR +lR * 2)
172
-
173
- const nextStart = vIndexR + vR.length
174
- const vIndexS = getStartOfV(input, nextStart)
175
- const lS = getL(input, nextStart)
176
- const vS = input.substring(vIndexS, vIndexS + lS * 2)
177
-
178
- // const r = new BigInteger(vR, 16)
179
- // const s = new BigInteger(vS, 16)
180
- const r = utils.hexToNumber(vR)
181
- const s = utils.hexToNumber(vS)
182
-
183
- return { r, s }
184
- }
185
-
186
- /**
187
- * 解析 ASN.1 der,针对 sm2 加密
188
- */
189
- export function decodeEnc(input: string) {
190
- // Extracts a sequence from the input based on the current start index.
191
- function extractSequence(input: string, start: number): { value: string; nextStart: number } {
192
- const vIndex = getStartOfV(input, start);
193
- const length = getL(input, start);
194
- const value = input.substring(vIndex, vIndex + length * 2);
195
- const nextStart = vIndex + value.length;
196
- return { value, nextStart };
197
- }
198
-
199
- const start = getStartOfV(input, 0);
200
-
201
- const { value: vR, nextStart: startS } = extractSequence(input, start);
202
- const { value: vS, nextStart: startHash } = extractSequence(input, startS);
203
- const { value: hash, nextStart: startCipher } = extractSequence(input, startHash);
204
- const { value: cipher } = extractSequence(input, startCipher);
205
-
206
- const x = utils.hexToNumber(vR);
207
- const y = utils.hexToNumber(vS);
208
-
209
- return { x, y, hash, cipher };
210
- }
package/src/sm2/bn.ts DELETED
@@ -1,4 +0,0 @@
1
- export const ZERO = BigInt(0);
2
- export const ONE = BigInt(1);
3
- export const TWO = BigInt(2);
4
- export const THREE = BigInt(3);
package/src/sm2/ec.ts DELETED
@@ -1,24 +0,0 @@
1
- import { weierstrass } from '@noble/curves/abstract/weierstrass';
2
- import { Field } from '@noble/curves/abstract/modular'; // finite field for mod arithmetics
3
- import { ONE } from './bn';
4
- import { randomBytes } from './rng';
5
- import { sm3 } from './sm3';
6
- import { hmac } from './hmac';
7
- import { concatBytes } from '@noble/curves/abstract/utils';
8
-
9
- export const sm2Fp = Field(BigInt('115792089210356248756420345214020892766250353991924191454421193933289684991999'))
10
- export const sm2Curve = weierstrass({
11
- // sm2: short weierstrass.
12
- a: BigInt('115792089210356248756420345214020892766250353991924191454421193933289684991996'),
13
- b: BigInt('18505919022281880113072981827955639221458448578012075254857346196103069175443'),
14
- Fp: sm2Fp,
15
- h: ONE,
16
- n: BigInt('115792089210356248756420345214020892766061623724957744567843809356293439045923'),
17
- Gx: BigInt('22963146547237050559479531362550074578802567295341616970375194840604139615431'),
18
- Gy: BigInt('85132369209828568825618990617112496413088388631904505083283536607588877201568'),
19
- hash: sm3,
20
- hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sm3, key, concatBytes(...msgs)),
21
- randomBytes,
22
- });
23
- // 有限域运算
24
- export const field = Field(BigInt(sm2Curve.CURVE.n))
package/src/sm2/hmac.ts DELETED
@@ -1,76 +0,0 @@
1
- import { Hash, CHash, Input, toBytes } from '../sm3/utils';
2
- // HMAC (RFC 2104)
3
- export class HMAC<T extends Hash<T>> extends Hash<HMAC<T>> {
4
- oHash: T;
5
- iHash: T;
6
- blockLen: number;
7
- outputLen: number;
8
- private finished = false;
9
- private destroyed = false;
10
-
11
- constructor(hash: CHash, _key: Input) {
12
- super();
13
- const key = toBytes(_key);
14
- this.iHash = hash.create() as T;
15
- if (typeof this.iHash.update !== 'function')
16
- throw new Error('Expected instance of class which extends utils.Hash');
17
- this.blockLen = this.iHash.blockLen;
18
- this.outputLen = this.iHash.outputLen;
19
- const blockLen = this.blockLen;
20
- const pad = new Uint8Array(blockLen);
21
- // blockLen can be bigger than outputLen
22
- pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
23
- for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36;
24
- this.iHash.update(pad);
25
- // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
26
- this.oHash = hash.create() as T;
27
- // Undo internal XOR && apply outer XOR
28
- for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36 ^ 0x5c;
29
- this.oHash.update(pad);
30
- pad.fill(0);
31
- }
32
- update(buf: Input) {
33
- this.iHash.update(buf);
34
- return this;
35
- }
36
- digestInto(out: Uint8Array) {
37
- this.finished = true;
38
- this.iHash.digestInto(out);
39
- this.oHash.update(out);
40
- this.oHash.digestInto(out);
41
- this.destroy();
42
- }
43
- digest() {
44
- const out = new Uint8Array(this.oHash.outputLen);
45
- this.digestInto(out);
46
- return out;
47
- }
48
- _cloneInto(to?: HMAC<T>): HMAC<T> {
49
- // Create new instance without calling constructor since key already in state and we don't know it.
50
- to ||= Object.create(Object.getPrototypeOf(this), {});
51
- const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
52
- to = to as this;
53
- to.finished = finished;
54
- to.destroyed = destroyed;
55
- to.blockLen = blockLen;
56
- to.outputLen = outputLen;
57
- to.oHash = oHash._cloneInto(to.oHash);
58
- to.iHash = iHash._cloneInto(to.iHash);
59
- return to;
60
- }
61
- destroy() {
62
- this.destroyed = true;
63
- this.oHash.destroy();
64
- this.iHash.destroy();
65
- }
66
- }
67
-
68
- /**
69
- * HMAC: RFC2104 message authentication code.
70
- * @param hash - function that would be used e.g. sha256
71
- * @param key - message key
72
- * @param message - message data
73
- */
74
- export const hmac = (hash: CHash, key: Input, message: Input): Uint8Array =>
75
- new HMAC<any>(hash, key).update(message).digest();
76
- hmac.create = (hash: CHash, key: Input) => new HMAC<any>(hash, key);
package/src/sm2/index.ts DELETED
@@ -1,319 +0,0 @@
1
- /* eslint-disable no-use-before-define */
2
- import { encodeDer, decodeDer, encodeEnc, decodeEnc } from './asn1'
3
- import { arrayToHex, arrayToUtf8, generateKeyPairHex, hexToArray, leftPad, utf8ToHex } from './utils'
4
- import { sm3 } from './sm3'
5
- import * as utils from '@noble/curves/abstract/utils';
6
- import { field, sm2Curve } from './ec';
7
- import { ONE, ZERO } from './bn';
8
- import { bytesToHex } from '@/sm3/utils';
9
- import { ProjPointType } from '@noble/curves/abstract/weierstrass';
10
-
11
- export * from './utils'
12
- export { initRNGPool } from './rng'
13
- export { calculateSharedKey } from './kx'
14
-
15
- const C1C2C3 = 0
16
- // a empty array, just make tsc happy
17
- export const EmptyArray = new Uint8Array()
18
- /**
19
- * 加密
20
- */
21
- export function doEncrypt(msg: string | Uint8Array, publicKey: string | ProjPointType<bigint>, cipherMode = 1, options?: {
22
- asn1?: boolean // 使用 ASN.1 对 C1 编码
23
- }) {
24
-
25
- const msgArr = typeof msg === 'string' ? hexToArray(utf8ToHex(msg)) : Uint8Array.from(msg)
26
- const publicKeyPoint = typeof publicKey === 'string' ? sm2Curve.ProjectivePoint.fromHex(publicKey) :
27
- publicKey
28
-
29
- const keypair = generateKeyPairHex()
30
- const k = utils.hexToNumber(keypair.privateKey)
31
-
32
- // c1 = k * G
33
- let c1 = keypair.publicKey
34
-
35
- if (c1.length > 128) c1 = c1.substring(c1.length - 128)
36
- const p = publicKeyPoint.multiply(k)
37
-
38
- // (x2, y2) = k * publicKey
39
- const x2 = hexToArray(leftPad(utils.numberToHexUnpadded(p.x), 64))
40
- const y2 = hexToArray(leftPad(utils.numberToHexUnpadded(p.y), 64))
41
-
42
- // c3 = hash(x2 || msg || y2)
43
- const c3 = bytesToHex(sm3(utils.concatBytes(x2, msgArr, y2)));
44
-
45
- xorCipherStream(x2, y2, msgArr)
46
- const c2 = bytesToHex(msgArr)
47
- if (options?.asn1) {
48
- const point = sm2Curve.ProjectivePoint.fromHex(keypair.publicKey)
49
- const encode = cipherMode === C1C2C3 ?
50
- encodeEnc(point.x, point.y, c2, c3) :
51
- encodeEnc(point.x, point.y, c3, c2)
52
- return encode
53
- }
54
- return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2
55
- }
56
-
57
- function xorCipherStream(x2: Uint8Array, y2: Uint8Array, msg: Uint8Array) {
58
- let ct = 1
59
- let offset = 0
60
- let t = EmptyArray
61
- const ctShift = new Uint8Array(4)
62
- const nextT = () => {
63
- // (1) Hai = hash(z || ct)
64
- // (2) ct++
65
- ctShift[0] = ct >> 24 & 0x00ff
66
- ctShift[1] = ct >> 16 & 0x00ff
67
- ctShift[2] = ct >> 8 & 0x00ff
68
- ctShift[3] = ct & 0x00ff
69
- t = sm3(utils.concatBytes(x2, y2, ctShift))
70
- ct++
71
- offset = 0
72
- }
73
- nextT() // 先生成 Ha1
74
-
75
- for (let i = 0, len = msg.length; i < len; i++) {
76
- // t = Ha1 || Ha2 || Ha3 || Ha4
77
- if (offset === t.length) nextT()
78
-
79
- // c2 = msg ^ t
80
- msg[i] ^= t[offset++] & 0xff
81
- }
82
-
83
- }
84
-
85
- /**
86
- * 解密
87
- */
88
- export function doDecrypt(encryptData: string, privateKey: string, cipherMode?: number, options?: {
89
- output: 'array'
90
- asn1?: boolean
91
- }): Uint8Array
92
- export function doDecrypt(encryptData: string, privateKey: string, cipherMode?: number, options?: {
93
- output: 'string',
94
- asn1?: boolean
95
- }): string
96
- export function doDecrypt(encryptData: string, privateKey: string, cipherMode = 1, {
97
- output = 'string',
98
- asn1 = false,
99
- } = {}) {
100
- const privateKeyInteger = utils.hexToNumber(privateKey)
101
-
102
- let c1: ProjPointType<bigint>
103
- let c2: string
104
- let c3: string
105
-
106
-
107
- if (asn1) {
108
- const {x, y, cipher, hash} = decodeEnc(encryptData)
109
- c1 = sm2Curve.ProjectivePoint.fromAffine({ x, y })
110
- c3 = hash
111
- c2 = cipher
112
- if (cipherMode === C1C2C3) {
113
- [c2, c3] = [c3, c2]
114
- }
115
- } else {
116
- // c1c3c2
117
- c1 = sm2Curve.ProjectivePoint.fromHex('04' + encryptData.substring(0, 128))!
118
- c3 = encryptData.substring(128, 128 + 64)
119
- c2 = encryptData.substring(128 + 64)
120
-
121
- if (cipherMode === C1C2C3) {
122
- c3 = encryptData.substring(encryptData.length - 64)
123
- c2 = encryptData.substring(128, encryptData.length - 64)
124
- }
125
- }
126
-
127
-
128
- const msg = hexToArray(c2)
129
- const p = c1.multiply(privateKeyInteger)
130
- const x2 = hexToArray(leftPad(utils.numberToHexUnpadded(p.x), 64))
131
- const y2 = hexToArray(leftPad(utils.numberToHexUnpadded(p.y), 64))
132
-
133
- xorCipherStream(x2, y2, msg)
134
- // c3 = hash(x2 || msg || y2)
135
- const checkC3 = arrayToHex(Array.from(sm3(utils.concatBytes(x2, msg, y2))))
136
-
137
- if (checkC3 === c3.toLowerCase()) {
138
- return output === 'array' ? msg : arrayToUtf8(msg)
139
- } else {
140
- return output === 'array' ? [] : ''
141
- }
142
- }
143
-
144
- export interface SignaturePoint {
145
- k: bigint
146
- x1: bigint
147
- }
148
-
149
- /**
150
- * 签名
151
- */
152
- export function doSignature(msg: Uint8Array | string, privateKey: string, options: {
153
- pointPool?: SignaturePoint[], der?: boolean, hash?: boolean, publicKey?: string, userId?: string
154
- } = {}) {
155
- let {
156
- pointPool, der, hash, publicKey, userId
157
- } = options
158
- let hashHex = typeof msg === 'string' ? utf8ToHex(msg) : arrayToHex(Array.from(msg))
159
-
160
- if (hash) {
161
- // sm3杂凑
162
- publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey)
163
- hashHex = getHash(hashHex, publicKey, userId)
164
- }
165
-
166
- const dA = utils.hexToNumber(privateKey)
167
- const e = utils.hexToNumber(hashHex)
168
-
169
- // k
170
- let k: bigint | null = null
171
- let r: bigint | null = null
172
- let s: bigint | null = null
173
-
174
- do {
175
- do {
176
- let point: SignaturePoint
177
- if (pointPool && pointPool.length) {
178
- point = pointPool.pop()!
179
- } else {
180
- point = getPoint()
181
- }
182
- k = point.k
183
-
184
- // r = (e + x1) mod n
185
- r = field.add(e, point.x1)
186
- } while (r === ZERO || (r + k) === sm2Curve.CURVE.n)
187
-
188
- // s = ((1 + dA)^-1 * (k - r * dA)) mod n
189
- s = field.mul(field.inv(field.addN(dA, ONE)), field.subN(k, field.mulN(r, dA)))
190
- } while (s === ZERO)
191
- if (der) return encodeDer(r, s) // asn.1 der 编码
192
- return leftPad(utils.numberToHexUnpadded(r), 64) + leftPad(utils.numberToHexUnpadded(s), 64)
193
- }
194
-
195
- /**
196
- * 验签
197
- */
198
- export function doVerifySignature(msg: string | Uint8Array, signHex: string, publicKey: string | ProjPointType<bigint>, options: { der?: boolean, hash?: boolean, userId?: string } = {}) {
199
- let hashHex: string
200
- const {
201
- hash,
202
- der,
203
- userId,
204
- } = options
205
- const publicKeyHex = typeof publicKey === 'string' ? publicKey : publicKey.toHex(false)
206
- if (hash) {
207
- // sm3杂凑
208
- hashHex = getHash(typeof msg === 'string' ? utf8ToHex(msg) : msg, publicKeyHex, userId)
209
- } else {
210
- hashHex = typeof msg === 'string' ? utf8ToHex(msg) : arrayToHex(Array.from(msg))
211
- }
212
-
213
- let r: bigint;
214
- let s: bigint;
215
- if (der) {
216
- const decodeDerObj = decodeDer(signHex) // asn.1 der 解码
217
- r = decodeDerObj.r
218
- s = decodeDerObj.s
219
- } else {
220
- r = utils.hexToNumber(signHex.substring(0, 64))
221
- s = utils.hexToNumber(signHex.substring(64))
222
- }
223
-
224
- const PA = typeof publicKey === 'string' ? sm2Curve.ProjectivePoint.fromHex(publicKey) : publicKey
225
- const e = utils.hexToNumber(hashHex)
226
-
227
- // t = (r + s) mod n
228
- const t = field.add(r, s)
229
-
230
- if (t === ZERO) return false
231
-
232
- // x1y1 = s * G + t * PA
233
- const x1y1 = sm2Curve.ProjectivePoint.BASE.multiply(s).add(PA.multiply(t))
234
-
235
- // R = (e + x1) mod n
236
- // const R = e.add(x1y1.getX().toBigInteger()).mod(n)
237
- const R = field.add(e, x1y1.x)
238
-
239
- // return r.equals(R)
240
- return r === R
241
- }
242
-
243
- export function getZ(publicKey: string, userId = '1234567812345678') {
244
- // z = hash(entl || userId || a || b || gx || gy || px || py)
245
- userId = utf8ToHex(userId)
246
- const a = leftPad(utils.numberToHexUnpadded(sm2Curve.CURVE.a), 64)
247
- // const b = leftPad(G.curve.b.toBigInteger().toRadix(16), 64)
248
- const b = leftPad(utils.numberToHexUnpadded(sm2Curve.CURVE.b), 64)
249
- // const gx = leftPad(G.getX().toBigInteger().toRadix(16), 64)
250
- const gx = leftPad(utils.numberToHexUnpadded(sm2Curve.ProjectivePoint.BASE.x), 64)
251
- // const gy = leftPad(G.getY().toBigInteger().toRadix(16), 64)
252
- const gy = leftPad(utils.numberToHexUnpadded(sm2Curve.ProjectivePoint.BASE.y), 64)
253
- let px: string
254
- let py: string
255
- if (publicKey.length === 128) {
256
- px = publicKey.substring(0, 64)
257
- py = publicKey.substring(64, 128)
258
- } else {
259
- // const point = G.curve.decodePointHex(publicKey)!
260
- const point = sm2Curve.ProjectivePoint.fromHex(publicKey)!
261
- // px = leftPad(point.getX().toBigInteger().toRadix(16), 64)
262
- px = leftPad(utils.numberToHexUnpadded(point.x), 64)
263
- // py = leftPad(point.getY().toBigInteger().toRadix(16), 64)
264
- py = leftPad(utils.numberToHexUnpadded(point.y), 64)
265
- }
266
- const data = hexToArray(userId + a + b + gx + gy + px + py)
267
-
268
- const entl = userId.length * 4
269
-
270
- const z = sm3(utils.concatBytes(new Uint8Array([entl >> 8 & 0x00ff, entl & 0x00ff]), data))
271
-
272
- return z
273
- }
274
-
275
- /**
276
- * sm3杂凑算法
277
- */
278
- export function getHash(hashHex: string | Uint8Array, publicKey: string, userId = '1234567812345678') {
279
- const z = getZ(publicKey, userId)
280
- // e = hash(z || msg)
281
- return bytesToHex(sm3(utils.concatBytes(z, typeof hashHex === 'string' ? hexToArray(hashHex) : hashHex)))
282
- }
283
-
284
- /**
285
- * 预计算公钥点,可用于提升加密性能
286
- * @export
287
- * @param {string} publicKey 公钥
288
- * @param windowSize 计算窗口大小,默认为 8
289
- * @returns {ProjPointType<bigint>} 预计算的点
290
- */
291
- export function precomputePublicKey(publicKey: string, windowSize?: number) {
292
- const point = sm2Curve.ProjectivePoint.fromHex(publicKey)
293
- return sm2Curve.utils.precompute(windowSize, point)
294
- }
295
-
296
- /**
297
- * 计算公钥
298
- */
299
- export function getPublicKeyFromPrivateKey(privateKey: string) {
300
- const pubKey = sm2Curve.getPublicKey(privateKey, false)
301
- const pubPad = leftPad(utils.bytesToHex(pubKey), 64)
302
- return pubPad
303
- }
304
-
305
- /**
306
- * 获取椭圆曲线点
307
- */
308
- export function getPoint() {
309
- const keypair = generateKeyPairHex()
310
- const PA = sm2Curve.ProjectivePoint.fromHex(keypair.publicKey)
311
- const k = utils.hexToNumber(keypair.privateKey)
312
-
313
- return {
314
- ...keypair,
315
- k,
316
- x1: PA!.x,
317
- }
318
- }
319
-