sm-crypto-v2 1.7.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/src/sm2/kx.ts DELETED
@@ -1,83 +0,0 @@
1
- import { field, sm2Curve } from './ec';
2
- import { KeyPair, hexToArray, leftPad } from './utils';
3
- import * as utils from '@noble/curves/abstract/utils';
4
- import { sm3 } from './sm3';
5
- import { EmptyArray, getZ } from '.';
6
-
7
-
8
- // 用到的常数
9
- const wPow2 = utils.hexToNumber('80000000000000000000000000000000')
10
- const wPow2Sub1 = utils.hexToNumber('7fffffffffffffffffffffffffffffff')
11
-
12
- // from sm2 sign part, extracted for code reusable.
13
- function hkdf(z: Uint8Array, keylen: number) {
14
- let msg = new Uint8Array(keylen)
15
- let ct = 1
16
- let offset = 0
17
- let t = EmptyArray
18
- const ctShift = new Uint8Array(4)
19
- const nextT = () => {
20
- // (1) Hai = hash(z || ct)
21
- // (2) ct++
22
- ctShift[0] = ct >> 24 & 0x00ff
23
- ctShift[1] = ct >> 16 & 0x00ff
24
- ctShift[2] = ct >> 8 & 0x00ff
25
- ctShift[3] = ct & 0x00ff
26
- t = sm3(utils.concatBytes(z, ctShift))
27
- ct++
28
- offset = 0
29
- }
30
- nextT() // 先生成 Ha1
31
-
32
- for (let i = 0, len = msg.length; i < len; i++) {
33
- // t = Ha1 || Ha2 || Ha3 || Ha4
34
- if (offset === t.length) nextT()
35
-
36
- // 输出 stream
37
- msg[i] = t[offset++] & 0xff
38
- }
39
- return msg
40
- }
41
-
42
- export function calculateSharedKey(
43
- keypairA: KeyPair,
44
- ephemeralKeypairA: KeyPair,
45
- publicKeyB: string,
46
- ephemeralPublicKeyB: string,
47
- sharedKeyLength: number,
48
- isRecipient = false,
49
- idA: string = '1234567812345678',
50
- idB: string = '1234567812345678',
51
- ) {
52
- const RA = sm2Curve.ProjectivePoint.fromHex(ephemeralKeypairA.publicKey)
53
- const RB = sm2Curve.ProjectivePoint.fromHex(ephemeralPublicKeyB)
54
- // const PA = sm2Curve.ProjectivePoint.fromHex(keypairA.publicKey) // 用不到
55
- const PB = sm2Curve.ProjectivePoint.fromHex(publicKeyB)
56
- let ZA = getZ(keypairA.publicKey, idA)
57
- let ZB = getZ(publicKeyB, idB)
58
- if (isRecipient) {
59
- [ZA, ZB] = [ZB, ZA];
60
- }
61
- const rA = utils.hexToNumber(ephemeralKeypairA.privateKey)
62
- const dA = utils.hexToNumber(keypairA.privateKey)
63
- // 1.先算 tA
64
- const x1 = RA.x
65
- // x1_ = 2^w + (x1 & (2^w - 1))
66
- const x1_ = wPow2 + (x1 & wPow2Sub1)
67
- // tA = (dA + x1b * rA) mod n
68
- const tA = field.add(dA, field.mulN(x1_, rA))
69
-
70
- // 2.算 U
71
- // x2_ = 2^w + (x2 & (2^w - 1))
72
- const x2 = RB.x
73
- const x2_ = field.add(wPow2, (x2 & wPow2Sub1))
74
- // U = [h * tA](PB + x2_ * RB)
75
- const U = RB.multiply(x2_).add(PB).multiply(tA)
76
-
77
- // 3.算 KDF
78
- // KA = KDF(xU || yU || ZA || ZB, kLen)
79
- const xU = hexToArray(leftPad(utils.numberToHexUnpadded(U.x), 64))
80
- const yU = hexToArray(leftPad(utils.numberToHexUnpadded(U.y), 64))
81
- const KA = hkdf(utils.concatBytes(xU, yU, ZA, ZB), sharedKeyLength)
82
- return KA
83
- }
package/src/sm2/rng.ts DELETED
@@ -1,77 +0,0 @@
1
- // Secure RNG Generator wrapper
2
- // 1. Use native sync API if available
3
- // 2. Use async API and maintain number pool if available
4
- // 3. Throw error if none of above available
5
- // Web: globalThis.crypto
6
- // Node: async import("crypto").webcrypto
7
- // Mini Program: wx.getRandomValues
8
- declare module wx {
9
- function getRandomValues(options: {
10
- length: number;
11
- success: (res: { randomValues: ArrayBuffer }) => void;
12
- }): void;
13
- }
14
-
15
- const DEFAULT_PRNG_POOL_SIZE = 16384
16
- let prngPool = new Uint8Array(0)
17
- let _syncCrypto: typeof import('crypto')['webcrypto']
18
- export async function initRNGPool() {
19
- if ('crypto' in globalThis) {
20
- _syncCrypto = globalThis.crypto
21
- return // no need to use pooling
22
- }
23
- if (prngPool.length > DEFAULT_PRNG_POOL_SIZE / 2) return // there is sufficient number
24
- // we always populate full pool size
25
- // since numbers may be consumed during micro tasks.
26
- if ('wx' in globalThis && 'getRandomValues' in globalThis.wx) {
27
- prngPool = await new Promise(r => {
28
- wx.getRandomValues({
29
- length: DEFAULT_PRNG_POOL_SIZE,
30
- success(res) {
31
- r(new Uint8Array(res.randomValues));
32
- }
33
- });
34
- });
35
- } else {
36
- // check if node or browser, use webcrypto if available
37
- try {
38
- // node 19+ and browser
39
- if (globalThis.crypto) {
40
- _syncCrypto = globalThis.crypto
41
- } else {
42
- // node below 19
43
- const crypto = await import(/* webpackIgnore: true */ 'crypto');
44
- _syncCrypto = crypto.webcrypto
45
- }
46
- const array = new Uint8Array(DEFAULT_PRNG_POOL_SIZE);
47
- _syncCrypto.getRandomValues(array);
48
- prngPool = array;
49
- } catch (error) {
50
- throw new Error('no available csprng, abort.');
51
- }
52
- }
53
- }
54
-
55
- initRNGPool()
56
-
57
- function consumePool(length: number): Uint8Array {
58
- if (prngPool.length > length) {
59
- const prng = prngPool.slice(0, length)
60
- prngPool = prngPool.slice(length)
61
- initRNGPool()
62
- return prng
63
- } else {
64
- throw new Error('random number pool is not ready or insufficient, prevent getting too long random values or too often.')
65
- }
66
- }
67
-
68
- export function randomBytes(length = 0): Uint8Array {
69
- const array = new Uint8Array(length);
70
- if (_syncCrypto) {
71
- return _syncCrypto.getRandomValues(array);
72
- } else {
73
- // no sync crypto available, use async pool
74
- const result = consumePool(length)
75
- return result
76
- }
77
- }
package/src/sm2/sm3.ts DELETED
@@ -1,241 +0,0 @@
1
- // import assert from './_assert.js';
2
- import { Hash, createView, Input, toBytes, wrapConstructor } from '../sm3/utils.js';
3
-
4
- const BoolA = (A: number, B: number, C: number) => ((A & B) | (A & C)) | (B & C)
5
- const BoolB = (A: number, B: number, C: number) => ((A ^ B) ^ C)
6
- const BoolC = (A: number, B: number, C: number) => (A & B) | ((~A) & C)
7
- // Polyfill for Safari 14
8
- function setBigUint64(view: DataView, byteOffset: number, value: bigint, isLE: boolean): void {
9
- if (typeof view.setBigUint64 === 'function') return view.setBigUint64(byteOffset, value, isLE);
10
- const _32n = BigInt(32);
11
- const _u32_max = BigInt(0xffffffff);
12
- const wh = Number((value >> _32n) & _u32_max);
13
- const wl = Number(value & _u32_max);
14
- const h = isLE ? 4 : 0;
15
- const l = isLE ? 0 : 4;
16
- view.setUint32(byteOffset + h, wh, isLE);
17
- view.setUint32(byteOffset + l, wl, isLE);
18
- }
19
-
20
- /**
21
- * 循环左移
22
- */
23
- export function rotl(x: number, n: number) {
24
- const s = n & 31
25
- return (x << s) | (x >>> (32 - s))
26
- }
27
-
28
- /**
29
- * 二进制异或运算
30
- */
31
- function xor(x: Uint8Array, y: Uint8Array) {
32
- const result = new Uint8Array(x.length)
33
- for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] ^ y[i]) & 0xff
34
- return result
35
- }
36
-
37
- /**
38
- * 压缩函数中的置换函数 P0(X) = X xor (X <<< 9) xor (X <<< 17)
39
- */
40
- function P0(X: number) {
41
- return (X ^ rotl(X, 9)) ^ rotl(X, 17)
42
- }
43
-
44
- /**
45
- * 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)
46
- */
47
- function P1(X: number) {
48
- return (X ^ rotl(X, 15)) ^ rotl(X, 23)
49
- }
50
-
51
- // from noble-hashes (https://github.com/paulmillr/noble-hashes#hmac)
52
- /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
53
-
54
- // Base SHA2 class (RFC 6234)
55
- export abstract class SHA2<T extends SHA2<T>> extends Hash<T> {
56
- protected abstract process(buf: DataView, offset: number): void;
57
- protected abstract get(): number[];
58
- protected abstract set(...args: number[]): void;
59
- abstract destroy(): void;
60
- protected abstract roundClean(): void;
61
- // For partial updates less than block size
62
- protected buffer: Uint8Array;
63
- protected view: DataView;
64
- protected finished = false;
65
- protected length = 0;
66
- protected pos = 0;
67
- protected destroyed = false;
68
-
69
- constructor(
70
- readonly blockLen: number,
71
- public outputLen: number,
72
- readonly padOffset: number,
73
- readonly isLE: boolean
74
- ) {
75
- super();
76
- this.buffer = new Uint8Array(blockLen);
77
- this.view = createView(this.buffer);
78
- }
79
- update(data: Input): this {
80
- const { view, buffer, blockLen } = this;
81
- data = toBytes(data);
82
- const len = data.length;
83
- for (let pos = 0; pos < len; ) {
84
- const take = Math.min(blockLen - this.pos, len - pos);
85
- // Fast path: we have at least one block in input, cast it to view and process
86
- if (take === blockLen) {
87
- const dataView = createView(data);
88
- for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos);
89
- continue;
90
- }
91
- buffer.set(data.subarray(pos, pos + take), this.pos);
92
- this.pos += take;
93
- pos += take;
94
- if (this.pos === blockLen) {
95
- this.process(view, 0);
96
- this.pos = 0;
97
- }
98
- }
99
- this.length += data.length;
100
- this.roundClean();
101
- return this;
102
- }
103
- digestInto(out: Uint8Array) {
104
- this.finished = true;
105
- // Padding
106
- // We can avoid allocation of buffer for padding completely if it
107
- // was previously not allocated here. But it won't change performance.
108
- const { buffer, view, blockLen, isLE } = this;
109
- let { pos } = this;
110
- // append the bit '1' to the message
111
- buffer[pos++] = 0b10000000;
112
- this.buffer.subarray(pos).fill(0);
113
- // we have less than padOffset left in buffer, so we cannot put length in current block, need process it and pad again
114
- if (this.padOffset > blockLen - pos) {
115
- this.process(view, 0);
116
- pos = 0;
117
- }
118
- // Pad until full block byte with zeros
119
- for (let i = pos; i < blockLen; i++) buffer[i] = 0;
120
- // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
121
- // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
122
- // So we just write lowest 64 bits of that value.
123
- setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
124
- this.process(view, 0);
125
- const oview = createView(out);
126
- const len = this.outputLen;
127
- // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT
128
- if (len % 4) throw new Error('_sha2: outputLen should be aligned to 32bit');
129
- const outLen = len / 4;
130
- const state = this.get();
131
- if (outLen > state.length) throw new Error('_sha2: outputLen bigger than state');
132
- for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE);
133
- }
134
- digest() {
135
- const { buffer, outputLen } = this;
136
- this.digestInto(buffer);
137
- const res = buffer.slice(0, outputLen);
138
- this.destroy();
139
- return res;
140
- }
141
- _cloneInto(to?: T): T {
142
- to ||= new (this.constructor as any)() as T;
143
- to.set(...this.get());
144
- const { blockLen, buffer, length, finished, destroyed, pos } = this;
145
- to.length = length;
146
- to.pos = pos;
147
- to.finished = finished;
148
- to.destroyed = destroyed;
149
- if (length % blockLen) to.buffer.set(buffer);
150
- return to;
151
- }
152
- }
153
-
154
- const IV = new Uint32Array([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e])
155
- const SM3_W = new Uint32Array(68)
156
- const SM3_M = new Uint32Array(64)
157
-
158
- const T1 = 0x79cc4519
159
- const T2 = 0x7a879d8a
160
-
161
- class SM3 extends SHA2<SM3> {
162
- // We cannot use array here since array allows indexing by variable
163
- // which means optimizer/compiler cannot use registers.
164
- A = IV[0] | 0;
165
- B = IV[1] | 0;
166
- C = IV[2] | 0;
167
- D = IV[3] | 0;
168
- E = IV[4] | 0;
169
- F = IV[5] | 0;
170
- G = IV[6] | 0;
171
- H = IV[7] | 0;
172
-
173
- constructor() {
174
- super(64, 32, 8, false);
175
- }
176
- protected get(): [number, number, number, number, number, number, number, number] {
177
- const { A, B, C, D, E, F, G, H } = this;
178
- return [A, B, C, D, E, F, G, H];
179
- }
180
- // prettier-ignore
181
- protected set(
182
- A: number, B: number, C: number, D: number, E: number, F: number, G: number, H: number
183
- ) {
184
- this.A = A | 0;
185
- this.B = B | 0;
186
- this.C = C | 0;
187
- this.D = D | 0;
188
- this.E = E | 0;
189
- this.F = F | 0;
190
- this.G = G | 0;
191
- this.H = H | 0;
192
- }
193
- protected process(view: DataView, offset: number): void {
194
- // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array
195
- for (let i = 0; i < 16; i++, offset += 4) SM3_W[i] = view.getUint32(offset, false);
196
- for (let i = 16; i < 68; i++) {
197
- SM3_W[i] = (P1((SM3_W[i- 16] ^ SM3_W[i - 9]) ^ rotl(SM3_W[i - 3], 15)) ^ rotl(SM3_W[i - 13], 7)) ^ SM3_W[i - 6]
198
- }
199
- for (let i = 0; i < 64; i++) {
200
- SM3_M[i] = SM3_W[i] ^ SM3_W[i + 4]
201
- }
202
- // Compression function main loop, 64 rounds
203
- let { A, B, C, D, E, F, G, H } = this;
204
- for (let j = 0; j < 64; j++) {
205
- let small = j >= 0 && j <= 15
206
- let T = small ? T1 : T2
207
- let SS1 = rotl(rotl(A, 12) + E + rotl(T, j), 7)
208
- let SS2 = SS1 ^ rotl(A, 12)
209
-
210
- let TT1 = ((small ? BoolB(A, B, C) : BoolA(A, B, C)) + D + SS2 + SM3_M[j]) | 0
211
- let TT2 = ((small ? BoolB(E, F, G) : BoolC(E, F, G)) + H + SS1 + SM3_W[j]) | 0
212
-
213
- D = C
214
- C = rotl(B, 9)
215
- B = A
216
- A = TT1
217
- H = G
218
- G = rotl(F, 19)
219
- F = E
220
- E = P0(TT2)
221
- }
222
- // Add the compressed chunk to the current hash value
223
- A = (A ^ this.A) | 0;
224
- B = (B ^ this.B) | 0;
225
- C = (C ^ this.C) | 0;
226
- D = (D ^ this.D) | 0;
227
- E = (E ^ this.E) | 0;
228
- F = (F ^ this.F) | 0;
229
- G = (G ^ this.G) | 0;
230
- H = (H ^ this.H) | 0;
231
- this.set(A, B, C, D, E, F, G, H);
232
- }
233
- protected roundClean() {
234
- SM3_W.fill(0);
235
- }
236
- destroy() {
237
- this.set(0, 0, 0, 0, 0, 0, 0, 0);
238
- this.buffer.fill(0);
239
- }
240
- }
241
- export const sm3 = wrapConstructor(() => new SM3());
package/src/sm2/utils.ts DELETED
@@ -1,164 +0,0 @@
1
- /* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
2
- import * as utils from '@noble/curves/abstract/utils';
3
-
4
- import { sm2Curve, sm2Fp } from './ec';
5
- import { mod } from '@noble/curves/abstract/modular';
6
- import { ONE, TWO, ZERO } from './bn';
7
-
8
- export interface KeyPair {
9
- privateKey: string
10
- publicKey: string
11
- }
12
-
13
- /**
14
- * 生成密钥对:publicKey = privateKey * G
15
- */
16
- export function generateKeyPairHex(str?: string): KeyPair {
17
- const privateKey = str ? utils.numberToBytesBE((mod(BigInt(str), ONE) + ONE), 32) : sm2Curve.utils.randomPrivateKey()
18
- // const random = typeof a === 'string' ? new BigInteger(a, b) :
19
- // a ? new BigInteger(a, b!, c!) : new BigInteger(n.bitLength(), rng)
20
- // const d = random.mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数
21
- // const privateKey = leftPad(d.toString(16), 64)
22
-
23
- // const P = G!.multiply(d) // P = dG,p 为公钥,d 为私钥
24
- // const Px = leftPad(P.getX().toBigInteger().toString(16), 64)
25
- // const Py = leftPad(P.getY().toBigInteger().toString(16), 64)
26
- // const publicKey = '04' + Px + Py
27
- const publicKey = sm2Curve.getPublicKey(privateKey, false);
28
- const privPad = leftPad(utils.bytesToHex(privateKey), 64)
29
- const pubPad = leftPad(utils.bytesToHex(publicKey), 64)
30
- return {privateKey: privPad, publicKey: pubPad}
31
- }
32
-
33
- /**
34
- * 生成压缩公钥
35
- */
36
- export function compressPublicKeyHex(s: string) {
37
- if (s.length !== 130) throw new Error('Invalid public key to compress')
38
-
39
- const len = (s.length - 2) / 2
40
- const xHex = s.substring(2, 2 + len)
41
- const y = utils.hexToNumber(s.substring(len + 2, len + len + 2))
42
-
43
- let prefix = '03'
44
- if (mod(y, TWO) === ZERO) prefix = '02'
45
- return prefix + xHex
46
- }
47
-
48
- /**
49
- * utf8串转16进制串
50
- */
51
- export function utf8ToHex(input: string) {
52
- input = decodeURIComponent(encodeURIComponent(input))
53
-
54
- const length = input.length
55
-
56
- // 转换到字数组
57
- const words = new Uint32Array((length >>> 2) + 1)
58
- for (let i = 0; i < length; i++) {
59
- words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8)
60
- }
61
-
62
- // 转换到16进制
63
- const hexChars: string[]= []
64
- for (let i = 0; i < length; i++) {
65
- const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
66
- hexChars.push((bite >>> 4).toString(16))
67
- hexChars.push((bite & 0x0f).toString(16))
68
- }
69
-
70
- return hexChars.join('')
71
- }
72
-
73
- /**
74
- * 补全16进制字符串
75
- */
76
- export function leftPad(input: string, num: number) {
77
- if (input.length >= num) return input
78
-
79
- return (new Array(num - input.length + 1)).join('0') + input
80
- }
81
-
82
- /**
83
- * 转成16进制串
84
- */
85
- export function arrayToHex(arr: number[]) {
86
- return arr.map(item => {
87
- const hex = item.toString(16)
88
- return hex.length === 1 ? '0' + hex : hex
89
- }).join('')
90
- }
91
-
92
- /**
93
- * 转成utf8串
94
- */
95
- export function arrayToUtf8(arr: Uint8Array) {
96
- const str: string[] = []
97
- for (let i = 0, len = arr.length; i < len; i++) {
98
- if (arr[i] >= 0xf0 && arr[i] <= 0xf7) {
99
- // 四字节
100
- str.push(String.fromCodePoint(((arr[i] & 0x07) << 18) + ((arr[i + 1] & 0x3f) << 12) + ((arr[i + 2] & 0x3f) << 6) + (arr[i + 3] & 0x3f)))
101
- i += 3
102
- } else if (arr[i] >= 0xe0 && arr[i] <= 0xef) {
103
- // 三字节
104
- str.push(String.fromCodePoint(((arr[i] & 0x0f) << 12) + ((arr[i + 1] & 0x3f) << 6) + (arr[i + 2] & 0x3f)))
105
- i += 2
106
- } else if (arr[i] >= 0xc0 && arr[i] <= 0xdf) {
107
- // 双字节
108
- str.push(String.fromCodePoint(((arr[i] & 0x1f) << 6) + (arr[i + 1] & 0x3f)))
109
- i++
110
- } else {
111
- // 单字节
112
- str.push(String.fromCodePoint(arr[i]))
113
- }
114
- }
115
-
116
- return str.join('')
117
- }
118
-
119
- /**
120
- * 转成字节数组
121
- */
122
- export function hexToArray(hexStr: string) {
123
- let hexStrLength = hexStr.length
124
-
125
- if (hexStrLength % 2 !== 0) {
126
- hexStr = leftPad(hexStr, hexStrLength + 1)
127
- }
128
-
129
- hexStrLength = hexStr.length
130
- const wordLength = hexStrLength / 2
131
- const words = new Uint8Array(wordLength)
132
-
133
- for (let i = 0; i < wordLength; i++) {
134
- words[i] = (parseInt(hexStr.substring(i * 2, i * 2 + 2), 16))
135
- }
136
- return words
137
- }
138
-
139
- /**
140
- * 验证公钥是否为椭圆曲线上的点
141
- */
142
- export function verifyPublicKey(publicKey: string) {
143
- const point = sm2Curve.ProjectivePoint.fromHex(publicKey)
144
- if (!point) return false
145
- try {
146
- point.assertValidity()
147
- return true
148
- } catch (error) {
149
- return false
150
- }
151
- }
152
-
153
- /**
154
- * 验证公钥是否等价,等价返回true
155
- */
156
- export function comparePublicKeyHex(publicKey1: string, publicKey2: string) {
157
- const point1 = sm2Curve.ProjectivePoint.fromHex(publicKey1)
158
- if (!point1) return false
159
-
160
- const point2 = sm2Curve.ProjectivePoint.fromHex(publicKey2)
161
- if (!point2) return false
162
-
163
- return point1.equals(point2)
164
- }
package/src/sm3/index.ts DELETED
@@ -1,72 +0,0 @@
1
- import { hmac } from '@/sm2/hmac'
2
- import { sm3 as sm2sm3 } from '../sm2/sm3'
3
- import { hexToArray } from '../sm2/utils'
4
- import { bytesToHex } from './utils'
5
-
6
- /**
7
- * 补全16进制字符串
8
- */
9
- // function leftPad(input, num) {
10
- // if (input.length >= num) return input
11
-
12
- // return (new Array(num - input.length + 1)).join('0') + input
13
- // }
14
-
15
- /**
16
- * utf8 串转字节数组
17
- */
18
- export function utf8ToArray(str: string) {
19
- const arr: number[] = []
20
-
21
- for (let i = 0, len = str.length; i < len; i++) {
22
- const point = str.codePointAt(i)!
23
-
24
- if (point <= 0x007f) {
25
- // 单字节,标量值:00000000 00000000 0zzzzzzz
26
- arr.push(point)
27
- } else if (point <= 0x07ff) {
28
- // 双字节,标量值:00000000 00000yyy yyzzzzzz
29
- arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)
30
- arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
31
- } else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {
32
- // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
33
- arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)
34
- arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)
35
- arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
36
- } else if (point >= 0x010000 && point <= 0x10FFFF) {
37
- // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
38
- i++
39
- arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)
40
- arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)
41
- arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)
42
- arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)
43
- } else {
44
- // 五、六字节,暂时不支持
45
- arr.push(point)
46
- throw new Error('input is not supported')
47
- }
48
- }
49
-
50
- return new Uint8Array(arr)
51
- }
52
-
53
- export function sm3(input: string | Uint8Array, options?: {
54
- key: Uint8Array | string
55
- mode?: 'hmac' | 'mac'
56
- }) {
57
- input = typeof input === 'string' ? utf8ToArray(input) : input
58
-
59
- if (options) {
60
- const mode = options.mode || 'hmac'
61
- if (mode !== 'hmac') throw new Error('invalid mode')
62
-
63
- let key = options.key
64
- if (!key) throw new Error('invalid key')
65
-
66
- key = typeof key === 'string' ? hexToArray(key) : key
67
- return bytesToHex(hmac(sm2sm3, key, input));
68
- }
69
- return bytesToHex(sm2sm3(input))
70
- }
71
-
72
- export default sm3