sm-crypto-v2 1.8.0 → 1.9.1

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/sm4/index.ts DELETED
@@ -1,322 +0,0 @@
1
- import { bytesToHex } from '@/sm3/utils'
2
- import { rotl } from '../sm2/sm3'
3
- import { arrayToHex, arrayToUtf8, hexToArray } from '../sm2/utils'
4
- import { utf8ToArray } from '../sm3'
5
-
6
- /* eslint-disable no-bitwise, no-mixed-operators, complexity */
7
- const DECRYPT = 0
8
- const ROUND = 32
9
- const BLOCK = 16
10
-
11
- const Sbox = Uint8Array.from([
12
- 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
13
- 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
14
- 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
15
- 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
16
- 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
17
- 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
18
- 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
19
- 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
20
- 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
21
- 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
22
- 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
23
- 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
24
- 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
25
- 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
26
- 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
27
- 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
28
- ])
29
-
30
- const CK = new Uint32Array([
31
- 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
32
- 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
33
- 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
34
- 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
35
- 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
36
- 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
37
- 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
38
- 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
39
- ])
40
-
41
- /**
42
- * 非线性变换
43
- */
44
- function byteSub(a: number) {
45
- return (Sbox[a >>> 24 & 0xFF] & 0xFF) << 24 |
46
- (Sbox[a >>> 16 & 0xFF] & 0xFF) << 16 |
47
- (Sbox[a >>> 8 & 0xFF] & 0xFF) << 8 |
48
- (Sbox[a & 0xFF] & 0xFF)
49
- }
50
-
51
- /**
52
- * 线性变换,加密/解密用
53
- */
54
- function l1(b: number) {
55
- return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24)
56
- }
57
-
58
- /**
59
- * 线性变换,生成轮密钥用
60
- */
61
- function l2(b: number) {
62
- return b ^ rotl(b, 13) ^ rotl(b, 23)
63
- }
64
-
65
- /**
66
- * 以一组 128 比特进行加密/解密操作
67
- */
68
- const x = new Uint32Array(4)
69
- const tmp = new Uint32Array(4)
70
- function sms4Crypt(input: Uint8Array, output: Uint8Array, roundKey: Uint32Array) {
71
- let x0 = 0, x1 = 0, x2 = 0, x3 = 0, tmp0 = 0, tmp1 = 0, tmp2 = 0, tmp3 = 0;
72
-
73
- // Unroll the first loop
74
- tmp0 = input[0] & 0xff;
75
- tmp1 = input[1] & 0xff;
76
- tmp2 = input[2] & 0xff;
77
- tmp3 = input[3] & 0xff;
78
- x0 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
79
-
80
- tmp0 = input[4] & 0xff;
81
- tmp1 = input[5] & 0xff;
82
- tmp2 = input[6] & 0xff;
83
- tmp3 = input[7] & 0xff;
84
- x1 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
85
-
86
- tmp0 = input[8] & 0xff;
87
- tmp1 = input[9] & 0xff;
88
- tmp2 = input[10] & 0xff;
89
- tmp3 = input[11] & 0xff;
90
- x2 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
91
-
92
- tmp0 = input[12] & 0xff;
93
- tmp1 = input[13] & 0xff;
94
- tmp2 = input[14] & 0xff;
95
- tmp3 = input[15] & 0xff;
96
- x3 = tmp0 << 24 | tmp1 << 16 | tmp2 << 8 | tmp3;
97
-
98
- for (let r = 0; r < 32; r += 4) {
99
- // Inlined l1 and rotl functions and avoid the mid variable
100
- tmp0 = x1 ^ x2 ^ x3 ^ roundKey[r];
101
- tmp0 = byteSub(tmp0); // byteSub is another function we should inline if possible.
102
- x0 ^= tmp0 ^ ((tmp0 << 2) | (tmp0 >>> 30)) ^ ((tmp0 << 10) | (tmp0 >>> 22)) ^ ((tmp0 << 18) | (tmp0 >>> 14)) ^ ((tmp0 << 24) | (tmp0 >>> 8));
103
-
104
- tmp1 = x2 ^ x3 ^ x0 ^ roundKey[r + 1];
105
- tmp1 = byteSub(tmp1);
106
- x1 ^= tmp1 ^ ((tmp1 << 2) | (tmp1 >>> 30)) ^ ((tmp1 << 10) | (tmp1 >>> 22)) ^ ((tmp1 << 18) | (tmp1 >>> 14)) ^ ((tmp1 << 24) | (tmp1 >>> 8));
107
-
108
- tmp2 = x3 ^ x0 ^ x1 ^ roundKey[r + 2];
109
- tmp2 = byteSub(tmp2);
110
- x2 ^= tmp2 ^ ((tmp2 << 2) | (tmp2 >>> 30)) ^ ((tmp2 << 10) | (tmp2 >>> 22)) ^ ((tmp2 << 18) | (tmp2 >>> 14)) ^ ((tmp2 << 24) | (tmp2 >>> 8));
111
-
112
- tmp3 = x0 ^ x1 ^ x2 ^ roundKey[r + 3];
113
- tmp3 = byteSub(tmp3);
114
- x3 ^= tmp3 ^ ((tmp3 << 2) | (tmp3 >>> 30)) ^ ((tmp3 << 10) | (tmp3 >>> 22)) ^ ((tmp3 << 18) | (tmp3 >>> 14)) ^ ((tmp3 << 24) | (tmp3 >>> 8));
115
- }
116
-
117
- // Unroll the last loop
118
- output[0] = x3 >>> 24 & 0xff;
119
- output[1] = x3 >>> 16 & 0xff;
120
- output[2] = x3 >>> 8 & 0xff;
121
- output[3] = x3 & 0xff;
122
-
123
- output[4] = x2 >>> 24 & 0xff;
124
- output[5] = x2 >>> 16 & 0xff;
125
- output[6] = x2 >>> 8 & 0xff;
126
- output[7] = x2 & 0xff;
127
-
128
- output[8] = x1 >>> 24 & 0xff;
129
- output[9] = x1 >>> 16 & 0xff;
130
- output[10] = x1 >>> 8 & 0xff;
131
- output[11] = x1 & 0xff;
132
-
133
- output[12] = x0 >>> 24 & 0xff;
134
- output[13] = x0 >>> 16 & 0xff;
135
- output[14] = x0 >>> 8 & 0xff;
136
- output[15] = x0 & 0xff;
137
- }
138
-
139
- /**
140
- * 密钥扩展算法
141
- */
142
- function sms4KeyExt(key: Uint8Array, roundKey: Uint32Array, cryptFlag: 0 | 1) {
143
- let x0 = 0, x1 = 0, x2 = 0, x3 = 0, mid = 0;
144
-
145
- // Unwrap the first loop and use local variables instead of the array x
146
- x0 = (key[0] & 0xff) << 24 | (key[1] & 0xff) << 16 | (key[2] & 0xff) << 8 | (key[3] & 0xff);
147
- x1 = (key[4] & 0xff) << 24 | (key[5] & 0xff) << 16 | (key[6] & 0xff) << 8 | (key[7] & 0xff);
148
- x2 = (key[8] & 0xff) << 24 | (key[9] & 0xff) << 16 | (key[10] & 0xff) << 8 | (key[11] & 0xff);
149
- x3 = (key[12] & 0xff) << 24 | (key[13] & 0xff) << 16 | (key[14] & 0xff) << 8 | (key[15] & 0xff);
150
-
151
- // 与系统参数做异或
152
- x0 ^= 0xa3b1bac6;
153
- x1 ^= 0x56aa3350;
154
- x2 ^= 0x677d9197;
155
- x3 ^= 0xb27022dc;
156
-
157
- for (let r = 0; r < 32; r += 4) {
158
- mid = x1 ^ x2 ^ x3 ^ CK[r + 0];
159
- mid = byteSub(mid); // Again, if possible, inline the byteSub function.
160
- x0 ^= mid ^ ((mid << 13) | (mid >>> 19)) ^ ((mid << 23) | (mid >>> 9));
161
- roundKey[r + 0] = x0;
162
-
163
- mid = x2 ^ x3 ^ x0 ^ CK[r + 1];
164
- mid = byteSub(mid);
165
- x1 ^= mid ^ ((mid << 13) | (mid >>> 19)) ^ ((mid << 23) | (mid >>> 9));
166
- roundKey[r + 1] = x1;
167
-
168
- mid = x3 ^ x0 ^ x1 ^ CK[r + 2];
169
- mid = byteSub(mid);
170
- x2 ^= mid ^ ((mid << 13) | (mid >>> 19)) ^ ((mid << 23) | (mid >>> 9));
171
- roundKey[r + 2] = x2;
172
-
173
- mid = x0 ^ x1 ^ x2 ^ CK[r + 3];
174
- mid = byteSub(mid);
175
- x3 ^= mid ^ ((mid << 13) | (mid >>> 19)) ^ ((mid << 23) | (mid >>> 9));
176
- roundKey[r + 3] = x3;
177
- }
178
-
179
- if (cryptFlag === DECRYPT) {
180
- for (let r = 0; r < 16; r++) {
181
- // Use destructuring to swap elements
182
- [roundKey[r], roundKey[31 - r]] = [roundKey[31 - r], roundKey[r]];
183
- }
184
- }
185
- }
186
-
187
- export interface SM4Options {
188
- padding?: 'pkcs#7' | 'pkcs#5' | 'none' | null
189
- mode?: 'cbc' | 'ecb'
190
- iv?: Uint8Array | string
191
- output?: 'string' | 'array'
192
- }
193
-
194
- const blockOutput = new Uint8Array(16)
195
- export function sm4(inArray: Uint8Array | string, key: Uint8Array | string, cryptFlag: 0 | 1, options: SM4Options = {}) {
196
- let {
197
- padding = 'pkcs#7',
198
- mode,
199
- iv = new Uint8Array(16),
200
- output
201
- } = options
202
- if (mode === 'cbc') {
203
- // CBC 模式,默认走 ECB 模式
204
- if (typeof iv === 'string') iv = hexToArray(iv)
205
- if (iv.length !== (128 / 8)) {
206
- // iv 不是 128 比特
207
- throw new Error('iv is invalid')
208
- }
209
- }
210
-
211
- // 检查 key
212
- if (typeof key === 'string') key = hexToArray(key)
213
- if (key.length !== (128 / 8)) {
214
- // key 不是 128 比特
215
- throw new Error('key is invalid')
216
- }
217
-
218
- // 检查输入
219
- if (typeof inArray === 'string') {
220
- if (cryptFlag !== DECRYPT) {
221
- // 加密,输入为 utf8 串
222
- inArray = utf8ToArray(inArray)
223
- } else {
224
- // 解密,输入为 16 进制串
225
- inArray = hexToArray(inArray)
226
- }
227
- } else {
228
- inArray = Uint8Array.from(inArray)
229
- }
230
-
231
- // 新增填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
232
- if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag !== DECRYPT) {
233
- const paddingCount = BLOCK - inArray.length % BLOCK
234
- const newArray = new Uint8Array(inArray.length + paddingCount)
235
- newArray.set(inArray, 0)
236
- for (let i = 0; i < paddingCount; i++) newArray[inArray.length + i] = paddingCount
237
- inArray = newArray
238
- }
239
-
240
- // 生成轮密钥
241
- const roundKey = new Uint32Array(ROUND)
242
- sms4KeyExt(key, roundKey, cryptFlag)
243
-
244
- let outArray = new Uint8Array(inArray.length)
245
- let lastVector = iv as Uint8Array
246
- let restLen = inArray.length
247
- let point = 0
248
- while (restLen >= BLOCK) {
249
- const input = inArray.subarray(point, point + 16)
250
-
251
- if (mode === 'cbc') {
252
- for (let i = 0; i < BLOCK; i++) {
253
- if (cryptFlag !== DECRYPT) {
254
- // 加密过程在组加密前进行异或
255
- input[i] ^= lastVector[i]
256
- }
257
- }
258
- }
259
-
260
- sms4Crypt(input, blockOutput, roundKey)
261
-
262
-
263
- for (let i = 0; i < BLOCK; i++) {
264
- if (mode === 'cbc') {
265
- if (cryptFlag === DECRYPT) {
266
- // 解密过程在组解密后进行异或
267
- blockOutput[i] ^= lastVector[i]
268
- }
269
- }
270
-
271
- outArray[point + i] = blockOutput[i]
272
- }
273
-
274
- if (mode === 'cbc') {
275
- if (cryptFlag !== DECRYPT) {
276
- // 使用上一次输出作为加密向量
277
- lastVector = blockOutput
278
- } else {
279
- // 使用上一次输入作为解密向量
280
- lastVector = input
281
- }
282
- }
283
-
284
- restLen -= BLOCK
285
- point += BLOCK
286
- }
287
-
288
- // 去除填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
289
- if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag === DECRYPT) {
290
- const len = outArray.length
291
- const paddingCount = outArray[len - 1]
292
- for (let i = 1; i <= paddingCount; i++) {
293
- if (outArray[len - i] !== paddingCount) throw new Error('padding is invalid')
294
- }
295
- outArray = outArray.slice(0, len - paddingCount)
296
- }
297
-
298
- // 调整输出
299
- if (output !== 'array') {
300
- if (cryptFlag !== DECRYPT) {
301
- // 加密,输出转 16 进制串
302
- return bytesToHex(outArray)
303
- } else {
304
- // 解密,输出转 utf8 串
305
- return arrayToUtf8(outArray)
306
- }
307
- } else {
308
- return outArray
309
- }
310
- }
311
-
312
- export function encrypt(inArray: Uint8Array | string, key: Uint8Array | string, options?: { output: 'array' } | SM4Options): Uint8Array
313
- export function encrypt(inArray: Uint8Array | string, key: Uint8Array | string, options?: { output: 'string' } | SM4Options): string
314
- export function encrypt(inArray: Uint8Array | string, key: Uint8Array | string, options: SM4Options = {}) {
315
- return sm4(inArray, key, 1, options)
316
- }
317
-
318
- export function decrypt(inArray: Uint8Array | string, key: Uint8Array | string, options?: { output: 'array' } | SM4Options): Uint8Array
319
- export function decrypt(inArray: Uint8Array | string, key: Uint8Array | string, options?: { output: 'string' } | SM4Options): string
320
- export function decrypt(inArray: Uint8Array | string, key: Uint8Array | string, options: SM4Options = {}) {
321
- return sm4(inArray, key, 0, options)
322
- }
package/tsconfig.json DELETED
@@ -1,21 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ESNext",
4
- "module": "commonjs",
5
- "lib": ["esnext"],
6
- "strict": true,
7
- "strictNullChecks": true,
8
- "esModuleInterop": true,
9
- "declaration": true,
10
- "useUnknownInCatchVariables": false,
11
- "forceConsistentCasingInFileNames": true,
12
- "skipLibCheck": true,
13
- "skipDefaultLibCheck": true,
14
- "noImplicitAny": false,
15
- "preserveSymlinks": true,
16
- "paths": {
17
- "@/*": ["./src/*"]
18
- }
19
- },
20
- "exclude": ["dist/**"]
21
- }
package/vitest.config.ts DELETED
@@ -1,22 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig(({ command, mode }) => {
4
- return {
5
- test: {
6
- alias: {
7
- '@': './src'
8
- },
9
- coverage: {
10
- provider: 'istanbul',
11
- reporter: [
12
- ['text'],
13
- ['html'],
14
- ['json-summary'],
15
- ]
16
- }
17
- },
18
- define: {
19
- __BUILD_TS__: '100000000'
20
- }
21
- };
22
- });
package/webpack.config.js DELETED
@@ -1,26 +0,0 @@
1
- const path = require('path');
2
- const webpack = require('webpack');
3
-
4
- module.exports = {
5
- entry: {
6
- sm2: './src/sm2/index.js',
7
- sm3: './src/sm3/index.js',
8
- sm4: './src/sm4/index.js',
9
- },
10
- output: {
11
- path: path.resolve(__dirname, 'dist'),
12
- filename: '[name].js',
13
- library: '[name]',
14
- libraryTarget: 'umd',
15
- },
16
- module: {
17
- loaders: [{
18
- test: /\.js$/,
19
- exclude: /node_modules/,
20
- loader: 'babel-loader'
21
- }]
22
- },
23
- plugins: [
24
- new webpack.optimize.UglifyJsPlugin(),
25
- ]
26
- };