first commit
0 parents
Showing
43 changed files
with
4106 additions
and
0 deletions
.babelrc
0 → 100644
.eslintrc.js
0 → 100644
1 | module.exports = { | ||
2 | 'extends': [ | ||
3 | 'airbnb-base', | ||
4 | 'plugin:promise/recommended' | ||
5 | ], | ||
6 | 'parserOptions': { | ||
7 | 'ecmaVersion': 9, | ||
8 | 'ecmaFeatures': { | ||
9 | 'jsx': false | ||
10 | }, | ||
11 | 'sourceType': 'module' | ||
12 | }, | ||
13 | 'env': { | ||
14 | 'es6': true, | ||
15 | 'node': true, | ||
16 | 'jest': true | ||
17 | }, | ||
18 | 'plugins': [ | ||
19 | 'import', | ||
20 | 'node', | ||
21 | 'promise' | ||
22 | ], | ||
23 | 'rules': { | ||
24 | 'arrow-parens': 'off', | ||
25 | 'comma-dangle': [ | ||
26 | 'error', | ||
27 | 'only-multiline' | ||
28 | ], | ||
29 | 'complexity': ['error', 10], | ||
30 | 'func-names': 'off', | ||
31 | 'global-require': 'off', | ||
32 | 'handle-callback-err': [ | ||
33 | 'error', | ||
34 | '^(err|error)$' | ||
35 | ], | ||
36 | 'import/no-unresolved': [ | ||
37 | 'error', | ||
38 | { | ||
39 | 'caseSensitive': true, | ||
40 | 'commonjs': true, | ||
41 | 'ignore': ['^[^.]'] | ||
42 | } | ||
43 | ], | ||
44 | 'import/prefer-default-export': 'off', | ||
45 | 'linebreak-style': 'off', | ||
46 | 'no-catch-shadow': 'error', | ||
47 | 'no-continue': 'off', | ||
48 | 'no-div-regex': 'warn', | ||
49 | 'no-else-return': 'off', | ||
50 | 'no-param-reassign': 'off', | ||
51 | 'no-plusplus': 'off', | ||
52 | 'no-shadow': 'off', | ||
53 | 'no-multi-assign': 'off', | ||
54 | 'no-underscore-dangle': 'off', | ||
55 | 'node/no-deprecated-api': 'error', | ||
56 | 'node/process-exit-as-throw': 'error', | ||
57 | 'object-curly-spacing': [ | ||
58 | 'error', | ||
59 | 'never' | ||
60 | ], | ||
61 | 'operator-linebreak': [ | ||
62 | 'error', | ||
63 | 'after', | ||
64 | { | ||
65 | 'overrides': { | ||
66 | ':': 'before', | ||
67 | '?': 'before' | ||
68 | } | ||
69 | } | ||
70 | ], | ||
71 | 'prefer-arrow-callback': 'off', | ||
72 | 'prefer-destructuring': 'off', | ||
73 | 'prefer-template': 'off', | ||
74 | 'quote-props': [ | ||
75 | 1, | ||
76 | 'as-needed', | ||
77 | { | ||
78 | 'unnecessary': true | ||
79 | } | ||
80 | ], | ||
81 | 'semi': [ | ||
82 | 'error', | ||
83 | 'never' | ||
84 | ], | ||
85 | 'max-len': 'off', | ||
86 | }, | ||
87 | 'globals': { | ||
88 | 'window': true, | ||
89 | 'document': true, | ||
90 | 'App': true, | ||
91 | 'Page': true, | ||
92 | 'Component': true, | ||
93 | 'Behavior': true | ||
94 | } | ||
95 | } |
.gitignore
0 → 100644
.history/package_20210804210329.json
0 → 100644
1 | { | ||
2 | "name": "@ddn/sm-crypto", | ||
3 | "version": "0.0.1", | ||
4 | "description": "@ddn/sm-crypto,基于sm-crypto。", | ||
5 | "main": "src/index.js", | ||
6 | "scripts": { | ||
7 | "prepublish": "npm run build", | ||
8 | "test": "jest ./test/*", | ||
9 | "lint": "eslint \"src/**/*.js\" --fix", | ||
10 | "build": "npm run lint && webpack" | ||
11 | }, | ||
12 | "repository": { | ||
13 | "type": "git", | ||
14 | "url": "git+https://github.com/ddnlink" | ||
15 | }, | ||
16 | "keywords": [ | ||
17 | "ddn", | ||
18 | "sm", | ||
19 | "js", | ||
20 | "crypto" | ||
21 | ], | ||
22 | "jest": { | ||
23 | "testEnvironment": "jsdom", | ||
24 | "testURL": "https://jest.test" | ||
25 | }, | ||
26 | "author": "creazy", | ||
27 | "license": "MIT", | ||
28 | "dependencies": { | ||
29 | "jsbn": "^1.1.0" | ||
30 | }, | ||
31 | "devDependencies": { | ||
32 | "babel-core": "^6.26.0", | ||
33 | "babel-loader": "^7.1.2", | ||
34 | "babel-preset-es2015": "^6.24.1", | ||
35 | "jest": "^22.1.4", | ||
36 | "webpack": "^3.10.0", | ||
37 | "eslint": "^5.3.0", | ||
38 | "eslint-config-airbnb-base": "13.1.0", | ||
39 | "eslint-plugin-import": "^2.14.0", | ||
40 | "eslint-plugin-node": "^7.0.1", | ||
41 | "eslint-plugin-promise": "^3.8.0" | ||
42 | } | ||
43 | } |
.history/package_20210929075608.json
0 → 100644
1 | { | ||
2 | "name": "@ddn/sm-crypto", | ||
3 | "version": "0.0.1", | ||
4 | "description": "@ddn/sm-crypto,基于sm-crypto。", | ||
5 | "main": "src/index.js", | ||
6 | "scripts": { | ||
7 | "prepublish": "npm run build", | ||
8 | "test": "jest ./test/*", | ||
9 | "lint": "eslint \"src/**/*.js\" --fix", | ||
10 | "build": "npm run lint && webpack" | ||
11 | }, | ||
12 | "repository": { | ||
13 | "type": "git", | ||
14 | "url": "git+https://github.com/ddnlink" | ||
15 | }, | ||
16 | "files": [ | ||
17 | "dist", | ||
18 | "README.md" | ||
19 | ], | ||
20 | "keywords": [ | ||
21 | "ddn", | ||
22 | "sm", | ||
23 | "js", | ||
24 | "crypto" | ||
25 | ], | ||
26 | "jest": { | ||
27 | "testEnvironment": "jsdom", | ||
28 | "testURL": "https://jest.test" | ||
29 | }, | ||
30 | "author": "creazy", | ||
31 | "license": "MIT", | ||
32 | "dependencies": { | ||
33 | "jsbn": "^1.1.0" | ||
34 | }, | ||
35 | "devDependencies": { | ||
36 | "babel-core": "^6.26.0", | ||
37 | "babel-loader": "^7.1.2", | ||
38 | "babel-preset-es2015": "^6.24.1", | ||
39 | "jest": "^22.1.4", | ||
40 | "webpack": "^3.10.0", | ||
41 | "eslint": "^5.3.0", | ||
42 | "eslint-config-airbnb-base": "13.1.0", | ||
43 | "eslint-plugin-import": "^2.14.0", | ||
44 | "eslint-plugin-node": "^7.0.1", | ||
45 | "eslint-plugin-promise": "^3.8.0" | ||
46 | } | ||
47 | } |
.history/package_20210929080331.json
0 → 100644
1 | { | ||
2 | "name": "@ddn/sm-crypto", | ||
3 | "version": "0.0.1", | ||
4 | "description": "@ddn/sm-crypto,基于sm-crypto。", | ||
5 | "main": "dist/index.js", | ||
6 | "scripts": { | ||
7 | "prepublish": "npm run build", | ||
8 | "test": "jest ./test/*", | ||
9 | "lint": "eslint \"src/**/*.js\" --fix", | ||
10 | "build": "npm run lint && webpack" | ||
11 | }, | ||
12 | "repository": { | ||
13 | "type": "git", | ||
14 | "url": "git+https://github.com/ddnlink" | ||
15 | }, | ||
16 | "files": [ | ||
17 | "dist", | ||
18 | "README.md" | ||
19 | ], | ||
20 | "keywords": [ | ||
21 | "ddn", | ||
22 | "sm", | ||
23 | "js", | ||
24 | "crypto" | ||
25 | ], | ||
26 | "jest": { | ||
27 | "testEnvironment": "jsdom", | ||
28 | "testURL": "https://jest.test" | ||
29 | }, | ||
30 | "author": "creazy", | ||
31 | "license": "MIT", | ||
32 | "dependencies": { | ||
33 | "jsbn": "^1.1.0" | ||
34 | }, | ||
35 | "devDependencies": { | ||
36 | "babel-core": "^6.26.0", | ||
37 | "babel-loader": "^7.1.2", | ||
38 | "babel-preset-es2015": "^6.24.1", | ||
39 | "jest": "^22.1.4", | ||
40 | "webpack": "^3.10.0", | ||
41 | "eslint": "^5.3.0", | ||
42 | "eslint-config-airbnb-base": "13.1.0", | ||
43 | "eslint-plugin-import": "^2.14.0", | ||
44 | "eslint-plugin-node": "^7.0.1", | ||
45 | "eslint-plugin-promise": "^3.8.0" | ||
46 | } | ||
47 | } |
.history/src/sm2/ec_20210804182222.js
0 → 100644
1 | /* eslint-disable no-case-declarations, max-len */ | ||
2 | const {BigInteger} = require('jsbn') | ||
3 | |||
4 | /** | ||
5 | * thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/ | ||
6 | * | ||
7 | * Basic Javascript Elliptic Curve implementation | ||
8 | * Ported loosely from BouncyCastle's Java EC code | ||
9 | * Only Fp curves implemented for now | ||
10 | */ | ||
11 | |||
12 | const THREE = new BigInteger('3') | ||
13 | |||
14 | /** | ||
15 | * 椭圆曲线域元素 | ||
16 | */ | ||
17 | class ECFieldElementFp { | ||
18 | constructor(q, x) { | ||
19 | this.x = x | ||
20 | this.q = q | ||
21 | // TODO if (x.compareTo(q) >= 0) error | ||
22 | } | ||
23 | |||
24 | /** | ||
25 | * 判断相等 | ||
26 | */ | ||
27 | equals(other) { | ||
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 | } | ||
80 | } | ||
81 | |||
82 | class ECPointFp { | ||
83 | constructor(curve, x, y, z) { | ||
84 | this.curve = curve | ||
85 | this.x = x | ||
86 | this.y = y | ||
87 | // 标准射影坐标系:zinv == null 或 z * zinv == 1 | ||
88 | this.z = z == null ? BigInteger.ONE : z | ||
89 | this.zinv = null | ||
90 | // TODO: compression flag | ||
91 | } | ||
92 | |||
93 | getX() { | ||
94 | if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q) | ||
95 | |||
96 | return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q)) | ||
97 | } | ||
98 | |||
99 | getY() { | ||
100 | if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q) | ||
101 | |||
102 | return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q)) | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * 判断相等 | ||
107 | */ | ||
108 | equals(other) { | ||
109 | if (other === this) return true | ||
110 | if (this.isInfinity()) return other.isInfinity() | ||
111 | if (other.isInfinity()) return this.isInfinity() | ||
112 | |||
113 | // u = y2 * z1 - y1 * z2 | ||
114 | const u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q) | ||
115 | if (!u.equals(BigInteger.ZERO)) return false | ||
116 | |||
117 | // v = x2 * z1 - x1 * z2 | ||
118 | const v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q) | ||
119 | return v.equals(BigInteger.ZERO) | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * 是否是无穷远点 | ||
124 | */ | ||
125 | isInfinity() { | ||
126 | if ((this.x === null) && (this.y === null)) return true | ||
127 | return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO) | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * 取反,x 轴对称点 | ||
132 | */ | ||
133 | negate() { | ||
134 | return new ECPointFp(this.curve, this.x, this.y.negate(), this.z) | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * 相加 | ||
139 | * | ||
140 | * 标准射影坐标系: | ||
141 | * | ||
142 | * λ1 = x1 * z2 | ||
143 | * λ2 = x2 * z1 | ||
144 | * λ3 = λ1 − λ2 | ||
145 | * λ4 = y1 * z2 | ||
146 | * λ5 = y2 * z1 | ||
147 | * λ6 = λ4 − λ5 | ||
148 | * λ7 = λ1 + λ2 | ||
149 | * λ8 = z1 * z2 | ||
150 | * λ9 = λ3^2 | ||
151 | * λ10 = λ3 * λ9 | ||
152 | * λ11 = λ8 * λ6^2 − λ7 * λ9 | ||
153 | * x3 = λ3 * λ11 | ||
154 | * y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10 | ||
155 | * z3 = λ10 * λ8 | ||
156 | */ | ||
157 | add(b) { | ||
158 | if (this.isInfinity()) return b | ||
159 | if (b.isInfinity()) return this | ||
160 | |||
161 | const x1 = this.x.toBigInteger() | ||
162 | const y1 = this.y.toBigInteger() | ||
163 | const z1 = this.z | ||
164 | const x2 = b.x.toBigInteger() | ||
165 | const y2 = b.y.toBigInteger() | ||
166 | const z2 = b.z | ||
167 | const q = this.curve.q | ||
168 | |||
169 | const w1 = x1.multiply(z2).mod(q) | ||
170 | const w2 = x2.multiply(z1).mod(q) | ||
171 | const w3 = w1.subtract(w2) | ||
172 | const w4 = y1.multiply(z2).mod(q) | ||
173 | const w5 = y2.multiply(z1).mod(q) | ||
174 | const w6 = w4.subtract(w5) | ||
175 | |||
176 | if (BigInteger.ZERO.equals(w3)) { | ||
177 | if (BigInteger.ZERO.equals(w6)) { | ||
178 | return this.twice() // this == b,计算自加 | ||
179 | } | ||
180 | return this.curve.infinity // this == -b,则返回无穷远点 | ||
181 | } | ||
182 | |||
183 | const w7 = w1.add(w2) | ||
184 | const w8 = z1.multiply(z2).mod(q) | ||
185 | const w9 = w3.square().mod(q) | ||
186 | const w10 = w3.multiply(w9).mod(q) | ||
187 | const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q) | ||
188 | |||
189 | const x3 = w3.multiply(w11).mod(q) | ||
190 | const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q) | ||
191 | const z3 = w10.multiply(w8).mod(q) | ||
192 | |||
193 | return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3) | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * 自加 | ||
198 | * | ||
199 | * 标准射影坐标系: | ||
200 | * | ||
201 | * λ1 = 3 * x1^2 + a * z1^2 | ||
202 | * λ2 = 2 * y1 * z1 | ||
203 | * λ3 = y1^2 | ||
204 | * λ4 = λ3 * x1 * z1 | ||
205 | * λ5 = λ2^2 | ||
206 | * λ6 = λ1^2 − 8 * λ4 | ||
207 | * x3 = λ2 * λ6 | ||
208 | * y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3 | ||
209 | * z3 = λ2 * λ5 | ||
210 | */ | ||
211 | twice() { | ||
212 | if (this.isInfinity()) return this | ||
213 | if (!this.y.toBigInteger().signum()) return this.curve.infinity | ||
214 | |||
215 | const x1 = this.x.toBigInteger() | ||
216 | const y1 = this.y.toBigInteger() | ||
217 | const z1 = this.z | ||
218 | const q = this.curve.q | ||
219 | const a = this.curve.a.toBigInteger() | ||
220 | |||
221 | const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q) | ||
222 | const w2 = y1.shiftLeft(1).multiply(z1).mod(q) | ||
223 | const w3 = y1.square().mod(q) | ||
224 | const w4 = w3.multiply(x1).multiply(z1).mod(q) | ||
225 | const w5 = w2.square().mod(q) | ||
226 | const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q) | ||
227 | |||
228 | const x3 = w2.multiply(w6).mod(q) | ||
229 | const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q) | ||
230 | const z3 = w2.multiply(w5).mod(q) | ||
231 | |||
232 | return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3) | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * 倍点计算 | ||
237 | */ | ||
238 | multiply(k) { | ||
239 | if (this.isInfinity()) return this | ||
240 | if (!k.signum()) return this.curve.infinity | ||
241 | |||
242 | // 使用加减法 | ||
243 | const k3 = k.multiply(THREE) | ||
244 | const neg = this.negate() | ||
245 | let Q = this | ||
246 | |||
247 | for (let i = k3.bitLength() - 2; i > 0; i--) { | ||
248 | Q = Q.twice() | ||
249 | |||
250 | const k3Bit = k3.testBit(i) | ||
251 | const kBit = k.testBit(i) | ||
252 | |||
253 | if (k3Bit !== kBit) { | ||
254 | Q = Q.add(k3Bit ? this : neg) | ||
255 | } | ||
256 | } | ||
257 | |||
258 | return Q | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * 椭圆曲线 y^2 = x^3 + ax + b | ||
264 | */ | ||
265 | class ECCurveFp { | ||
266 | constructor(q, a, b) { | ||
267 | this.q = q | ||
268 | this.a = this.fromBigInteger(a) | ||
269 | this.b = this.fromBigInteger(b) | ||
270 | this.infinity = new ECPointFp(this, null, null) // 无穷远点 | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * 判断两个椭圆曲线是否相等 | ||
275 | */ | ||
276 | equals(other) { | ||
277 | if (other === this) return true | ||
278 | return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b)) | ||
279 | } | ||
280 | |||
281 | /** | ||
282 | * 生成椭圆曲线域元素 | ||
283 | */ | ||
284 | fromBigInteger(x) { | ||
285 | return new ECFieldElementFp(this.q, x) | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * 解析 16 进制串为椭圆曲线点 | ||
290 | */ | ||
291 | decodePointHex(s) { | ||
292 | switch (parseInt(s.substr(0, 2), 16)) { | ||
293 | // 第一个字节 | ||
294 | case 0: | ||
295 | return this.infinity | ||
296 | case 2: | ||
297 | case 3: | ||
298 | // 不支持的压缩方式 | ||
299 | return null | ||
300 | case 4: | ||
301 | case 6: | ||
302 | case 7: | ||
303 | const len = (s.length - 2) / 2 | ||
304 | const xHex = s.substr(2, len) | ||
305 | const yHex = s.substr(len + 2, len) | ||
306 | |||
307 | return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16))) | ||
308 | default: | ||
309 | // 不支持 | ||
310 | return null | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | |||
315 | module.exports = { | ||
316 | ECPointFp, | ||
317 | ECCurveFp, | ||
318 | } |
.history/src/sm2/ec_20210804205518.js
0 → 100644
1 | /* eslint-disable no-case-declarations, max-len */ | ||
2 | const {BigInteger} = require('jsbn') | ||
3 | |||
4 | /** | ||
5 | * thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/ | ||
6 | * | ||
7 | * Basic Javascript Elliptic Curve implementation | ||
8 | * Ported loosely from BouncyCastle's Java EC code | ||
9 | * Only Fp curves implemented for now | ||
10 | */ | ||
11 | |||
12 | const THREE = new BigInteger('3') | ||
13 | |||
14 | /** | ||
15 | * 椭圆曲线域元素 | ||
16 | */ | ||
17 | class ECFieldElementFp { | ||
18 | constructor(q, x) { | ||
19 | this.x = x | ||
20 | this.q = q | ||
21 | // TODO if (x.compareTo(q) >= 0) error | ||
22 | } | ||
23 | |||
24 | /** | ||
25 | * 判断相等 | ||
26 | */ | ||
27 | equals(other) { | ||
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 | } | ||
80 | } | ||
81 | |||
82 | class ECPointFp { | ||
83 | constructor(curve, x, y, z) { | ||
84 | this.curve = curve | ||
85 | this.x = x | ||
86 | this.y = y | ||
87 | // 标准射影坐标系:zinv == null 或 z * zinv == 1 | ||
88 | this.z = z == null ? BigInteger.ONE : z | ||
89 | this.zinv = null | ||
90 | // TODO: compression flag | ||
91 | } | ||
92 | |||
93 | getX() { | ||
94 | if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q) | ||
95 | |||
96 | return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q)) | ||
97 | } | ||
98 | |||
99 | getY() { | ||
100 | if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q) | ||
101 | |||
102 | return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q)) | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * 判断相等 | ||
107 | */ | ||
108 | equals(other) { | ||
109 | if (other === this) return true | ||
110 | if (this.isInfinity()) return other.isInfinity() | ||
111 | if (other.isInfinity()) return this.isInfinity() | ||
112 | |||
113 | // u = y2 * z1 - y1 * z2 | ||
114 | const u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q) | ||
115 | if (!u.equals(BigInteger.ZERO)) return false | ||
116 | |||
117 | // v = x2 * z1 - x1 * z2 | ||
118 | const v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q) | ||
119 | return v.equals(BigInteger.ZERO) | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * 是否是无穷远点 | ||
124 | */ | ||
125 | isInfinity() { | ||
126 | if ((this.x === null) && (this.y === null)) return true | ||
127 | return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO) | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * 取反,x 轴对称点 | ||
132 | */ | ||
133 | negate() { | ||
134 | return new ECPointFp(this.curve, this.x, this.y.negate(), this.z) | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * 相加 | ||
139 | * | ||
140 | * 标准射影坐标系: | ||
141 | * | ||
142 | * λ1 = x1 * z2 | ||
143 | * λ2 = x2 * z1 | ||
144 | * λ3 = λ1 − λ2 | ||
145 | * λ4 = y1 * z2 | ||
146 | * λ5 = y2 * z1 | ||
147 | * λ6 = λ4 − λ5 | ||
148 | * λ7 = λ1 + λ2 | ||
149 | * λ8 = z1 * z2 | ||
150 | * λ9 = λ3^2 | ||
151 | * λ10 = λ3 * λ9 | ||
152 | * λ11 = λ8 * λ6^2 − λ7 * λ9 | ||
153 | * x3 = λ3 * λ11 | ||
154 | * y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10 | ||
155 | * z3 = λ10 * λ8 | ||
156 | */ | ||
157 | add(b) { | ||
158 | if (this.isInfinity()) return b | ||
159 | if (b.isInfinity()) return this | ||
160 | |||
161 | const x1 = this.x.toBigInteger() | ||
162 | const y1 = this.y.toBigInteger() | ||
163 | const z1 = this.z | ||
164 | const x2 = b.x.toBigInteger() | ||
165 | const y2 = b.y.toBigInteger() | ||
166 | const z2 = b.z | ||
167 | const q = this.curve.q | ||
168 | |||
169 | const w1 = x1.multiply(z2).mod(q) | ||
170 | const w2 = x2.multiply(z1).mod(q) | ||
171 | const w3 = w1.subtract(w2) | ||
172 | const w4 = y1.multiply(z2).mod(q) | ||
173 | const w5 = y2.multiply(z1).mod(q) | ||
174 | const w6 = w4.subtract(w5) | ||
175 | |||
176 | if (BigInteger.ZERO.equals(w3)) { | ||
177 | if (BigInteger.ZERO.equals(w6)) { | ||
178 | return this.twice() // this == b,计算自加 | ||
179 | } | ||
180 | return this.curve.infinity // this == -b,则返回无穷远点 | ||
181 | } | ||
182 | |||
183 | const w7 = w1.add(w2) | ||
184 | const w8 = z1.multiply(z2).mod(q) | ||
185 | const w9 = w3.square().mod(q) | ||
186 | const w10 = w3.multiply(w9).mod(q) | ||
187 | const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q) | ||
188 | |||
189 | const x3 = w3.multiply(w11).mod(q) | ||
190 | const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q) | ||
191 | const z3 = w10.multiply(w8).mod(q) | ||
192 | |||
193 | return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3) | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * 自加 | ||
198 | * | ||
199 | * 标准射影坐标系: | ||
200 | * | ||
201 | * λ1 = 3 * x1^2 + a * z1^2 | ||
202 | * λ2 = 2 * y1 * z1 | ||
203 | * λ3 = y1^2 | ||
204 | * λ4 = λ3 * x1 * z1 | ||
205 | * λ5 = λ2^2 | ||
206 | * λ6 = λ1^2 − 8 * λ4 | ||
207 | * x3 = λ2 * λ6 | ||
208 | * y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3 | ||
209 | * z3 = λ2 * λ5 | ||
210 | */ | ||
211 | twice() { | ||
212 | if (this.isInfinity()) return this | ||
213 | if (!this.y.toBigInteger().signum()) return this.curve.infinity | ||
214 | |||
215 | const x1 = this.x.toBigInteger() | ||
216 | const y1 = this.y.toBigInteger() | ||
217 | const z1 = this.z | ||
218 | const q = this.curve.q | ||
219 | const a = this.curve.a.toBigInteger() | ||
220 | |||
221 | const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q) | ||
222 | const w2 = y1.shiftLeft(1).multiply(z1).mod(q) | ||
223 | const w3 = y1.square().mod(q) | ||
224 | const w4 = w3.multiply(x1).multiply(z1).mod(q) | ||
225 | const w5 = w2.square().mod(q) | ||
226 | const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q) | ||
227 | |||
228 | const x3 = w2.multiply(w6).mod(q) | ||
229 | const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q) | ||
230 | const z3 = w2.multiply(w5).mod(q) | ||
231 | |||
232 | return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3) | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * 倍点计算 | ||
237 | */ | ||
238 | multiply(k) { | ||
239 | if (this.isInfinity()) return this | ||
240 | if (!k.signum()) return this.curve.infinity | ||
241 | |||
242 | // 使用加减法 | ||
243 | const k3 = k.multiply(THREE) | ||
244 | const neg = this.negate() | ||
245 | let Q = this | ||
246 | |||
247 | for (let i = k3.bitLength() - 2; i > 0; i--) { | ||
248 | Q = Q.twice() | ||
249 | |||
250 | const k3Bit = k3.testBit(i) | ||
251 | const kBit = k.testBit(i) | ||
252 | |||
253 | if (k3Bit !== kBit) { | ||
254 | Q = Q.add(k3Bit ? this : neg) | ||
255 | } | ||
256 | } | ||
257 | |||
258 | return Q | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * 椭圆曲线 y^2 = x^3 + ax + b | ||
264 | */ | ||
265 | class ECCurveFp { | ||
266 | constructor(q, a, b) { | ||
267 | this.q = q | ||
268 | this.a = this.fromBigInteger(a) | ||
269 | this.b = this.fromBigInteger(b) | ||
270 | this.infinity = new ECPointFp(this, null, null) // 无穷远点 | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * 判断两个椭圆曲线是否相等 | ||
275 | */ | ||
276 | equals(other) { | ||
277 | if (other === this) return true | ||
278 | return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b)) | ||
279 | } | ||
280 | |||
281 | /** | ||
282 | * 生成椭圆曲线域元素 | ||
283 | */ | ||
284 | fromBigInteger(x) { | ||
285 | return new ECFieldElementFp(this.q, x) | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * 解析 16 进制串为椭圆曲线点 | ||
290 | */ | ||
291 | decodePointHex(s) { | ||
292 | switch (parseInt(s.substr(0, 2), 16)) { | ||
293 | // 第一个字节 | ||
294 | case 0: | ||
295 | return this.infinity | ||
296 | case 2: | ||
297 | case 3: | ||
298 | // 不支持的压缩方式 | ||
299 | return null | ||
300 | case 4: | ||
301 | case 6: | ||
302 | case 7: | ||
303 | const len = (s.length - 2) / 2 | ||
304 | const xHex = s.substr(2, len) | ||
305 | const yHex = s.substr(len + 2, len) | ||
306 | |||
307 | return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16))) | ||
308 | default: | ||
309 | // 不支持 | ||
310 | return null | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | |||
315 | module.exports = { | ||
316 | ECPointFp, | ||
317 | ECCurveFp, | ||
318 | } |
.history/src/sm2/ec_20210804205639.js
0 → 100644
1 | /* eslint-disable no-case-declarations, max-len */ | ||
2 | const {BigInteger} = require('jsbn') | ||
3 | |||
4 | /** | ||
5 | * thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/ | ||
6 | * | ||
7 | * Basic Javascript Elliptic Curve implementation | ||
8 | * Ported loosely from BouncyCastle's Java EC code | ||
9 | * Only Fp curves implemented for now | ||
10 | */ | ||
11 | |||
12 | const THREE = new BigInteger('3') | ||
13 | |||
14 | /** | ||
15 | * 椭圆曲线域元素 | ||
16 | */ | ||
17 | class ECFieldElementFp { | ||
18 | constructor(q, x) { | ||
19 | this.x = x | ||
20 | this.q = q | ||
21 | // TODO if (x.compareTo(q) >= 0) error | ||
22 | } | ||
23 | |||
24 | /** | ||
25 | * 判断相等 | ||
26 | */ | ||
27 | equals(other) { | ||
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 | } | ||
80 | } | ||
81 | |||
82 | class ECPointFp { | ||
83 | constructor(curve, x, y, z) { | ||
84 | this.curve = curve | ||
85 | this.x = x | ||
86 | this.y = y | ||
87 | // 标准射影坐标系:zinv == null 或 z * zinv == 1 | ||
88 | this.z = z == null ? BigInteger.ONE : z | ||
89 | this.zinv = null | ||
90 | // TODO: compression flag | ||
91 | } | ||
92 | |||
93 | getX() { | ||
94 | if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q) | ||
95 | |||
96 | return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q)) | ||
97 | } | ||
98 | |||
99 | getY() { | ||
100 | if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q) | ||
101 | |||
102 | return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q)) | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * 判断相等 | ||
107 | */ | ||
108 | equals(other) { | ||
109 | if (other === this) return true | ||
110 | if (this.isInfinity()) return other.isInfinity() | ||
111 | if (other.isInfinity()) return this.isInfinity() | ||
112 | |||
113 | // u = y2 * z1 - y1 * z2 | ||
114 | const u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q) | ||
115 | if (!u.equals(BigInteger.ZERO)) return false | ||
116 | |||
117 | // v = x2 * z1 - x1 * z2 | ||
118 | const v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q) | ||
119 | return v.equals(BigInteger.ZERO) | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * 是否是无穷远点 | ||
124 | */ | ||
125 | isInfinity() { | ||
126 | if ((this.x === null) && (this.y === null)) return true | ||
127 | return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO) | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * 取反,x 轴对称点 | ||
132 | */ | ||
133 | negate() { | ||
134 | return new ECPointFp(this.curve, this.x, this.y.negate(), this.z) | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * 相加 | ||
139 | * | ||
140 | * 标准射影坐标系: | ||
141 | * | ||
142 | * λ1 = x1 * z2 | ||
143 | * λ2 = x2 * z1 | ||
144 | * λ3 = λ1 − λ2 | ||
145 | * λ4 = y1 * z2 | ||
146 | * λ5 = y2 * z1 | ||
147 | * λ6 = λ4 − λ5 | ||
148 | * λ7 = λ1 + λ2 | ||
149 | * λ8 = z1 * z2 | ||
150 | * λ9 = λ3^2 | ||
151 | * λ10 = λ3 * λ9 | ||
152 | * λ11 = λ8 * λ6^2 − λ7 * λ9 | ||
153 | * x3 = λ3 * λ11 | ||
154 | * y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10 | ||
155 | * z3 = λ10 * λ8 | ||
156 | */ | ||
157 | add(b) { | ||
158 | if (this.isInfinity()) return b | ||
159 | if (b.isInfinity()) return this | ||
160 | |||
161 | const x1 = this.x.toBigInteger() | ||
162 | const y1 = this.y.toBigInteger() | ||
163 | const z1 = this.z | ||
164 | const x2 = b.x.toBigInteger() | ||
165 | const y2 = b.y.toBigInteger() | ||
166 | const z2 = b.z | ||
167 | const q = this.curve.q | ||
168 | |||
169 | const w1 = x1.multiply(z2).mod(q) | ||
170 | const w2 = x2.multiply(z1).mod(q) | ||
171 | const w3 = w1.subtract(w2) | ||
172 | const w4 = y1.multiply(z2).mod(q) | ||
173 | const w5 = y2.multiply(z1).mod(q) | ||
174 | const w6 = w4.subtract(w5) | ||
175 | |||
176 | if (BigInteger.ZERO.equals(w3)) { | ||
177 | if (BigInteger.ZERO.equals(w6)) { | ||
178 | return this.twice() // this == b,计算自加 | ||
179 | } | ||
180 | return this.curve.infinity // this == -b,则返回无穷远点 | ||
181 | } | ||
182 | |||
183 | const w7 = w1.add(w2) | ||
184 | const w8 = z1.multiply(z2).mod(q) | ||
185 | const w9 = w3.square().mod(q) | ||
186 | const w10 = w3.multiply(w9).mod(q) | ||
187 | const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q) | ||
188 | |||
189 | const x3 = w3.multiply(w11).mod(q) | ||
190 | const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q) | ||
191 | const z3 = w10.multiply(w8).mod(q) | ||
192 | |||
193 | return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3) | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * 自加 | ||
198 | * | ||
199 | * 标准射影坐标系: | ||
200 | * | ||
201 | * λ1 = 3 * x1^2 + a * z1^2 | ||
202 | * λ2 = 2 * y1 * z1 | ||
203 | * λ3 = y1^2 | ||
204 | * λ4 = λ3 * x1 * z1 | ||
205 | * λ5 = λ2^2 | ||
206 | * λ6 = λ1^2 − 8 * λ4 | ||
207 | * x3 = λ2 * λ6 | ||
208 | * y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3 | ||
209 | * z3 = λ2 * λ5 | ||
210 | */ | ||
211 | twice() { | ||
212 | if (this.isInfinity()) return this | ||
213 | if (!this.y.toBigInteger().signum()) return this.curve.infinity | ||
214 | |||
215 | const x1 = this.x.toBigInteger() | ||
216 | const y1 = this.y.toBigInteger() | ||
217 | const z1 = this.z | ||
218 | const q = this.curve.q | ||
219 | const a = this.curve.a.toBigInteger() | ||
220 | |||
221 | const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q) | ||
222 | const w2 = y1.shiftLeft(1).multiply(z1).mod(q) | ||
223 | const w3 = y1.square().mod(q) | ||
224 | const w4 = w3.multiply(x1).multiply(z1).mod(q) | ||
225 | const w5 = w2.square().mod(q) | ||
226 | const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q) | ||
227 | |||
228 | const x3 = w2.multiply(w6).mod(q) | ||
229 | const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q) | ||
230 | const z3 = w2.multiply(w5).mod(q) | ||
231 | |||
232 | return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3) | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * 倍点计算 | ||
237 | */ | ||
238 | multiply(k) { | ||
239 | if (this.isInfinity()) return this | ||
240 | if (!k.signum()) return this.curve.infinity | ||
241 | |||
242 | // 使用加减法 | ||
243 | const k3 = k.multiply(THREE) | ||
244 | const neg = this.negate() | ||
245 | let Q = this | ||
246 | |||
247 | for (let i = k3.bitLength() - 2; i > 0; i--) { | ||
248 | Q = Q.twice() | ||
249 | |||
250 | const k3Bit = k3.testBit(i) | ||
251 | const kBit = k.testBit(i) | ||
252 | |||
253 | if (k3Bit !== kBit) { | ||
254 | Q = Q.add(k3Bit ? this : neg) | ||
255 | } | ||
256 | } | ||
257 | |||
258 | return Q | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * 椭圆曲线 y^2 = x^3 + ax + b | ||
264 | */ | ||
265 | class ECCurveFp { | ||
266 | constructor(q, a, b) { | ||
267 | this.q = q | ||
268 | this.a = this.fromBigInteger(a) | ||
269 | this.b = this.fromBigInteger(b) | ||
270 | this.infinity = new ECPointFp(this, null, null) // 无穷远点 | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * 判断两个椭圆曲线是否相等 | ||
275 | */ | ||
276 | equals(other) { | ||
277 | if (other === this) return true | ||
278 | return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b)) | ||
279 | } | ||
280 | |||
281 | /** | ||
282 | * 生成椭圆曲线域元素 | ||
283 | */ | ||
284 | fromBigInteger(x) { | ||
285 | return new ECFieldElementFp(this.q, x) | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * 解析 16 进制串为椭圆曲线点 | ||
290 | */ | ||
291 | decodePointHex(s) { | ||
292 | switch (parseInt(s.substr(0, 2), 16)) { | ||
293 | // 第一个字节 | ||
294 | case 0: | ||
295 | return this.infinity | ||
296 | case 2: | ||
297 | case 3: | ||
298 | // 不支持的压缩方式 | ||
299 | return null | ||
300 | case 4: | ||
301 | case 6: | ||
302 | case 7: | ||
303 | const len = (s.length - 2) / 2 | ||
304 | const xHex = s.substr(2, len) | ||
305 | const yHex = s.substr(len + 2, len) | ||
306 | |||
307 | return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16))) | ||
308 | default: | ||
309 | // 不支持 | ||
310 | return null | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | |||
315 | module.exports = { | ||
316 | ECPointFp, | ||
317 | ECCurveFp, | ||
318 | } |
.history/src/sm2/utils_20210804205255.js
0 → 100644
1 | /* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */ | ||
2 | const {BigInteger, SecureRandom} = require('jsbn') | ||
3 | const {ECCurveFp} = require('./ec') | ||
4 | |||
5 | const rng = new SecureRandom() | ||
6 | const {curve, G, n} = generateEcparam() | ||
7 | |||
8 | /** | ||
9 | * 获取公共椭圆曲线 | ||
10 | */ | ||
11 | function getGlobalCurve() { | ||
12 | return curve | ||
13 | } | ||
14 | |||
15 | /** | ||
16 | * 生成ecparam | ||
17 | */ | ||
18 | function generateEcparam() { | ||
19 | // 椭圆曲线 | ||
20 | const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16) | ||
21 | const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16) | ||
22 | const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16) | ||
23 | const curve = new ECCurveFp(p, a, b) | ||
24 | |||
25 | // 基点 | ||
26 | const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7' | ||
27 | const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0' | ||
28 | const G = curve.decodePointHex('04' + gxHex + gyHex) | ||
29 | |||
30 | const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16) | ||
31 | |||
32 | return {curve, G, n} | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * 生成密钥对 | ||
37 | */ | ||
38 | function generateKeyPairHex() { | ||
39 | const d = new BigInteger(n.bitLength(), rng).mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数 | ||
40 | const privateKey = leftPad(d.toString(16), 64) | ||
41 | |||
42 | const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥 | ||
43 | const Px = leftPad(P.getX().toBigInteger().toString(16), 64) | ||
44 | const Py = leftPad(P.getY().toBigInteger().toString(16), 64) | ||
45 | const publicKey = '04' + Px + Py | ||
46 | |||
47 | return {privateKey, publicKey} | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * 根据指定hash值,生成密钥对 | ||
52 | * @param {String} hashValue | ||
53 | */ | ||
54 | function generateKeyPairHexByHashValue(hashValue) { | ||
55 | const d = new BigInteger(hashValue, 16) | ||
56 | const privateKey = leftPad(d.toString(16), 64) | ||
57 | const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥 | ||
58 | const Px = leftPad(P.getX().toBigInteger().toString(16), 64) | ||
59 | const Py = leftPad(P.getY().toBigInteger().toString(16), 64) | ||
60 | const publicKey = '0x' + Px + Py | ||
61 | |||
62 | return {privateKey, publicKey} | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * 解析utf8字符串到16进制 | ||
67 | */ | ||
68 | function parseUtf8StringToHex(input) { | ||
69 | input = unescape(encodeURIComponent(input)) | ||
70 | |||
71 | const length = input.length | ||
72 | |||
73 | // 转换到字数组 | ||
74 | const words = [] | ||
75 | for (let i = 0; i < length; i++) { | ||
76 | words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8) | ||
77 | } | ||
78 | |||
79 | // 转换到16进制 | ||
80 | const hexChars = [] | ||
81 | for (let i = 0; i < length; i++) { | ||
82 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
83 | hexChars.push((bite >>> 4).toString(16)) | ||
84 | hexChars.push((bite & 0x0f).toString(16)) | ||
85 | } | ||
86 | |||
87 | return hexChars.join('') | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * 解析arrayBuffer到16进制字符串 | ||
92 | */ | ||
93 | function parseArrayBufferToHex(input) { | ||
94 | return Array.prototype.map.call(new Uint8Array(input), x => ('00' + x.toString(16)).slice(-2)).join('') | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * 补全16进制字符串 | ||
99 | */ | ||
100 | function leftPad(input, num) { | ||
101 | if (input.length >= num) return input | ||
102 | |||
103 | return (new Array(num - input.length + 1)).join('0') + input | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * 转成16进制串 | ||
108 | */ | ||
109 | function arrayToHex(arr) { | ||
110 | const words = [] | ||
111 | let j = 0 | ||
112 | for (let i = 0; i < arr.length * 2; i += 2) { | ||
113 | words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4) | ||
114 | j++ | ||
115 | } | ||
116 | |||
117 | // 转换到16进制 | ||
118 | const hexChars = [] | ||
119 | for (let i = 0; i < arr.length; i++) { | ||
120 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
121 | hexChars.push((bite >>> 4).toString(16)) | ||
122 | hexChars.push((bite & 0x0f).toString(16)) | ||
123 | } | ||
124 | |||
125 | return hexChars.join('') | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * 转成utf8串 | ||
130 | */ | ||
131 | function arrayToUtf8(arr) { | ||
132 | const words = [] | ||
133 | let j = 0 | ||
134 | for (let i = 0; i < arr.length * 2; i += 2) { | ||
135 | words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4) | ||
136 | j++ | ||
137 | } | ||
138 | |||
139 | try { | ||
140 | const latin1Chars = [] | ||
141 | |||
142 | for (let i = 0; i < arr.length; i++) { | ||
143 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
144 | latin1Chars.push(String.fromCharCode(bite)) | ||
145 | } | ||
146 | |||
147 | return decodeURIComponent(escape(latin1Chars.join(''))) | ||
148 | } catch (e) { | ||
149 | throw new Error('Malformed UTF-8 data') | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * 转成ascii码数组 | ||
155 | */ | ||
156 | function hexToArray(hexStr) { | ||
157 | const words = [] | ||
158 | let hexStrLength = hexStr.length | ||
159 | |||
160 | if (hexStrLength % 2 !== 0) { | ||
161 | hexStr = leftPad(hexStr, hexStrLength + 1) | ||
162 | } | ||
163 | |||
164 | hexStrLength = hexStr.length | ||
165 | |||
166 | for (let i = 0; i < hexStrLength; i += 2) { | ||
167 | words.push(parseInt(hexStr.substr(i, 2), 16)) | ||
168 | } | ||
169 | return words | ||
170 | } | ||
171 | |||
172 | module.exports = { | ||
173 | getGlobalCurve, | ||
174 | generateEcparam, | ||
175 | generateKeyPairHex, | ||
176 | generateKeyPairHexByHashValue, | ||
177 | parseUtf8StringToHex, | ||
178 | parseArrayBufferToHex, | ||
179 | leftPad, | ||
180 | arrayToHex, | ||
181 | arrayToUtf8, | ||
182 | hexToArray, | ||
183 | } |
.history/src/sm2/utils_20210804205313.js
0 → 100644
1 | /* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */ | ||
2 | const {BigInteger, SecureRandom} = require('jsbn') | ||
3 | const {ECCurveFp} = require('./ec') | ||
4 | |||
5 | const rng = new SecureRandom() | ||
6 | const {curve, G, n} = generateEcparam() | ||
7 | |||
8 | /** | ||
9 | * 获取公共椭圆曲线 | ||
10 | */ | ||
11 | function getGlobalCurve() { | ||
12 | return curve | ||
13 | } | ||
14 | |||
15 | /** | ||
16 | * 生成ecparam | ||
17 | */ | ||
18 | function generateEcparam() { | ||
19 | // 椭圆曲线 | ||
20 | const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16) | ||
21 | const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16) | ||
22 | const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16) | ||
23 | const curve = new ECCurveFp(p, a, b) | ||
24 | |||
25 | // 基点 | ||
26 | const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7' | ||
27 | const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0' | ||
28 | const G = curve.decodePointHex('04' + gxHex + gyHex) | ||
29 | |||
30 | const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16) | ||
31 | |||
32 | return {curve, G, n} | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * 生成密钥对 | ||
37 | */ | ||
38 | function generateKeyPairHex() { | ||
39 | const d = new BigInteger(n.bitLength(), rng).mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数 | ||
40 | const privateKey = leftPad(d.toString(16), 64) | ||
41 | |||
42 | const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥 | ||
43 | const Px = leftPad(P.getX().toBigInteger().toString(16), 64) | ||
44 | const Py = leftPad(P.getY().toBigInteger().toString(16), 64) | ||
45 | const publicKey = '04' + Px + Py | ||
46 | |||
47 | return {privateKey, publicKey} | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * 根据指定hash值,生成密钥对 | ||
52 | * @param {String} hashValue | ||
53 | */ | ||
54 | function generateKeyPairHexByHashValue(hashValue) { | ||
55 | const d = new BigInteger(hashValue, 16) | ||
56 | const privateKey = leftPad(d.toString(16), 64) | ||
57 | const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥 | ||
58 | const Px = leftPad(P.getX().toBigInteger().toString(16), 64) | ||
59 | const Py = leftPad(P.getY().toBigInteger().toString(16), 64) | ||
60 | const publicKey = '04' + Px + Py | ||
61 | |||
62 | return {privateKey, publicKey} | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * 解析utf8字符串到16进制 | ||
67 | */ | ||
68 | function parseUtf8StringToHex(input) { | ||
69 | input = unescape(encodeURIComponent(input)) | ||
70 | |||
71 | const length = input.length | ||
72 | |||
73 | // 转换到字数组 | ||
74 | const words = [] | ||
75 | for (let i = 0; i < length; i++) { | ||
76 | words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8) | ||
77 | } | ||
78 | |||
79 | // 转换到16进制 | ||
80 | const hexChars = [] | ||
81 | for (let i = 0; i < length; i++) { | ||
82 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
83 | hexChars.push((bite >>> 4).toString(16)) | ||
84 | hexChars.push((bite & 0x0f).toString(16)) | ||
85 | } | ||
86 | |||
87 | return hexChars.join('') | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * 解析arrayBuffer到16进制字符串 | ||
92 | */ | ||
93 | function parseArrayBufferToHex(input) { | ||
94 | return Array.prototype.map.call(new Uint8Array(input), x => ('00' + x.toString(16)).slice(-2)).join('') | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * 补全16进制字符串 | ||
99 | */ | ||
100 | function leftPad(input, num) { | ||
101 | if (input.length >= num) return input | ||
102 | |||
103 | return (new Array(num - input.length + 1)).join('0') + input | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * 转成16进制串 | ||
108 | */ | ||
109 | function arrayToHex(arr) { | ||
110 | const words = [] | ||
111 | let j = 0 | ||
112 | for (let i = 0; i < arr.length * 2; i += 2) { | ||
113 | words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4) | ||
114 | j++ | ||
115 | } | ||
116 | |||
117 | // 转换到16进制 | ||
118 | const hexChars = [] | ||
119 | for (let i = 0; i < arr.length; i++) { | ||
120 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
121 | hexChars.push((bite >>> 4).toString(16)) | ||
122 | hexChars.push((bite & 0x0f).toString(16)) | ||
123 | } | ||
124 | |||
125 | return hexChars.join('') | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * 转成utf8串 | ||
130 | */ | ||
131 | function arrayToUtf8(arr) { | ||
132 | const words = [] | ||
133 | let j = 0 | ||
134 | for (let i = 0; i < arr.length * 2; i += 2) { | ||
135 | words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4) | ||
136 | j++ | ||
137 | } | ||
138 | |||
139 | try { | ||
140 | const latin1Chars = [] | ||
141 | |||
142 | for (let i = 0; i < arr.length; i++) { | ||
143 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
144 | latin1Chars.push(String.fromCharCode(bite)) | ||
145 | } | ||
146 | |||
147 | return decodeURIComponent(escape(latin1Chars.join(''))) | ||
148 | } catch (e) { | ||
149 | throw new Error('Malformed UTF-8 data') | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * 转成ascii码数组 | ||
155 | */ | ||
156 | function hexToArray(hexStr) { | ||
157 | const words = [] | ||
158 | let hexStrLength = hexStr.length | ||
159 | |||
160 | if (hexStrLength % 2 !== 0) { | ||
161 | hexStr = leftPad(hexStr, hexStrLength + 1) | ||
162 | } | ||
163 | |||
164 | hexStrLength = hexStr.length | ||
165 | |||
166 | for (let i = 0; i < hexStrLength; i += 2) { | ||
167 | words.push(parseInt(hexStr.substr(i, 2), 16)) | ||
168 | } | ||
169 | return words | ||
170 | } | ||
171 | |||
172 | module.exports = { | ||
173 | getGlobalCurve, | ||
174 | generateEcparam, | ||
175 | generateKeyPairHex, | ||
176 | generateKeyPairHexByHashValue, | ||
177 | parseUtf8StringToHex, | ||
178 | parseArrayBufferToHex, | ||
179 | leftPad, | ||
180 | arrayToHex, | ||
181 | arrayToUtf8, | ||
182 | hexToArray, | ||
183 | } |
.history/tet_20210804205350.js
0 → 100644
File mode changed
.history/tet_20210804205353.js
0 → 100644
1 | /* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */ | ||
2 | const {BigInteger, SecureRandom} = require('jsbn') | ||
3 | const {ECCurveFp} = require('./ec') | ||
4 | |||
5 | const rng = new SecureRandom() | ||
6 | const {curve, G, n} = generateEcparam() | ||
7 | |||
8 | /** | ||
9 | * 获取公共椭圆曲线 | ||
10 | */ | ||
11 | function getGlobalCurve() { | ||
12 | return curve | ||
13 | } | ||
14 | |||
15 | /** | ||
16 | * 生成ecparam | ||
17 | */ | ||
18 | function generateEcparam() { | ||
19 | // 椭圆曲线 | ||
20 | const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16) | ||
21 | const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16) | ||
22 | const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16) | ||
23 | const curve = new ECCurveFp(p, a, b) | ||
24 | |||
25 | // 基点 | ||
26 | const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7' | ||
27 | const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0' | ||
28 | const G = curve.decodePointHex('04' + gxHex + gyHex) | ||
29 | |||
30 | const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16) | ||
31 | |||
32 | return {curve, G, n} | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * 生成密钥对 | ||
37 | */ | ||
38 | function generateKeyPairHex() { | ||
39 | const d = new BigInteger(n.bitLength(), rng).mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数 | ||
40 | const privateKey = leftPad(d.toString(16), 64) | ||
41 | |||
42 | const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥 | ||
43 | const Px = leftPad(P.getX().toBigInteger().toString(16), 64) | ||
44 | const Py = leftPad(P.getY().toBigInteger().toString(16), 64) | ||
45 | const publicKey = '04' + Px + Py | ||
46 | |||
47 | return {privateKey, publicKey} | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * 根据指定hash值,生成密钥对 | ||
52 | * @param {String} hashValue | ||
53 | */ | ||
54 | function generateKeyPairHexByHashValue(hashValue) { | ||
55 | const d = new BigInteger(hashValue, 16) | ||
56 | const privateKey = leftPad(d.toString(16), 64) | ||
57 | const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥 | ||
58 | const Px = leftPad(P.getX().toBigInteger().toString(16), 64) | ||
59 | const Py = leftPad(P.getY().toBigInteger().toString(16), 64) | ||
60 | const publicKey = '04' + Px + Py | ||
61 | |||
62 | return {privateKey, publicKey} | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * 解析utf8字符串到16进制 | ||
67 | */ | ||
68 | function parseUtf8StringToHex(input) { | ||
69 | input = unescape(encodeURIComponent(input)) | ||
70 | |||
71 | const length = input.length | ||
72 | |||
73 | // 转换到字数组 | ||
74 | const words = [] | ||
75 | for (let i = 0; i < length; i++) { | ||
76 | words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8) | ||
77 | } | ||
78 | |||
79 | // 转换到16进制 | ||
80 | const hexChars = [] | ||
81 | for (let i = 0; i < length; i++) { | ||
82 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
83 | hexChars.push((bite >>> 4).toString(16)) | ||
84 | hexChars.push((bite & 0x0f).toString(16)) | ||
85 | } | ||
86 | |||
87 | return hexChars.join('') | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * 解析arrayBuffer到16进制字符串 | ||
92 | */ | ||
93 | function parseArrayBufferToHex(input) { | ||
94 | return Array.prototype.map.call(new Uint8Array(input), x => ('00' + x.toString(16)).slice(-2)).join('') | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * 补全16进制字符串 | ||
99 | */ | ||
100 | function leftPad(input, num) { | ||
101 | if (input.length >= num) return input | ||
102 | |||
103 | return (new Array(num - input.length + 1)).join('0') + input | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * 转成16进制串 | ||
108 | */ | ||
109 | function arrayToHex(arr) { | ||
110 | const words = [] | ||
111 | let j = 0 | ||
112 | for (let i = 0; i < arr.length * 2; i += 2) { | ||
113 | words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4) | ||
114 | j++ | ||
115 | } | ||
116 | |||
117 | // 转换到16进制 | ||
118 | const hexChars = [] | ||
119 | for (let i = 0; i < arr.length; i++) { | ||
120 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
121 | hexChars.push((bite >>> 4).toString(16)) | ||
122 | hexChars.push((bite & 0x0f).toString(16)) | ||
123 | } | ||
124 | |||
125 | return hexChars.join('') | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * 转成utf8串 | ||
130 | */ | ||
131 | function arrayToUtf8(arr) { | ||
132 | const words = [] | ||
133 | let j = 0 | ||
134 | for (let i = 0; i < arr.length * 2; i += 2) { | ||
135 | words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4) | ||
136 | j++ | ||
137 | } | ||
138 | |||
139 | try { | ||
140 | const latin1Chars = [] | ||
141 | |||
142 | for (let i = 0; i < arr.length; i++) { | ||
143 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
144 | latin1Chars.push(String.fromCharCode(bite)) | ||
145 | } | ||
146 | |||
147 | return decodeURIComponent(escape(latin1Chars.join(''))) | ||
148 | } catch (e) { | ||
149 | throw new Error('Malformed UTF-8 data') | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * 转成ascii码数组 | ||
155 | */ | ||
156 | function hexToArray(hexStr) { | ||
157 | const words = [] | ||
158 | let hexStrLength = hexStr.length | ||
159 | |||
160 | if (hexStrLength % 2 !== 0) { | ||
161 | hexStr = leftPad(hexStr, hexStrLength + 1) | ||
162 | } | ||
163 | |||
164 | hexStrLength = hexStr.length | ||
165 | |||
166 | for (let i = 0; i < hexStrLength; i += 2) { | ||
167 | words.push(parseInt(hexStr.substr(i, 2), 16)) | ||
168 | } | ||
169 | return words | ||
170 | } | ||
171 | |||
172 | module.exports = { | ||
173 | getGlobalCurve, | ||
174 | generateEcparam, | ||
175 | generateKeyPairHex, | ||
176 | generateKeyPairHexByHashValue, | ||
177 | parseUtf8StringToHex, | ||
178 | parseArrayBufferToHex, | ||
179 | leftPad, | ||
180 | arrayToHex, | ||
181 | arrayToUtf8, | ||
182 | hexToArray, | ||
183 | } |
.history/tet_20210804205420.js
0 → 100644
1 | const sm2 = require('sm-crypto').sm2 | ||
2 | |||
3 | function getKeys(secret) { | ||
4 | // const hash = createHash(Buffer.from(secret)) | ||
5 | |||
6 | // const m = new Uint8Array(nacl.sign.seedLength) | ||
7 | // for (let i = 0; i < m.length; i++) m[i] = hash[i] | ||
8 | |||
9 | // const keypair = nacl.sign.keyPair.fromSeed(m) | ||
10 | /** | ||
11 | * { | ||
12 | publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7', | ||
13 | privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453' | ||
14 | } | ||
15 | */ | ||
16 | const keypair =sm2.generateKeyPairHex(secret) | ||
17 | let sigValueHex = sm2.doSignature(secret, keypair.privateKey) | ||
18 | let verifyResult = sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey) | ||
19 | console.log(verifyResult) | ||
20 | return { | ||
21 | publicKey: (keypair.publicKey), | ||
22 | privateKey: (keypair.privateKey) | ||
23 | } | ||
24 | |||
25 | } | ||
26 | function bufToHex(data) { | ||
27 | return Buffer.from(data).toString('hex') | ||
28 | } | ||
29 | console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output")) |
.history/tet_20210804205701.js
0 → 100644
1 | const sm2 = require('sm-crypto').sm2 | ||
2 | |||
3 | function getKeys(secret) { | ||
4 | // const hash = createHash(Buffer.from(secret)) | ||
5 | |||
6 | // const m = new Uint8Array(nacl.sign.seedLength) | ||
7 | // for (let i = 0; i < m.length; i++) m[i] = hash[i] | ||
8 | |||
9 | // const keypair = nacl.sign.keyPair.fromSeed(m) | ||
10 | /** | ||
11 | * { | ||
12 | publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7', | ||
13 | privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453' | ||
14 | } | ||
15 | */ | ||
16 | const keypair =sm2.generateKeyPairHex(secret) | ||
17 | // let sigValueHex = sm2.doSignature(secret, keypair.privateKey) | ||
18 | // let verifyResult = sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey) | ||
19 | // console.log(verifyResult) | ||
20 | return { | ||
21 | publicKey: (keypair.publicKey), | ||
22 | privateKey: (keypair.privateKey) | ||
23 | } | ||
24 | |||
25 | } | ||
26 | function bufToHex(data) { | ||
27 | return Buffer.from(data).toString('hex') | ||
28 | } | ||
29 | console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output")) |
.history/tet_20210804205707.js
0 → 100644
1 | const sm2 = require('sm-crypto').sm2 | ||
2 | |||
3 | function getKeys(secret) { | ||
4 | // const hash = createHash(Buffer.from(secret)) | ||
5 | |||
6 | // const m = new Uint8Array(nacl.sign.seedLength) | ||
7 | // for (let i = 0; i < m.length; i++) m[i] = hash[i] | ||
8 | |||
9 | // const keypair = nacl.sign.keyPair.fromSeed(m) | ||
10 | /** | ||
11 | * { | ||
12 | publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7', | ||
13 | privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453' | ||
14 | } | ||
15 | */ | ||
16 | const keypair =sm2.generateKeyPairHex(secret) | ||
17 | let sigValueHex = sm2.doSignature(secret, keypair.privateKey) | ||
18 | let verifyResult = sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey) | ||
19 | console.log(verifyResult) | ||
20 | return { | ||
21 | publicKey: (keypair.publicKey), | ||
22 | privateKey: (keypair.privateKey) | ||
23 | } | ||
24 | |||
25 | } | ||
26 | function bufToHex(data) { | ||
27 | return Buffer.from(data).toString('hex') | ||
28 | } | ||
29 | console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output")) |
.history/tet_20210804205958.js
0 → 100644
1 | const sm2 = require('sm-crypto').sm2 | ||
2 | |||
3 | function getKeys(secret) { | ||
4 | // const hash = createHash(Buffer.from(secret)) | ||
5 | |||
6 | // const m = new Uint8Array(nacl.sign.seedLength) | ||
7 | // for (let i = 0; i < m.length; i++) m[i] = hash[i] | ||
8 | |||
9 | // const keypair = nacl.sign.keyPair.fromSeed(m) | ||
10 | /** | ||
11 | * { | ||
12 | publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7', | ||
13 | privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453' | ||
14 | } | ||
15 | */ | ||
16 | const hash=sm3(secret) | ||
17 | const keypair =sm2.generateKeyPairHexByHashValue(hash) | ||
18 | let sigValueHex = sm2.doSignature(secret, keypair.privateKey) | ||
19 | let verifyResult = sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey) | ||
20 | console.log(verifyResult) | ||
21 | return { | ||
22 | publicKey: (keypair.publicKey), | ||
23 | privateKey: (keypair.privateKey) | ||
24 | } | ||
25 | |||
26 | } | ||
27 | function bufToHex(data) { | ||
28 | return Buffer.from(data).toString('hex') | ||
29 | } | ||
30 | console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output")) |
.history/tet_20210804210023.js
0 → 100644
1 | const SM = require('sm-crypto') | ||
2 | |||
3 | function getKeys(secret) { | ||
4 | // const hash = createHash(Buffer.from(secret)) | ||
5 | |||
6 | // const m = new Uint8Array(nacl.sign.seedLength) | ||
7 | // for (let i = 0; i < m.length; i++) m[i] = hash[i] | ||
8 | |||
9 | // const keypair = nacl.sign.keyPair.fromSeed(m) | ||
10 | /** | ||
11 | * { | ||
12 | publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7', | ||
13 | privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453' | ||
14 | } | ||
15 | */ | ||
16 | const hash=SM.sm3(secret) | ||
17 | const keypair =SM.sm2.generateKeyPairHexByHashValue(hash) | ||
18 | let sigValueHex = SM.sm2.doSignature(secret, keypair.privateKey) | ||
19 | let verifyResult = SM.sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey) | ||
20 | console.log(verifyResult) | ||
21 | return { | ||
22 | publicKey: (keypair.publicKey), | ||
23 | privateKey: (keypair.privateKey) | ||
24 | } | ||
25 | |||
26 | } | ||
27 | function bufToHex(data) { | ||
28 | return Buffer.from(data).toString('hex') | ||
29 | } | ||
30 | console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output")) |
.history/tet_20210804210037.js
0 → 100644
1 | const SM = require('./src') | ||
2 | |||
3 | function getKeys(secret) { | ||
4 | // const hash = createHash(Buffer.from(secret)) | ||
5 | |||
6 | // const m = new Uint8Array(nacl.sign.seedLength) | ||
7 | // for (let i = 0; i < m.length; i++) m[i] = hash[i] | ||
8 | |||
9 | // const keypair = nacl.sign.keyPair.fromSeed(m) | ||
10 | /** | ||
11 | * { | ||
12 | publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7', | ||
13 | privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453' | ||
14 | } | ||
15 | */ | ||
16 | const hash=SM.sm3(secret) | ||
17 | const keypair =SM.sm2.generateKeyPairHexByHashValue(hash) | ||
18 | let sigValueHex = SM.sm2.doSignature(secret, keypair.privateKey) | ||
19 | let verifyResult = SM.sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey) | ||
20 | console.log(verifyResult) | ||
21 | return { | ||
22 | publicKey: (keypair.publicKey), | ||
23 | privateKey: (keypair.privateKey) | ||
24 | } | ||
25 | |||
26 | } | ||
27 | function bufToHex(data) { | ||
28 | return Buffer.from(data).toString('hex') | ||
29 | } | ||
30 | console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output")) |
.npmignore
0 → 100644
LICENCE_MIT
0 → 100644
1 | Copyright © 2018 june01 | ||
2 | |||
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
4 | |||
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
6 | |||
7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
README.md
0 → 100644
1 | # sm-crypto | ||
2 | |||
3 | 国密算法sm2、sm3和sm4的js版。 | ||
4 | |||
5 | > PS: 小程序移植版:[https://github.com/wechat-miniprogram/sm-crypto](https://github.com/wechat-miniprogram/sm-crypto) | ||
6 | |||
7 | ## 安装 | ||
8 | |||
9 | ```bash | ||
10 | npm install --save @ddn/sm-crypto | ||
11 | ``` | ||
12 | |||
13 | ## sm2 | ||
14 | |||
15 | ### 获取密钥对 | ||
16 | |||
17 | ```js | ||
18 | const sm2 = require('@ddn/sm-crypto').sm2; | ||
19 | |||
20 | let keypair = sm2.generateKeyPairHex(); | ||
21 | |||
22 | publicKey = keypair.publicKey; // 公钥 | ||
23 | privateKey = keypair.privateKey; // 私钥 | ||
24 | ``` | ||
25 | |||
26 | ### 获取密钥对根据hash | ||
27 | |||
28 | ```js | ||
29 | const sm2 = require('@ddn/sm-crypto').sm2; | ||
30 | const secret='enter boring shaft rent essence foil trick vibrant fabric quote indoor output' | ||
31 | let keypair = sm2.generateKeyPairHex(); | ||
32 | |||
33 | publicKey = keypair.publicKey; // 公钥 | ||
34 | privateKey = keypair.privateKey; // 私钥 | ||
35 | ``` | ||
36 | |||
37 | ### 加密解密 | ||
38 | |||
39 | ```js | ||
40 | const sm2 = require('@ddn/sm-crypto').sm2; | ||
41 | const cipherMode = 1; // 1 - C1C3C2,0 - C1C2C3,默认为1 | ||
42 | |||
43 | let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode); // 加密结果 | ||
44 | let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode); // 解密结果 | ||
45 | ``` | ||
46 | |||
47 | ### 签名验签 | ||
48 | |||
49 | > ps:理论上来说,只做纯签名是最快的。 | ||
50 | |||
51 | ```js | ||
52 | const sm2 = require('@ddn/sm-crypto').sm2; | ||
53 | |||
54 | // 纯签名 + 生成椭圆曲线点 | ||
55 | let sigValueHex = sm2.doSignature(msg, privateKey); // 签名 | ||
56 | let verifyResult = sm2.doVerifySignature(msg, sigValueHex, publicKey); // 验签结果 | ||
57 | |||
58 | // 纯签名 | ||
59 | let sigValueHex2 = sm2.doSignature(msg, privateKey, { | ||
60 | pointPool: [sm2.getPoint(), sm2.getPoint(), sm2.getPoint(), sm2.getPoint()], // 传入事先已生成好的椭圆曲线点,可加快签名速度 | ||
61 | }); // 签名 | ||
62 | let verifyResult2 = sm2.doVerifySignature(msg, sigValueHex2, publicKey); // 验签结果 | ||
63 | |||
64 | // 纯签名 + 生成椭圆曲线点 + der编解码 | ||
65 | let sigValueHex3 = sm2.doSignature(msg, privateKey, { | ||
66 | der: true, | ||
67 | }); // 签名 | ||
68 | let verifyResult3 = sm2.doVerifySignature(msg, sigValueHex3, publicKey, { | ||
69 | der: true, | ||
70 | }); // 验签结果 | ||
71 | |||
72 | // 纯签名 + 生成椭圆曲线点 + sm3杂凑 | ||
73 | let sigValueHex4 = sm2.doSignature(msg, privateKey, { | ||
74 | hash: true, | ||
75 | }); // 签名 | ||
76 | let verifyResult4 = sm2.doVerifySignature(msg, sigValueHex4, publicKey, { | ||
77 | hash: true, | ||
78 | }); // 验签结果 | ||
79 | |||
80 | // 纯签名 + 生成椭圆曲线点 + sm3杂凑(不做公钥推导) | ||
81 | let sigValueHex5 = sm2.doSignature(msg, privateKey, { | ||
82 | hash: true, | ||
83 | publicKey, // 传入公钥的话,可以去掉sm3杂凑中推导公钥的过程,速度会比纯签名 + 生成椭圆曲线点 + sm3杂凑快 | ||
84 | }); | ||
85 | let verifyResult5 = sm2.doVerifySignature(msg, sigValueHex5, publicKey, { | ||
86 | hash: true, | ||
87 | publicKey, | ||
88 | }); | ||
89 | ``` | ||
90 | |||
91 | ### 获取椭圆曲线点 | ||
92 | |||
93 | ```js | ||
94 | const sm2 = require('@ddn/sm-crypto').sm2; | ||
95 | |||
96 | let poin = sm2.getPoint(); // 获取一个椭圆曲线点,可在sm2签名时传入 | ||
97 | ``` | ||
98 | |||
99 | ## sm3 | ||
100 | |||
101 | ```js | ||
102 | const sm3 = require('@ddn/sm-crypto').sm3; | ||
103 | |||
104 | let hashData = sm3('abc'); // 杂凑 | ||
105 | ``` | ||
106 | |||
107 | ## sm4 | ||
108 | |||
109 | ### 加密 | ||
110 | |||
111 | ```js | ||
112 | const sm4 = require('@ddn/sm-crypto').sm4; | ||
113 | const key = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10]; | ||
114 | |||
115 | let encryptData = sm4.encrypt([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10], key); // 加密 | ||
116 | ``` | ||
117 | |||
118 | ### 解密 | ||
119 | |||
120 | ```js | ||
121 | const sm4 = require('@ddn/sm-crypto').sm4; | ||
122 | const key = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10]; | ||
123 | |||
124 | let decryptData = sm4.decrypt([0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46], key); // 解密 | ||
125 | ``` | ||
126 | |||
127 | ## 协议 | ||
128 | |||
129 | MIT |
dist/sm2.js
0 → 100644
This diff is collapsed.
Click to expand it.
dist/sm3.js
0 → 100644
1 | window.sm3=function(n){function r(u){if(t[u])return t[u].exports;var e=t[u]={i:u,l:!1,exports:{}};return n[u].call(e.exports,e,e.exports,r),e.l=!0,e.exports}var t={};return r.m=n,r.c=t,r.d=function(n,t,u){r.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:u})},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,r){return Object.prototype.hasOwnProperty.call(n,r)},r.p="",r(r.s=7)}({7:function(n,r,t){"use strict";function u(n,r){return n.length>=r?n:new Array(r-n.length+1).join("0")+n}function e(n){for(var r="",t=0;t<n.length/8;t++)r+=u(parseInt(n.substr(8*t,8),2).toString(16),2);return r}function o(n){for(var r="",t=0;t<n.length/2;t++)r+=u(parseInt(n.substr(2*t,2),16).toString(2),8);return r}function i(n){for(var r="",t=0,e=n.length;t<e;t++){r+=u(n[t].codePointAt(0).toString(2),8)}return r}function f(n,r){return n.substring(r%n.length)+n.substr(0,r%n.length)}function c(n,r,t){for(var u=n||"",e=r||"",o=[],i=void 0,f=u.length-1;f>=0;f--)i=t(u[f],e[f],i),o[f]=i[0];return o.join("")}function a(n,r){return c(n,r,function(n,r){return[n===r?"0":"1"]})}function s(n,r){return c(n,r,function(n,r){return["1"===n&&"1"===r?"1":"0"]})}function v(n,r){return c(n,r,function(n,r){return["1"===n||"1"===r?"1":"0"]})}function l(n,r){return c(n,r,function(n,r,t){var u=t?t[1]:"0";return n!==r?["0"===u?"1":"0",u]:[u,n]})}function d(n){return c(n,void 0,function(n){return["1"===n?"0":"1"]})}function g(n){return function(){for(var r=arguments.length,t=Array(r),u=0;u<r;u++)t[u]=arguments[u];return t.reduce(function(r,t){return n(r,t)})}}function p(n){return g(a)(n,f(n,9),f(n,17))}function b(n){return g(a)(n,f(n,15),f(n,23))}function h(n,r,t,u){return u>=0&&u<=15?g(a)(n,r,t):g(v)(s(n,r),s(n,t),s(r,t))}function x(n,r,t,u){return u>=0&&u<=15?g(a)(n,r,t):v(s(n,r),s(d(n),t))}function j(n){return o(n>=0&&n<=15?"79cc4519":"7a879d8a")}function y(n,r){for(var t=[],u=[],e=0;e<16;e++)t.push(r.substr(32*e,32));for(var o=16;o<68;o++)t.push(g(a)(b(g(a)(t[o-16],t[o-9],f(t[o-3],15))),f(t[o-13],7),t[o-6]));for(var i=0;i<64;i++)u.push(a(t[i],t[i+4]));for(var c=[],s=0;s<8;s++)c.push(n.substr(32*s,32));for(var v=c[0],d=c[1],y=c[2],S=c[3],w=c[4],m=c[5],A=c[6],O=c[7],P=void 0,I=void 0,_=void 0,M=void 0,k=0;k<64;k++)P=f(g(l)(f(v,12),w,f(j(k),k)),7),I=a(P,f(v,12)),_=g(l)(h(v,d,y,k),S,I,u[k]),M=g(l)(x(w,m,A,k),O,P,t[k]),S=y,y=f(d,9),d=v,v=_,O=A,A=f(m,19),m=w,w=p(M);return a([v,d,y,S,w,m,A,O].join(""),n)}n.exports=function(n){var r=i(n),t=r.length,f=t%512;f=f>=448?512-f%448-1:448-f-1;for(var c=(r+"1"+u("",f)+u(t.toString(2),64)).toString(),a=(t+f+65)/512,s=o("7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e"),v=0;v<=a-1;v++){s=y(s,c.substr(512*v,512))}return e(s)}}}); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
dist/sm4.js
0 → 100644
1 | window.sm4=function(r){function n(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return r[e].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var t={};return n.m=r,n.c=t,n.d=function(r,t,e){n.o(r,t)||Object.defineProperty(r,t,{configurable:!1,enumerable:!0,get:e})},n.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return n.d(t,"a",t),t},n.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},n.p="",n(n.s=8)}({8:function(r,n,t){"use strict";function e(r,n){return r<<n|r>>>32-n}function o(r){return(255&l[r>>>24&255])<<24|(255&l[r>>>16&255])<<16|(255&l[r>>>8&255])<<8|255&l[255&r]}function u(r){return r^e(r,2)^e(r,10)^e(r,18)^e(r,24)}function f(r){return r^e(r,13)^e(r,23)}function i(r,n,t){for(var e=void 0,f=void 0,i=new Array(4),c=new Array(4),a=0;a<4;a++)c[0]=255&r[0+4*a],c[1]=255&r[1+4*a],c[2]=255&r[2+4*a],c[3]=255&r[3+4*a],i[a]=c[0]<<24|c[1]<<16|c[2]<<8|c[3];for(e=0;e<32;e+=4)f=i[1]^i[2]^i[3]^t[e+0],f=o(f),i[0]^=u(f),f=i[2]^i[3]^i[0]^t[e+1],f=o(f),i[1]^=u(f),f=i[3]^i[0]^i[1]^t[e+2],f=o(f),i[2]^=u(f),f=i[0]^i[1]^i[2]^t[e+3],f=o(f),i[3]^=u(f);for(var v=0;v<16;v+=4)n[v]=i[3-v/4]>>>24&255,n[v+1]=i[3-v/4]>>>16&255,n[v+2]=i[3-v/4]>>>8&255,n[v+3]=255&i[3-v/4]}function c(r,n,t){for(var e=void 0,u=void 0,i=new Array(4),c=new Array(4),a=0;a<4;a++)c[0]=255&r[0+4*a],c[1]=255&r[1+4*a],c[2]=255&r[2+4*a],c[3]=255&r[3+4*a],i[a]=c[0]<<24|c[1]<<16|c[2]<<8|c[3];for(i[0]^=2746333894,i[1]^=1453994832,i[2]^=1736282519,i[3]^=2993693404,e=0;e<32;e+=4)u=i[1]^i[2]^i[3]^y[e+0],u=o(u),n[e+0]=i[0]^=f(u),u=i[2]^i[3]^i[0]^y[e+1],u=o(u),n[e+1]=i[1]^=f(u),u=i[3]^i[0]^i[1]^y[e+2],u=o(u),n[e+2]=i[2]^=f(u),u=i[0]^i[1]^i[2]^y[e+3],u=o(u),n[e+3]=i[3]^=f(u);if(t===v)for(e=0;e<16;e++)u=n[e],n[e]=n[31-e],n[31-e]=u}function a(r,n,t){var e=[],o=0,u=new Array(p);c(n,u,t);for(var f=new Array(16),a=new Array(16),v=r.length;v>=s;){f=r.slice(o,o+16),i(f,a,u);for(var l=0;l<s;l++)e[o+l]=a[l];v-=s,o+=s}return e}var v=0,p=32,s=16,l=[214,144,233,254,204,225,61,183,22,182,20,194,40,251,44,5,43,103,154,118,42,190,4,195,170,68,19,38,73,134,6,153,156,66,80,244,145,239,152,122,51,84,11,67,237,207,172,98,228,179,28,169,201,8,232,149,128,223,148,250,117,143,63,166,71,7,167,252,243,115,23,186,131,89,60,25,230,133,79,168,104,107,129,178,113,100,218,139,248,235,15,75,112,86,157,53,30,36,14,94,99,88,209,162,37,34,124,59,1,33,120,135,212,0,70,87,159,211,39,82,76,54,2,231,160,196,200,158,234,191,138,210,64,199,56,181,163,247,242,206,249,97,21,161,224,174,93,164,155,52,26,85,173,147,50,48,245,140,177,227,29,246,226,46,130,102,202,96,192,41,35,171,13,83,78,111,213,219,55,69,222,253,142,47,3,255,106,114,109,108,91,81,141,27,175,146,187,221,188,127,17,217,92,65,31,16,90,216,10,193,49,136,165,205,123,189,45,116,208,18,184,229,180,176,137,105,151,74,12,150,119,126,101,185,241,9,197,110,198,132,24,240,125,236,58,220,77,32,121,238,95,62,215,203,57,72],y=[462357,472066609,943670861,1415275113,1886879365,2358483617,2830087869,3301692121,3773296373,4228057617,404694573,876298825,1347903077,1819507329,2291111581,2762715833,3234320085,3705924337,4177462797,337322537,808926789,1280531041,1752135293,2223739545,2695343797,3166948049,3638552301,4110090761,269950501,741554753,1213159005,1684763257];r.exports={encrypt:function(r,n){return a(r,n,1)},decrypt:function(r,n){return a(r,n,0)}}}}); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
docs/SM2椭圆曲线公钥密码算法.pdf
0 → 100644
No preview for this file type
docs/SM3密码杂凑算法.pdf
0 → 100644
No preview for this file type
docs/SM4分组密码算法.pdf
0 → 100644
No preview for this file type
package.json
0 → 100644
1 | { | ||
2 | "name": "@ddn/sm-crypto", | ||
3 | "version": "0.0.1", | ||
4 | "description": "@ddn/sm-crypto,基于sm-crypto。", | ||
5 | "main": "dist/index.js", | ||
6 | "scripts": { | ||
7 | "prepublish": "npm run build", | ||
8 | "test": "jest ./test/*", | ||
9 | "lint": "eslint \"src/**/*.js\" --fix", | ||
10 | "build": "npm run lint && webpack" | ||
11 | }, | ||
12 | "repository": { | ||
13 | "type": "git", | ||
14 | "url": "git+https://github.com/ddnlink" | ||
15 | }, | ||
16 | "files": [ | ||
17 | "dist", | ||
18 | "README.md" | ||
19 | ], | ||
20 | "keywords": [ | ||
21 | "ddn", | ||
22 | "sm", | ||
23 | "js", | ||
24 | "crypto" | ||
25 | ], | ||
26 | "jest": { | ||
27 | "testEnvironment": "jsdom", | ||
28 | "testURL": "https://jest.test" | ||
29 | }, | ||
30 | "author": "creazy", | ||
31 | "license": "MIT", | ||
32 | "dependencies": { | ||
33 | "jsbn": "^1.1.0" | ||
34 | }, | ||
35 | "devDependencies": { | ||
36 | "babel-core": "^6.26.0", | ||
37 | "babel-loader": "^7.1.2", | ||
38 | "babel-preset-es2015": "^6.24.1", | ||
39 | "jest": "^22.1.4", | ||
40 | "webpack": "^3.10.0", | ||
41 | "eslint": "^5.3.0", | ||
42 | "eslint-config-airbnb-base": "13.1.0", | ||
43 | "eslint-plugin-import": "^2.14.0", | ||
44 | "eslint-plugin-node": "^7.0.1", | ||
45 | "eslint-plugin-promise": "^3.8.0" | ||
46 | } | ||
47 | } |
src/index.js
0 → 100644
src/sm2/asn1.js
0 → 100644
1 | /* eslint-disable class-methods-use-this */ | ||
2 | const {BigInteger} = require('jsbn') | ||
3 | |||
4 | function bigIntToMinTwosComplementsHex(bigIntegerValue) { | ||
5 | let h = bigIntegerValue.toString(16) | ||
6 | if (h.substr(0, 1) !== '-') { | ||
7 | if (h.length % 2 === 1) { | ||
8 | h = '0' + h | ||
9 | } else if (!h.match(/^[0-7]/)) { | ||
10 | h = '00' + h | ||
11 | } | ||
12 | } else { | ||
13 | const hPos = h.substr(1) | ||
14 | let xorLen = hPos.length | ||
15 | if (xorLen % 2 === 1) { | ||
16 | xorLen += 1 | ||
17 | } else if (!h.match(/^[0-7]/)) { | ||
18 | xorLen += 2 | ||
19 | } | ||
20 | let hMask = '' | ||
21 | for (let i = 0; i < xorLen; i++) { | ||
22 | hMask += 'f' | ||
23 | } | ||
24 | const biMask = new BigInteger(hMask, 16) | ||
25 | const biNeg = biMask.xor(bigIntegerValue).add(BigInteger.ONE) | ||
26 | h = biNeg.toString(16).replace(/^-/, '') | ||
27 | } | ||
28 | return h | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * base class for ASN.1 DER encoder object | ||
33 | */ | ||
34 | class ASN1Object { | ||
35 | constructor() { | ||
36 | this.isModified = true | ||
37 | this.hTLV = null | ||
38 | this.hT = '00' | ||
39 | this.hL = '00' | ||
40 | this.hV = '' | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * get hexadecimal ASN.1 TLV length(L) bytes from TLV value(V) | ||
45 | */ | ||
46 | getLengthHexFromValue() { | ||
47 | const n = this.hV.length / 2 | ||
48 | let hN = n.toString(16) | ||
49 | if (hN.length % 2 === 1) { | ||
50 | hN = '0' + hN | ||
51 | } | ||
52 | if (n < 128) { | ||
53 | return hN | ||
54 | } else { | ||
55 | const hNlen = hN.length / 2 | ||
56 | const head = 128 + hNlen | ||
57 | return head.toString(16) + hN | ||
58 | } | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * get hexadecimal string of ASN.1 TLV bytes | ||
63 | */ | ||
64 | getEncodedHex() { | ||
65 | if (this.hTLV == null || this.isModified) { | ||
66 | this.hV = this.getFreshValueHex() | ||
67 | this.hL = this.getLengthHexFromValue() | ||
68 | this.hTLV = this.hT + this.hL + this.hV | ||
69 | this.isModified = false | ||
70 | } | ||
71 | return this.hTLV | ||
72 | } | ||
73 | |||
74 | getFreshValueHex() { | ||
75 | return '' | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * class for ASN.1 DER Integer | ||
81 | */ | ||
82 | class DERInteger extends ASN1Object { | ||
83 | constructor(options) { | ||
84 | super() | ||
85 | |||
86 | this.hT = '02' | ||
87 | if (options && options.bigint) { | ||
88 | this.hTLV = null | ||
89 | this.isModified = true | ||
90 | this.hV = bigIntToMinTwosComplementsHex(options.bigint) | ||
91 | } | ||
92 | } | ||
93 | |||
94 | getFreshValueHex() { | ||
95 | return this.hV | ||
96 | } | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * class for ASN.1 DER Sequence | ||
101 | */ | ||
102 | class DERSequence extends ASN1Object { | ||
103 | constructor(options) { | ||
104 | super() | ||
105 | |||
106 | this.hT = '30' | ||
107 | this.asn1Array = [] | ||
108 | if (options && options.array) { | ||
109 | this.asn1Array = options.array | ||
110 | } | ||
111 | } | ||
112 | |||
113 | getFreshValueHex() { | ||
114 | let h = '' | ||
115 | for (let i = 0; i < this.asn1Array.length; i++) { | ||
116 | const asn1Obj = this.asn1Array[i] | ||
117 | h += asn1Obj.getEncodedHex() | ||
118 | } | ||
119 | this.hV = h | ||
120 | return this.hV | ||
121 | } | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * get byte length for ASN.1 L(length) bytes | ||
126 | */ | ||
127 | function getByteLengthOfL(s, pos) { | ||
128 | if (s.substring(pos + 2, pos + 3) !== '8') return 1 | ||
129 | const i = parseInt(s.substring(pos + 3, pos + 4), 10) | ||
130 | if (i === 0) return -1 // length octet '80' indefinite length | ||
131 | if (i > 0 && i < 10) return i + 1 // including '8?' octet; | ||
132 | return -2 // malformed format | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * get hexadecimal string for ASN.1 L(length) bytes | ||
137 | */ | ||
138 | function getHexOfL(s, pos) { | ||
139 | const len = getByteLengthOfL(s, pos) | ||
140 | if (len < 1) return '' | ||
141 | return s.substring(pos + 2, pos + 2 + len * 2) | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * get integer value of ASN.1 length for ASN.1 data | ||
146 | */ | ||
147 | function getIntOfL(s, pos) { | ||
148 | const hLength = getHexOfL(s, pos) | ||
149 | if (hLength === '') return -1 | ||
150 | let bi | ||
151 | if (parseInt(hLength.substring(0, 1), 10) < 8) { | ||
152 | bi = new BigInteger(hLength, 16) | ||
153 | } else { | ||
154 | bi = new BigInteger(hLength.substring(2), 16) | ||
155 | } | ||
156 | return bi.intValue() | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'. | ||
161 | */ | ||
162 | function getStartPosOfV(s, pos) { | ||
163 | const lLen = getByteLengthOfL(s, pos) | ||
164 | if (lLen < 0) return lLen | ||
165 | return pos + (lLen + 1) * 2 | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * get hexadecimal string of ASN.1 V(value) | ||
170 | */ | ||
171 | function getHexOfV(s, pos) { | ||
172 | const pos1 = getStartPosOfV(s, pos) | ||
173 | const len = getIntOfL(s, pos) | ||
174 | return s.substring(pos1, pos1 + len * 2) | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * get next sibling starting index for ASN.1 object string | ||
179 | */ | ||
180 | function getPosOfNextSibling(s, pos) { | ||
181 | const pos1 = getStartPosOfV(s, pos) | ||
182 | const len = getIntOfL(s, pos) | ||
183 | return pos1 + len * 2 | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * get array of indexes of child ASN.1 objects | ||
188 | */ | ||
189 | function getPosArrayOfChildren(h, pos) { | ||
190 | const a = [] | ||
191 | const p0 = getStartPosOfV(h, pos) | ||
192 | a.push(p0) | ||
193 | |||
194 | const len = getIntOfL(h, pos) | ||
195 | let p = p0 | ||
196 | let k = 0 | ||
197 | for (;;) { | ||
198 | const pNext = getPosOfNextSibling(h, p) | ||
199 | if (pNext == null || (pNext - p0 >= (len * 2))) break | ||
200 | if (k >= 200) break | ||
201 | |||
202 | a.push(pNext) | ||
203 | p = pNext | ||
204 | |||
205 | k++ | ||
206 | } | ||
207 | |||
208 | return a | ||
209 | } | ||
210 | |||
211 | module.exports = { | ||
212 | /** | ||
213 | * ASN.1 DER编码 | ||
214 | */ | ||
215 | encodeDer(r, s) { | ||
216 | const derR = new DERInteger({bigint: r}) | ||
217 | const derS = new DERInteger({bigint: s}) | ||
218 | const derSeq = new DERSequence({array: [derR, derS]}) | ||
219 | |||
220 | return derSeq.getEncodedHex() | ||
221 | }, | ||
222 | |||
223 | /** | ||
224 | * 解析 ASN.1 DER | ||
225 | */ | ||
226 | decodeDer(input) { | ||
227 | // 1. Items of ASN.1 Sequence Check | ||
228 | const a = getPosArrayOfChildren(input, 0) | ||
229 | |||
230 | // 2. Integer check | ||
231 | const iTLV1 = a[0] | ||
232 | const iTLV2 = a[1] | ||
233 | |||
234 | // 3. getting value | ||
235 | const hR = getHexOfV(input, iTLV1) | ||
236 | const hS = getHexOfV(input, iTLV2) | ||
237 | |||
238 | const r = new BigInteger(hR, 16) | ||
239 | const s = new BigInteger(hS, 16) | ||
240 | |||
241 | return {r, s} | ||
242 | } | ||
243 | } |
src/sm2/ec.js
0 → 100644
1 | /* eslint-disable no-case-declarations, max-len */ | ||
2 | const {BigInteger} = require('jsbn') | ||
3 | |||
4 | /** | ||
5 | * thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/ | ||
6 | * | ||
7 | * Basic Javascript Elliptic Curve implementation | ||
8 | * Ported loosely from BouncyCastle's Java EC code | ||
9 | * Only Fp curves implemented for now | ||
10 | */ | ||
11 | |||
12 | const THREE = new BigInteger('3') | ||
13 | |||
14 | /** | ||
15 | * 椭圆曲线域元素 | ||
16 | */ | ||
17 | class ECFieldElementFp { | ||
18 | constructor(q, x) { | ||
19 | this.x = x | ||
20 | this.q = q | ||
21 | // TODO if (x.compareTo(q) >= 0) error | ||
22 | } | ||
23 | |||
24 | /** | ||
25 | * 判断相等 | ||
26 | */ | ||
27 | equals(other) { | ||
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 | } | ||
80 | } | ||
81 | |||
82 | class ECPointFp { | ||
83 | constructor(curve, x, y, z) { | ||
84 | this.curve = curve | ||
85 | this.x = x | ||
86 | this.y = y | ||
87 | // 标准射影坐标系:zinv == null 或 z * zinv == 1 | ||
88 | this.z = z == null ? BigInteger.ONE : z | ||
89 | this.zinv = null | ||
90 | // TODO: compression flag | ||
91 | } | ||
92 | |||
93 | getX() { | ||
94 | if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q) | ||
95 | |||
96 | return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q)) | ||
97 | } | ||
98 | |||
99 | getY() { | ||
100 | if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q) | ||
101 | |||
102 | return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q)) | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * 判断相等 | ||
107 | */ | ||
108 | equals(other) { | ||
109 | if (other === this) return true | ||
110 | if (this.isInfinity()) return other.isInfinity() | ||
111 | if (other.isInfinity()) return this.isInfinity() | ||
112 | |||
113 | // u = y2 * z1 - y1 * z2 | ||
114 | const u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q) | ||
115 | if (!u.equals(BigInteger.ZERO)) return false | ||
116 | |||
117 | // v = x2 * z1 - x1 * z2 | ||
118 | const v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q) | ||
119 | return v.equals(BigInteger.ZERO) | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * 是否是无穷远点 | ||
124 | */ | ||
125 | isInfinity() { | ||
126 | if ((this.x === null) && (this.y === null)) return true | ||
127 | return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO) | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * 取反,x 轴对称点 | ||
132 | */ | ||
133 | negate() { | ||
134 | return new ECPointFp(this.curve, this.x, this.y.negate(), this.z) | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * 相加 | ||
139 | * | ||
140 | * 标准射影坐标系: | ||
141 | * | ||
142 | * λ1 = x1 * z2 | ||
143 | * λ2 = x2 * z1 | ||
144 | * λ3 = λ1 − λ2 | ||
145 | * λ4 = y1 * z2 | ||
146 | * λ5 = y2 * z1 | ||
147 | * λ6 = λ4 − λ5 | ||
148 | * λ7 = λ1 + λ2 | ||
149 | * λ8 = z1 * z2 | ||
150 | * λ9 = λ3^2 | ||
151 | * λ10 = λ3 * λ9 | ||
152 | * λ11 = λ8 * λ6^2 − λ7 * λ9 | ||
153 | * x3 = λ3 * λ11 | ||
154 | * y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10 | ||
155 | * z3 = λ10 * λ8 | ||
156 | */ | ||
157 | add(b) { | ||
158 | if (this.isInfinity()) return b | ||
159 | if (b.isInfinity()) return this | ||
160 | |||
161 | const x1 = this.x.toBigInteger() | ||
162 | const y1 = this.y.toBigInteger() | ||
163 | const z1 = this.z | ||
164 | const x2 = b.x.toBigInteger() | ||
165 | const y2 = b.y.toBigInteger() | ||
166 | const z2 = b.z | ||
167 | const q = this.curve.q | ||
168 | |||
169 | const w1 = x1.multiply(z2).mod(q) | ||
170 | const w2 = x2.multiply(z1).mod(q) | ||
171 | const w3 = w1.subtract(w2) | ||
172 | const w4 = y1.multiply(z2).mod(q) | ||
173 | const w5 = y2.multiply(z1).mod(q) | ||
174 | const w6 = w4.subtract(w5) | ||
175 | |||
176 | if (BigInteger.ZERO.equals(w3)) { | ||
177 | if (BigInteger.ZERO.equals(w6)) { | ||
178 | return this.twice() // this == b,计算自加 | ||
179 | } | ||
180 | return this.curve.infinity // this == -b,则返回无穷远点 | ||
181 | } | ||
182 | |||
183 | const w7 = w1.add(w2) | ||
184 | const w8 = z1.multiply(z2).mod(q) | ||
185 | const w9 = w3.square().mod(q) | ||
186 | const w10 = w3.multiply(w9).mod(q) | ||
187 | const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q) | ||
188 | |||
189 | const x3 = w3.multiply(w11).mod(q) | ||
190 | const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q) | ||
191 | const z3 = w10.multiply(w8).mod(q) | ||
192 | |||
193 | return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3) | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * 自加 | ||
198 | * | ||
199 | * 标准射影坐标系: | ||
200 | * | ||
201 | * λ1 = 3 * x1^2 + a * z1^2 | ||
202 | * λ2 = 2 * y1 * z1 | ||
203 | * λ3 = y1^2 | ||
204 | * λ4 = λ3 * x1 * z1 | ||
205 | * λ5 = λ2^2 | ||
206 | * λ6 = λ1^2 − 8 * λ4 | ||
207 | * x3 = λ2 * λ6 | ||
208 | * y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3 | ||
209 | * z3 = λ2 * λ5 | ||
210 | */ | ||
211 | twice() { | ||
212 | if (this.isInfinity()) return this | ||
213 | if (!this.y.toBigInteger().signum()) return this.curve.infinity | ||
214 | |||
215 | const x1 = this.x.toBigInteger() | ||
216 | const y1 = this.y.toBigInteger() | ||
217 | const z1 = this.z | ||
218 | const q = this.curve.q | ||
219 | const a = this.curve.a.toBigInteger() | ||
220 | |||
221 | const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q) | ||
222 | const w2 = y1.shiftLeft(1).multiply(z1).mod(q) | ||
223 | const w3 = y1.square().mod(q) | ||
224 | const w4 = w3.multiply(x1).multiply(z1).mod(q) | ||
225 | const w5 = w2.square().mod(q) | ||
226 | const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q) | ||
227 | |||
228 | const x3 = w2.multiply(w6).mod(q) | ||
229 | const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q) | ||
230 | const z3 = w2.multiply(w5).mod(q) | ||
231 | |||
232 | return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3) | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * 倍点计算 | ||
237 | */ | ||
238 | multiply(k) { | ||
239 | if (this.isInfinity()) return this | ||
240 | if (!k.signum()) return this.curve.infinity | ||
241 | |||
242 | // 使用加减法 | ||
243 | const k3 = k.multiply(THREE) | ||
244 | const neg = this.negate() | ||
245 | let Q = this | ||
246 | |||
247 | for (let i = k3.bitLength() - 2; i > 0; i--) { | ||
248 | Q = Q.twice() | ||
249 | |||
250 | const k3Bit = k3.testBit(i) | ||
251 | const kBit = k.testBit(i) | ||
252 | |||
253 | if (k3Bit !== kBit) { | ||
254 | Q = Q.add(k3Bit ? this : neg) | ||
255 | } | ||
256 | } | ||
257 | |||
258 | return Q | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * 椭圆曲线 y^2 = x^3 + ax + b | ||
264 | */ | ||
265 | class ECCurveFp { | ||
266 | constructor(q, a, b) { | ||
267 | this.q = q | ||
268 | this.a = this.fromBigInteger(a) | ||
269 | this.b = this.fromBigInteger(b) | ||
270 | this.infinity = new ECPointFp(this, null, null) // 无穷远点 | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * 判断两个椭圆曲线是否相等 | ||
275 | */ | ||
276 | equals(other) { | ||
277 | if (other === this) return true | ||
278 | return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b)) | ||
279 | } | ||
280 | |||
281 | /** | ||
282 | * 生成椭圆曲线域元素 | ||
283 | */ | ||
284 | fromBigInteger(x) { | ||
285 | return new ECFieldElementFp(this.q, x) | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * 解析 16 进制串为椭圆曲线点 | ||
290 | */ | ||
291 | decodePointHex(s) { | ||
292 | switch (parseInt(s.substr(0, 2), 16)) { | ||
293 | // 第一个字节 | ||
294 | case 0: | ||
295 | return this.infinity | ||
296 | case 2: | ||
297 | case 3: | ||
298 | // 不支持的压缩方式 | ||
299 | return null | ||
300 | case 4: | ||
301 | case 6: | ||
302 | case 7: | ||
303 | const len = (s.length - 2) / 2 | ||
304 | const xHex = s.substr(2, len) | ||
305 | const yHex = s.substr(len + 2, len) | ||
306 | |||
307 | return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16))) | ||
308 | default: | ||
309 | // 不支持 | ||
310 | return null | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | |||
315 | module.exports = { | ||
316 | ECPointFp, | ||
317 | ECCurveFp, | ||
318 | } |
src/sm2/index.js
0 → 100644
1 | /* eslint-disable no-use-before-define */ | ||
2 | const {BigInteger} = require('jsbn') | ||
3 | const {encodeDer, decodeDer} = require('./asn1') | ||
4 | const SM3Digest = require('./sm3') | ||
5 | const SM2Cipher = require('./sm2') | ||
6 | const _ = require('./utils') | ||
7 | |||
8 | const {G, curve, n} = _.generateEcparam() | ||
9 | const C1C2C3 = 0 | ||
10 | |||
11 | /** | ||
12 | * 加密 | ||
13 | */ | ||
14 | function doEncrypt(msg, publicKey, cipherMode = 1) { | ||
15 | const cipher = new SM2Cipher() | ||
16 | msg = _.hexToArray(_.parseUtf8StringToHex(msg)) | ||
17 | |||
18 | if (publicKey.length > 128) { | ||
19 | publicKey = publicKey.substr(publicKey.length - 128) | ||
20 | } | ||
21 | const xHex = publicKey.substr(0, 64) | ||
22 | const yHex = publicKey.substr(64) | ||
23 | publicKey = cipher.createPoint(xHex, yHex) | ||
24 | |||
25 | const c1 = cipher.initEncipher(publicKey) | ||
26 | |||
27 | cipher.encryptBlock(msg) | ||
28 | const c2 = _.arrayToHex(msg) | ||
29 | |||
30 | let c3 = new Array(32) | ||
31 | cipher.doFinal(c3) | ||
32 | c3 = _.arrayToHex(c3) | ||
33 | |||
34 | return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2 | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * 解密 | ||
39 | */ | ||
40 | function doDecrypt(encryptData, privateKey, cipherMode = 1) { | ||
41 | const cipher = new SM2Cipher() | ||
42 | |||
43 | privateKey = new BigInteger(privateKey, 16) | ||
44 | |||
45 | const c1X = encryptData.substr(0, 64) | ||
46 | const c1Y = encryptData.substr(0 + c1X.length, 64) | ||
47 | const c1Length = c1X.length + c1Y.length | ||
48 | |||
49 | let c3 = encryptData.substr(c1Length, 64) | ||
50 | let c2 = encryptData.substr(c1Length + 64) | ||
51 | |||
52 | if (cipherMode === C1C2C3) { | ||
53 | c3 = encryptData.substr(encryptData.length - 64) | ||
54 | c2 = encryptData.substr(c1Length, encryptData.length - c1Length - 64) | ||
55 | } | ||
56 | |||
57 | const data = _.hexToArray(c2) | ||
58 | |||
59 | const c1 = cipher.createPoint(c1X, c1Y) | ||
60 | cipher.initDecipher(privateKey, c1) | ||
61 | cipher.decryptBlock(data) | ||
62 | const c3_ = new Array(32) | ||
63 | cipher.doFinal(c3_) | ||
64 | |||
65 | const isDecrypt = _.arrayToHex(c3_) === c3 | ||
66 | |||
67 | if (isDecrypt) { | ||
68 | const decryptData = _.arrayToUtf8(data) | ||
69 | return decryptData | ||
70 | } else { | ||
71 | return '' | ||
72 | } | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * 签名 | ||
77 | */ | ||
78 | function doSignature(msg, privateKey, { | ||
79 | pointPool, der, hash, publicKey | ||
80 | } = {}) { | ||
81 | let hashHex = typeof msg === 'string' ? _.parseUtf8StringToHex(msg) : _.parseArrayBufferToHex(msg) | ||
82 | |||
83 | if (hash) { | ||
84 | // sm3杂凑 | ||
85 | publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey) | ||
86 | hashHex = doSm3Hash(hashHex, publicKey) | ||
87 | } | ||
88 | |||
89 | const dA = new BigInteger(privateKey, 16) | ||
90 | const e = new BigInteger(hashHex, 16) | ||
91 | |||
92 | // k | ||
93 | let k = null | ||
94 | let r = null | ||
95 | let s = null | ||
96 | |||
97 | do { | ||
98 | do { | ||
99 | let point | ||
100 | if (pointPool && pointPool.length) { | ||
101 | point = pointPool.pop() | ||
102 | } else { | ||
103 | point = getPoint() | ||
104 | } | ||
105 | k = point.k | ||
106 | |||
107 | // r = (e + x1) mod n | ||
108 | r = e.add(point.x1).mod(n) | ||
109 | } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n)) | ||
110 | |||
111 | // s = ((1 + dA)^-1 * (k - r * dA)) mod n | ||
112 | s = dA.add(BigInteger.ONE).modInverse(n).multiply(k.subtract(r.multiply(dA))).mod(n) | ||
113 | } while (s.equals(BigInteger.ZERO)) | ||
114 | |||
115 | if (der) { | ||
116 | // asn1 der编码 | ||
117 | return encodeDer(r, s) | ||
118 | } | ||
119 | |||
120 | return _.leftPad(r.toString(16), 64) + _.leftPad(s.toString(16), 64) | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * 验签 | ||
125 | */ | ||
126 | function doVerifySignature(msg, signHex, publicKey, {der, hash} = {}) { | ||
127 | let hashHex = typeof msg === 'string' ? _.parseUtf8StringToHex(msg) : _.parseArrayBufferToHex(msg) | ||
128 | |||
129 | if (hash) { | ||
130 | // sm3杂凑 | ||
131 | hashHex = doSm3Hash(hashHex, publicKey) | ||
132 | } | ||
133 | |||
134 | let r; let | ||
135 | s | ||
136 | if (der) { | ||
137 | const decodeDerObj = decodeDer(signHex) | ||
138 | r = decodeDerObj.r | ||
139 | s = decodeDerObj.s | ||
140 | } else { | ||
141 | r = new BigInteger(signHex.substring(0, 64), 16) | ||
142 | s = new BigInteger(signHex.substring(64), 16) | ||
143 | } | ||
144 | |||
145 | const PA = curve.decodePointHex(publicKey) | ||
146 | const e = new BigInteger(hashHex, 16) | ||
147 | |||
148 | // t = (r + s) mod n | ||
149 | const t = r.add(s).mod(n) | ||
150 | |||
151 | if (t.equals(BigInteger.ZERO)) return false | ||
152 | |||
153 | // x1y1 = s * G + t * PA | ||
154 | const x1y1 = G.multiply(s).add(PA.multiply(t)) | ||
155 | |||
156 | // R = (e + x1) mod n | ||
157 | const R = e.add(x1y1.getX().toBigInteger()).mod(n) | ||
158 | |||
159 | return r.equals(R) | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * sm3杂凑算法 | ||
164 | */ | ||
165 | function doSm3Hash(hashHex, publicKey) { | ||
166 | const smDigest = new SM3Digest() | ||
167 | |||
168 | const z = new SM3Digest().getZ(G, publicKey.substr(2, 128)) | ||
169 | const zValue = _.hexToArray(_.arrayToHex(z).toString()) | ||
170 | |||
171 | const p = hashHex | ||
172 | const pValue = _.hexToArray(p) | ||
173 | |||
174 | const hashData = new Array(smDigest.getDigestSize()) | ||
175 | smDigest.blockUpdate(zValue, 0, zValue.length) | ||
176 | smDigest.blockUpdate(pValue, 0, pValue.length) | ||
177 | smDigest.doFinal(hashData, 0) | ||
178 | |||
179 | return _.arrayToHex(hashData).toString() | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * 计算公钥 | ||
184 | */ | ||
185 | function getPublicKeyFromPrivateKey(privateKey) { | ||
186 | const PA = G.multiply(new BigInteger(privateKey, 16)) | ||
187 | const x = _.leftPad(PA.getX().toBigInteger().toString(16), 64) | ||
188 | const y = _.leftPad(PA.getY().toBigInteger().toString(16), 64) | ||
189 | return '04' + x + y | ||
190 | } | ||
191 | |||
192 | /** | ||
193 | * 获取椭圆曲线点 | ||
194 | */ | ||
195 | function getPoint() { | ||
196 | const keypair = _.generateKeyPairHex() | ||
197 | const PA = curve.decodePointHex(keypair.publicKey) | ||
198 | |||
199 | keypair.k = new BigInteger(keypair.privateKey, 16) | ||
200 | keypair.x1 = PA.getX().toBigInteger() | ||
201 | |||
202 | return keypair | ||
203 | } | ||
204 | |||
205 | module.exports = { | ||
206 | generateKeyPairHex: _.generateKeyPairHex, | ||
207 | generateKeyPairHexBySecret: _.generateKeyPairHexBySecret, | ||
208 | doEncrypt, | ||
209 | doDecrypt, | ||
210 | doSignature, | ||
211 | doVerifySignature, | ||
212 | getPoint, | ||
213 | } |
src/sm2/sm2.js
0 → 100644
1 | /* eslint-disable no-bitwise, no-mixed-operators, class-methods-use-this */ | ||
2 | const {BigInteger} = require('jsbn') | ||
3 | const SM3Digest = require('./sm3') | ||
4 | const _ = require('./utils') | ||
5 | |||
6 | class SM2Cipher { | ||
7 | constructor() { | ||
8 | this.ct = 1 | ||
9 | this.p2 = null | ||
10 | this.sm3keybase = null | ||
11 | this.sm3c3 = null | ||
12 | this.key = new Array(32) | ||
13 | this.keyOff = 0 | ||
14 | } | ||
15 | |||
16 | reset() { | ||
17 | this.sm3keybase = new SM3Digest() | ||
18 | this.sm3c3 = new SM3Digest() | ||
19 | const xWords = _.hexToArray(this.p2.getX().toBigInteger().toRadix(16)) | ||
20 | const yWords = _.hexToArray(this.p2.getY().toBigInteger().toRadix(16)) | ||
21 | this.sm3keybase.blockUpdate(xWords, 0, xWords.length) | ||
22 | this.sm3c3.blockUpdate(xWords, 0, xWords.length) | ||
23 | this.sm3keybase.blockUpdate(yWords, 0, yWords.length) | ||
24 | this.ct = 1 | ||
25 | this.nextKey() | ||
26 | } | ||
27 | |||
28 | nextKey() { | ||
29 | const sm3keycur = new SM3Digest(this.sm3keybase) | ||
30 | sm3keycur.update((this.ct >> 24 & 0x00ff)) | ||
31 | sm3keycur.update((this.ct >> 16 & 0x00ff)) | ||
32 | sm3keycur.update((this.ct >> 8 & 0x00ff)) | ||
33 | sm3keycur.update((this.ct & 0x00ff)) | ||
34 | sm3keycur.doFinal(this.key, 0) | ||
35 | this.keyOff = 0 | ||
36 | this.ct++ | ||
37 | } | ||
38 | |||
39 | initEncipher(userKey) { | ||
40 | const keypair = _.generateKeyPairHex() | ||
41 | const k = new BigInteger(keypair.privateKey, 16) | ||
42 | let publicKey = keypair.publicKey | ||
43 | |||
44 | this.p2 = userKey.multiply(k) // [k](Pb) | ||
45 | this.reset() | ||
46 | |||
47 | if (publicKey.length > 128) { | ||
48 | publicKey = publicKey.substr(publicKey.length - 128) | ||
49 | } | ||
50 | |||
51 | return publicKey | ||
52 | } | ||
53 | |||
54 | encryptBlock(data) { | ||
55 | this.sm3c3.blockUpdate(data, 0, data.length) | ||
56 | for (let i = 0; i < data.length; i++) { | ||
57 | if (this.keyOff === this.key.length) { | ||
58 | this.nextKey() | ||
59 | } | ||
60 | data[i] ^= this.key[this.keyOff++] & 0xff | ||
61 | } | ||
62 | } | ||
63 | |||
64 | initDecipher(userD, c1) { | ||
65 | this.p2 = c1.multiply(userD) | ||
66 | this.reset() | ||
67 | } | ||
68 | |||
69 | decryptBlock(data) { | ||
70 | for (let i = 0; i < data.length; i++) { | ||
71 | if (this.keyOff === this.key.length) { | ||
72 | this.nextKey() | ||
73 | } | ||
74 | data[i] ^= this.key[this.keyOff++] & 0xff | ||
75 | } | ||
76 | this.sm3c3.blockUpdate(data, 0, data.length) | ||
77 | } | ||
78 | |||
79 | doFinal(c3) { | ||
80 | const yWords = _.hexToArray(this.p2.getY().toBigInteger().toRadix(16)) | ||
81 | this.sm3c3.blockUpdate(yWords, 0, yWords.length) | ||
82 | this.sm3c3.doFinal(c3, 0) | ||
83 | this.reset() | ||
84 | } | ||
85 | |||
86 | createPoint(x, y) { | ||
87 | const publicKey = '04' + x + y | ||
88 | const point = _.getGlobalCurve().decodePointHex(publicKey) | ||
89 | return point | ||
90 | } | ||
91 | } | ||
92 | |||
93 | module.exports = SM2Cipher |
src/sm2/sm3.js
0 → 100644
1 | /* eslint-disable no-bitwise, no-mixed-operators, class-methods-use-this, camelcase */ | ||
2 | const {BigInteger} = require('jsbn') | ||
3 | const _ = require('./utils') | ||
4 | |||
5 | const copyArray = function (sourceArray, sourceIndex, destinationArray, destinationIndex, length) { | ||
6 | for (let i = 0; i < length; i++) { | ||
7 | destinationArray[destinationIndex + i] = sourceArray[sourceIndex + i] | ||
8 | } | ||
9 | } | ||
10 | |||
11 | const Int32 = { | ||
12 | minValue: -0b10000000000000000000000000000000, | ||
13 | maxValue: 0b1111111111111111111111111111111, | ||
14 | parse(n) { | ||
15 | if (n < this.minValue) { | ||
16 | const bigInteger = Number(-n) | ||
17 | const bigIntegerRadix = bigInteger.toString(2) | ||
18 | const subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 31, 31) | ||
19 | let reBigIntegerRadix = '' | ||
20 | for (let i = 0; i < subBigIntegerRadix.length; i++) { | ||
21 | const subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1) | ||
22 | reBigIntegerRadix += subBigIntegerRadixItem === '0' ? '1' : '0' | ||
23 | } | ||
24 | const result = parseInt(reBigIntegerRadix, 2) | ||
25 | return (result + 1) | ||
26 | } else if (n > this.maxValue) { | ||
27 | const bigInteger = Number(n) | ||
28 | const bigIntegerRadix = bigInteger.toString(2) | ||
29 | const subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 31, 31) | ||
30 | let reBigIntegerRadix = '' | ||
31 | for (let i = 0; i < subBigIntegerRadix.length; i++) { | ||
32 | const subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1) | ||
33 | reBigIntegerRadix += subBigIntegerRadixItem === '0' ? '1' : '0' | ||
34 | } | ||
35 | const result = parseInt(reBigIntegerRadix, 2) | ||
36 | return -(result + 1) | ||
37 | } else { | ||
38 | return n | ||
39 | } | ||
40 | }, | ||
41 | parseByte(n) { | ||
42 | if (n < 0) { | ||
43 | const bigInteger = Number(-n) | ||
44 | const bigIntegerRadix = bigInteger.toString(2) | ||
45 | const subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 8, 8) | ||
46 | let reBigIntegerRadix = '' | ||
47 | for (let i = 0; i < subBigIntegerRadix.length; i++) { | ||
48 | const subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1) | ||
49 | reBigIntegerRadix += subBigIntegerRadixItem === '0' ? '1' : '0' | ||
50 | } | ||
51 | const result = parseInt(reBigIntegerRadix, 2) | ||
52 | return (result + 1) % 256 | ||
53 | } else if (n > 255) { | ||
54 | const bigInteger = Number(n) | ||
55 | const bigIntegerRadix = bigInteger.toString(2) | ||
56 | return parseInt(bigIntegerRadix.substr(bigIntegerRadix.length - 8, 8), 2) | ||
57 | } else { | ||
58 | return n | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | |||
63 | class SM3Digest { | ||
64 | constructor(...args) { | ||
65 | this.xBuf = [] | ||
66 | this.xBufOff = 0 | ||
67 | this.byteCount = 0 | ||
68 | this.DIGEST_LENGTH = 32 | ||
69 | this.v0 = [0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, | ||
70 | 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e] | ||
71 | this.v0 = [0x7380166f, 0x4914b2b9, 0x172442d7, -628488704, | ||
72 | -1452330820, 0x163138aa, -477237683, -1325724082] | ||
73 | this.v = new Array(8) | ||
74 | this.v_ = new Array(8) | ||
75 | this.X0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | ||
76 | this.X = new Array(68) | ||
77 | this.xOff = 0 | ||
78 | this.T_00_15 = 0x79cc4519 | ||
79 | this.T_16_63 = 0x7a879d8a | ||
80 | if (args.length > 0) { | ||
81 | this.initDigest(args[0]) | ||
82 | } else { | ||
83 | this.init() | ||
84 | } | ||
85 | } | ||
86 | |||
87 | init() { | ||
88 | this.xBuf = new Array(4) | ||
89 | this.reset() | ||
90 | } | ||
91 | |||
92 | initDigest(t) { | ||
93 | this.xBuf = [].concat(t.xBuf) | ||
94 | this.xBufOff = t.xBufOff | ||
95 | this.byteCount = t.byteCount | ||
96 | copyArray(t.X, 0, this.X, 0, t.X.length) | ||
97 | this.xOff = t.xOff | ||
98 | copyArray(t.v, 0, this.v, 0, t.v.length) | ||
99 | } | ||
100 | |||
101 | getDigestSize() { | ||
102 | return this.DIGEST_LENGTH | ||
103 | } | ||
104 | |||
105 | reset() { | ||
106 | this.byteCount = 0 | ||
107 | this.xBufOff = 0 | ||
108 | |||
109 | const keys = Object.keys(this.xBuf) | ||
110 | for (let i = 0, len = keys.length; i < len; i++) this.xBuf[keys[i]] = null | ||
111 | |||
112 | copyArray(this.v0, 0, this.v, 0, this.v0.length) | ||
113 | this.xOff = 0 | ||
114 | copyArray(this.X0, 0, this.X, 0, this.X0.length) | ||
115 | } | ||
116 | |||
117 | processBlock() { | ||
118 | let i | ||
119 | const ww = this.X | ||
120 | const ww_ = new Array(64) | ||
121 | for (i = 16; i < 68; i++) { | ||
122 | ww[i] = this.p1(ww[i - 16] ^ ww[i - 9] ^ (this.rotate(ww[i - 3], 15))) ^ (this.rotate(ww[i - 13], 7)) ^ ww[i - 6] | ||
123 | } | ||
124 | for (i = 0; i < 64; i++) { | ||
125 | ww_[i] = ww[i] ^ ww[i + 4] | ||
126 | } | ||
127 | const vv = this.v | ||
128 | const vv_ = this.v_ | ||
129 | copyArray(vv, 0, vv_, 0, this.v0.length) | ||
130 | let SS1 | ||
131 | let SS2 | ||
132 | let TT1 | ||
133 | let TT2 | ||
134 | let aaa | ||
135 | for (i = 0; i < 16; i++) { | ||
136 | aaa = this.rotate(vv_[0], 12) | ||
137 | SS1 = Int32.parse(Int32.parse(aaa + vv_[4]) + this.rotate(this.T_00_15, i)) | ||
138 | SS1 = this.rotate(SS1, 7) | ||
139 | SS2 = SS1 ^ aaa | ||
140 | TT1 = Int32.parse(Int32.parse(this.ff_00_15(vv_[0], vv_[1], vv_[2]) + vv_[3]) + SS2) + ww_[i] | ||
141 | TT2 = Int32.parse(Int32.parse(this.gg_00_15(vv_[4], vv_[5], vv_[6]) + vv_[7]) + SS1) + ww[i] | ||
142 | vv_[3] = vv_[2] | ||
143 | vv_[2] = this.rotate(vv_[1], 9) | ||
144 | vv_[1] = vv_[0] | ||
145 | vv_[0] = TT1 | ||
146 | vv_[7] = vv_[6] | ||
147 | vv_[6] = this.rotate(vv_[5], 19) | ||
148 | vv_[5] = vv_[4] | ||
149 | vv_[4] = this.p0(TT2) | ||
150 | } | ||
151 | for (i = 16; i < 64; i++) { | ||
152 | aaa = this.rotate(vv_[0], 12) | ||
153 | SS1 = Int32.parse(Int32.parse(aaa + vv_[4]) + this.rotate(this.T_16_63, i)) | ||
154 | SS1 = this.rotate(SS1, 7) | ||
155 | SS2 = SS1 ^ aaa | ||
156 | TT1 = Int32.parse(Int32.parse(this.ff_16_63(vv_[0], vv_[1], vv_[2]) + vv_[3]) + SS2) + ww_[i] | ||
157 | TT2 = Int32.parse(Int32.parse(this.gg_16_63(vv_[4], vv_[5], vv_[6]) + vv_[7]) + SS1) + ww[i] | ||
158 | vv_[3] = vv_[2] | ||
159 | vv_[2] = this.rotate(vv_[1], 9) | ||
160 | vv_[1] = vv_[0] | ||
161 | vv_[0] = TT1 | ||
162 | vv_[7] = vv_[6] | ||
163 | vv_[6] = this.rotate(vv_[5], 19) | ||
164 | vv_[5] = vv_[4] | ||
165 | vv_[4] = this.p0(TT2) | ||
166 | } | ||
167 | for (i = 0; i < 8; i++) { | ||
168 | vv[i] ^= Int32.parse(vv_[i]) | ||
169 | } | ||
170 | this.xOff = 0 | ||
171 | copyArray(this.X0, 0, this.X, 0, this.X0.length) | ||
172 | } | ||
173 | |||
174 | processWord(in_Renamed, inOff) { | ||
175 | let n = in_Renamed[inOff] << 24 | ||
176 | n |= (in_Renamed[++inOff] & 0xff) << 16 | ||
177 | n |= (in_Renamed[++inOff] & 0xff) << 8 | ||
178 | n |= (in_Renamed[++inOff] & 0xff) | ||
179 | this.X[this.xOff] = n | ||
180 | if (++this.xOff === 16) { | ||
181 | this.processBlock() | ||
182 | } | ||
183 | } | ||
184 | |||
185 | processLength(bitLength) { | ||
186 | if (this.xOff > 14) { | ||
187 | this.processBlock() | ||
188 | } | ||
189 | this.X[14] = (this.urShiftLong(bitLength, 32)) | ||
190 | this.X[15] = (bitLength & (0xffffffff)) | ||
191 | } | ||
192 | |||
193 | intToBigEndian(n, bs, off) { | ||
194 | bs[off] = Int32.parseByte(this.urShift(n, 24)) & 0xff | ||
195 | bs[++off] = Int32.parseByte(this.urShift(n, 16)) & 0xff | ||
196 | bs[++off] = Int32.parseByte(this.urShift(n, 8)) & 0xff | ||
197 | bs[++off] = Int32.parseByte(n) & 0xff | ||
198 | } | ||
199 | |||
200 | doFinal(out_Renamed, outOff) { | ||
201 | this.finish() | ||
202 | for (let i = 0; i < 8; i++) { | ||
203 | this.intToBigEndian(this.v[i], out_Renamed, outOff + i * 4) | ||
204 | } | ||
205 | this.reset() | ||
206 | return this.DIGEST_LENGTH | ||
207 | } | ||
208 | |||
209 | update(input) { | ||
210 | this.xBuf[this.xBufOff++] = input | ||
211 | if (this.xBufOff === this.xBuf.length) { | ||
212 | this.processWord(this.xBuf, 0) | ||
213 | this.xBufOff = 0 | ||
214 | } | ||
215 | this.byteCount++ | ||
216 | } | ||
217 | |||
218 | blockUpdate(input, inOff, length) { | ||
219 | while ((this.xBufOff !== 0) && (length > 0)) { | ||
220 | this.update(input[inOff]) | ||
221 | inOff++ | ||
222 | length-- | ||
223 | } | ||
224 | while (length > this.xBuf.length) { | ||
225 | this.processWord(input, inOff) | ||
226 | inOff += this.xBuf.length | ||
227 | length -= this.xBuf.length | ||
228 | this.byteCount += this.xBuf.length | ||
229 | } | ||
230 | while (length > 0) { | ||
231 | this.update(input[inOff]) | ||
232 | inOff++ | ||
233 | length-- | ||
234 | } | ||
235 | } | ||
236 | |||
237 | finish() { | ||
238 | const bitLength = (this.byteCount << 3) | ||
239 | this.update((128)) | ||
240 | while (this.xBufOff !== 0) this.update((0)) | ||
241 | this.processLength(bitLength) | ||
242 | this.processBlock() | ||
243 | } | ||
244 | |||
245 | rotate(x, n) { | ||
246 | return (x << n) | (this.urShift(x, (32 - n))) | ||
247 | } | ||
248 | |||
249 | p0(X) { | ||
250 | return ((X) ^ this.rotate((X), 9) ^ this.rotate((X), 17)) | ||
251 | } | ||
252 | |||
253 | p1(X) { | ||
254 | return ((X) ^ this.rotate((X), 15) ^ this.rotate((X), 23)) | ||
255 | } | ||
256 | |||
257 | ff_00_15(X, Y, Z) { | ||
258 | return (X ^ Y ^ Z) | ||
259 | } | ||
260 | |||
261 | ff_16_63(X, Y, Z) { | ||
262 | return ((X & Y) | (X & Z) | (Y & Z)) | ||
263 | } | ||
264 | |||
265 | gg_00_15(X, Y, Z) { | ||
266 | return (X ^ Y ^ Z) | ||
267 | } | ||
268 | |||
269 | gg_16_63(X, Y, Z) { | ||
270 | return ((X & Y) | (~X & Z)) | ||
271 | } | ||
272 | |||
273 | urShift(number, bits) { | ||
274 | if (number > Int32.maxValue || number < Int32.minValue) { | ||
275 | number = Int32.parse(number) | ||
276 | } | ||
277 | return number >>> bits | ||
278 | } | ||
279 | |||
280 | urShiftLong(number, bits) { | ||
281 | let returnV | ||
282 | const big = new BigInteger() | ||
283 | big.fromInt(number) | ||
284 | if (big.signum() >= 0) { | ||
285 | returnV = big.shiftRight(bits).intValue() | ||
286 | } else { | ||
287 | const bigAdd = new BigInteger() | ||
288 | bigAdd.fromInt(2) | ||
289 | const shiftLeftBits = ~bits | ||
290 | let shiftLeftNumber = '' | ||
291 | if (shiftLeftBits < 0) { | ||
292 | const shiftRightBits = 64 + shiftLeftBits | ||
293 | for (let i = 0; i < shiftRightBits; i++) { | ||
294 | shiftLeftNumber += '0' | ||
295 | } | ||
296 | const shiftLeftNumberBigAdd = new BigInteger() | ||
297 | shiftLeftNumberBigAdd.fromInt(number >> bits) | ||
298 | const shiftLeftNumberBig = new BigInteger('10' + shiftLeftNumber, 2) | ||
299 | shiftLeftNumber = shiftLeftNumberBig.toRadix(10) | ||
300 | const r = shiftLeftNumberBig.add(shiftLeftNumberBigAdd) | ||
301 | returnV = r.toRadix(10) | ||
302 | } else { | ||
303 | shiftLeftNumber = bigAdd.shiftLeft((~bits)).intValue() | ||
304 | returnV = (number >> bits) + shiftLeftNumber | ||
305 | } | ||
306 | } | ||
307 | return returnV | ||
308 | } | ||
309 | |||
310 | getZ(g, publicKey) { | ||
311 | const userId = _.parseUtf8StringToHex('1234567812345678') | ||
312 | const len = userId.length * 4 | ||
313 | this.update((len >> 8 & 0x00ff)) | ||
314 | this.update((len & 0x00ff)) | ||
315 | const userIdWords = _.hexToArray(userId) | ||
316 | this.blockUpdate(userIdWords, 0, userIdWords.length) | ||
317 | const aWords = _.hexToArray(g.curve.a.toBigInteger().toRadix(16)) | ||
318 | const bWords = _.hexToArray(g.curve.b.toBigInteger().toRadix(16)) | ||
319 | const gxWords = _.hexToArray(g.getX().toBigInteger().toRadix(16)) | ||
320 | const gyWords = _.hexToArray(g.getY().toBigInteger().toRadix(16)) | ||
321 | const pxWords = _.hexToArray(publicKey.substr(0, 64)) | ||
322 | const pyWords = _.hexToArray(publicKey.substr(64, 64)) | ||
323 | this.blockUpdate(aWords, 0, aWords.length) | ||
324 | this.blockUpdate(bWords, 0, bWords.length) | ||
325 | this.blockUpdate(gxWords, 0, gxWords.length) | ||
326 | this.blockUpdate(gyWords, 0, gyWords.length) | ||
327 | this.blockUpdate(pxWords, 0, pxWords.length) | ||
328 | this.blockUpdate(pyWords, 0, pyWords.length) | ||
329 | const md = new Array(this.getDigestSize()) | ||
330 | this.doFinal(md, 0) | ||
331 | return md | ||
332 | } | ||
333 | } | ||
334 | |||
335 | module.exports = SM3Digest |
src/sm2/utils.js
0 → 100644
1 | /* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */ | ||
2 | const {BigInteger, SecureRandom} = require('jsbn') | ||
3 | const {ECCurveFp} = require('./ec') | ||
4 | const SM3 = require('../sm3') | ||
5 | |||
6 | const rng = new SecureRandom() | ||
7 | const {curve, G, n} = generateEcparam() | ||
8 | |||
9 | /** | ||
10 | * 获取公共椭圆曲线 | ||
11 | */ | ||
12 | function getGlobalCurve() { | ||
13 | return curve | ||
14 | } | ||
15 | |||
16 | /** | ||
17 | * 生成ecparam | ||
18 | */ | ||
19 | function generateEcparam() { | ||
20 | // 椭圆曲线 | ||
21 | const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16) | ||
22 | const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16) | ||
23 | const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16) | ||
24 | const curve = new ECCurveFp(p, a, b) | ||
25 | |||
26 | // 基点 | ||
27 | const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7' | ||
28 | const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0' | ||
29 | const G = curve.decodePointHex('04' + gxHex + gyHex) | ||
30 | |||
31 | const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16) | ||
32 | |||
33 | return {curve, G, n} | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * 生成密钥对 | ||
38 | */ | ||
39 | function generateKeyPairHex() { | ||
40 | const d = new BigInteger(n.bitLength(), rng).mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数 | ||
41 | const privateKey = leftPad(d.toString(16), 64) | ||
42 | |||
43 | const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥 | ||
44 | const Px = leftPad(P.getX().toBigInteger().toString(16), 64) | ||
45 | const Py = leftPad(P.getY().toBigInteger().toString(16), 64) | ||
46 | const publicKey = '04' + Px + Py | ||
47 | |||
48 | return {privateKey, publicKey} | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * 根据指定字符串,生成密钥对 | ||
53 | * @param {String} secret | ||
54 | */ | ||
55 | function generateKeyPairHexBySecret(secret) { | ||
56 | const hashValue = SM3(secret) | ||
57 | const d = new BigInteger(hashValue, 16) | ||
58 | const privateKey = leftPad(d.toString(16), 64) | ||
59 | const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥 | ||
60 | const Px = leftPad(P.getX().toBigInteger().toString(16), 64) | ||
61 | const Py = leftPad(P.getY().toBigInteger().toString(16), 64) | ||
62 | const publicKey = '04' + Px + Py | ||
63 | |||
64 | return {privateKey, publicKey} | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * 解析utf8字符串到16进制 | ||
69 | */ | ||
70 | function parseUtf8StringToHex(input) { | ||
71 | input = unescape(encodeURIComponent(input)) | ||
72 | |||
73 | const length = input.length | ||
74 | |||
75 | // 转换到字数组 | ||
76 | const words = [] | ||
77 | for (let i = 0; i < length; i++) { | ||
78 | words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8) | ||
79 | } | ||
80 | |||
81 | // 转换到16进制 | ||
82 | const hexChars = [] | ||
83 | for (let i = 0; i < length; i++) { | ||
84 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
85 | hexChars.push((bite >>> 4).toString(16)) | ||
86 | hexChars.push((bite & 0x0f).toString(16)) | ||
87 | } | ||
88 | |||
89 | return hexChars.join('') | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * 解析arrayBuffer到16进制字符串 | ||
94 | */ | ||
95 | function parseArrayBufferToHex(input) { | ||
96 | return Array.prototype.map.call(new Uint8Array(input), x => ('00' + x.toString(16)).slice(-2)).join('') | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * 补全16进制字符串 | ||
101 | */ | ||
102 | function leftPad(input, num) { | ||
103 | if (input.length >= num) return input | ||
104 | |||
105 | return (new Array(num - input.length + 1)).join('0') + input | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * 转成16进制串 | ||
110 | */ | ||
111 | function arrayToHex(arr) { | ||
112 | const words = [] | ||
113 | let j = 0 | ||
114 | for (let i = 0; i < arr.length * 2; i += 2) { | ||
115 | words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4) | ||
116 | j++ | ||
117 | } | ||
118 | |||
119 | // 转换到16进制 | ||
120 | const hexChars = [] | ||
121 | for (let i = 0; i < arr.length; i++) { | ||
122 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
123 | hexChars.push((bite >>> 4).toString(16)) | ||
124 | hexChars.push((bite & 0x0f).toString(16)) | ||
125 | } | ||
126 | |||
127 | return hexChars.join('') | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * 转成utf8串 | ||
132 | */ | ||
133 | function arrayToUtf8(arr) { | ||
134 | const words = [] | ||
135 | let j = 0 | ||
136 | for (let i = 0; i < arr.length * 2; i += 2) { | ||
137 | words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4) | ||
138 | j++ | ||
139 | } | ||
140 | |||
141 | try { | ||
142 | const latin1Chars = [] | ||
143 | |||
144 | for (let i = 0; i < arr.length; i++) { | ||
145 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff | ||
146 | latin1Chars.push(String.fromCharCode(bite)) | ||
147 | } | ||
148 | |||
149 | return decodeURIComponent(escape(latin1Chars.join(''))) | ||
150 | } catch (e) { | ||
151 | throw new Error('Malformed UTF-8 data') | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * 转成ascii码数组 | ||
157 | */ | ||
158 | function hexToArray(hexStr) { | ||
159 | const words = [] | ||
160 | let hexStrLength = hexStr.length | ||
161 | |||
162 | if (hexStrLength % 2 !== 0) { | ||
163 | hexStr = leftPad(hexStr, hexStrLength + 1) | ||
164 | } | ||
165 | |||
166 | hexStrLength = hexStr.length | ||
167 | |||
168 | for (let i = 0; i < hexStrLength; i += 2) { | ||
169 | words.push(parseInt(hexStr.substr(i, 2), 16)) | ||
170 | } | ||
171 | return words | ||
172 | } | ||
173 | |||
174 | module.exports = { | ||
175 | getGlobalCurve, | ||
176 | generateEcparam, | ||
177 | generateKeyPairHex, | ||
178 | generateKeyPairHexBySecret, | ||
179 | parseUtf8StringToHex, | ||
180 | parseArrayBufferToHex, | ||
181 | leftPad, | ||
182 | arrayToHex, | ||
183 | arrayToUtf8, | ||
184 | hexToArray, | ||
185 | } |
src/sm3/index.js
0 → 100644
1 | /** | ||
2 | * 左补0到指定长度 | ||
3 | */ | ||
4 | function leftPad(input, num) { | ||
5 | if (input.length >= num) return input | ||
6 | |||
7 | return (new Array(num - input.length + 1)).join('0') + input | ||
8 | } | ||
9 | |||
10 | /** | ||
11 | * 二进制转化为十六进制 | ||
12 | */ | ||
13 | function binary2hex(binary) { | ||
14 | const binaryLength = 8 | ||
15 | let hex = '' | ||
16 | for (let i = 0; i < binary.length / binaryLength; i++) { | ||
17 | hex += leftPad(parseInt(binary.substr(i * binaryLength, binaryLength), 2).toString(16), 2) | ||
18 | } | ||
19 | return hex | ||
20 | } | ||
21 | |||
22 | /** | ||
23 | * 十六进制转化为二进制 | ||
24 | */ | ||
25 | function hex2binary(hex) { | ||
26 | const hexLength = 2 | ||
27 | let binary = '' | ||
28 | for (let i = 0; i < hex.length / hexLength; i++) { | ||
29 | binary += leftPad(parseInt(hex.substr(i * hexLength, hexLength), 16).toString(2), 8) | ||
30 | } | ||
31 | return binary | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * 普通字符串转化为二进制 | ||
36 | */ | ||
37 | function str2binary(str) { | ||
38 | let binary = '' | ||
39 | for (let i = 0, len = str.length; i < len; i++) { | ||
40 | const ch = str[i] | ||
41 | binary += leftPad(ch.codePointAt(0).toString(2), 8) | ||
42 | } | ||
43 | return binary | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * 循环左移 | ||
48 | */ | ||
49 | function rol(str, n) { | ||
50 | return str.substring(n % str.length) + str.substr(0, n % str.length) | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * 二进制运算 | ||
55 | */ | ||
56 | function binaryCal(x, y, method) { | ||
57 | const a = x || '' | ||
58 | const b = y || '' | ||
59 | const result = [] | ||
60 | let prevResult | ||
61 | |||
62 | for (let i = a.length - 1; i >= 0; i--) { // 大端 | ||
63 | prevResult = method(a[i], b[i], prevResult) | ||
64 | result[i] = prevResult[0] | ||
65 | } | ||
66 | return result.join('') | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * 二进制异或运算 | ||
71 | */ | ||
72 | function xor(x, y) { | ||
73 | return binaryCal(x, y, (a, b) => [(a === b ? '0' : '1')]) | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * 二进制与运算 | ||
78 | */ | ||
79 | function and(x, y) { | ||
80 | return binaryCal(x, y, (a, b) => [(a === '1' && b === '1' ? '1' : '0')]) | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * 二进制或运算 | ||
85 | */ | ||
86 | function or(x, y) { | ||
87 | return binaryCal(x, y, (a, b) => [(a === '1' || b === '1' ? '1' : '0')]) // a === '0' && b === '0' ? '0' : '1' | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * 二进制与运算 | ||
92 | */ | ||
93 | function add(x, y) { | ||
94 | const result = binaryCal(x, y, (a, b, prevResult) => { | ||
95 | const carry = prevResult ? prevResult[1] : '0' || '0' | ||
96 | |||
97 | // a,b不等时,carry不变,结果与carry相反 | ||
98 | // a,b相等时,结果等于原carry,新carry等于a | ||
99 | if (a !== b) return [carry === '0' ? '1' : '0', carry] | ||
100 | |||
101 | return [carry, a] | ||
102 | }) | ||
103 | |||
104 | return result | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * 二进制非运算 | ||
109 | */ | ||
110 | function not(x) { | ||
111 | return binaryCal(x, undefined, a => [a === '1' ? '0' : '1']) | ||
112 | } | ||
113 | |||
114 | function calMulti(method) { | ||
115 | return (...arr) => arr.reduce((prev, curr) => method(prev, curr)) | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * 压缩函数中的置换函数 P1(X) = X xor (X <<< 9) xor (X <<< 17) | ||
120 | */ | ||
121 | function P0(X) { | ||
122 | return calMulti(xor)(X, rol(X, 9), rol(X, 17)) | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23) | ||
127 | */ | ||
128 | function P1(X) { | ||
129 | return calMulti(xor)(X, rol(X, 15), rol(X, 23)) | ||
130 | } | ||
131 | |||
132 | function FF(X, Y, Z, j) { | ||
133 | return j >= 0 && j <= 15 ? calMulti(xor)(X, Y, Z) : calMulti(or)(and(X, Y), and(X, Z), and(Y, Z)) | ||
134 | } | ||
135 | |||
136 | function GG(X, Y, Z, j) { | ||
137 | return j >= 0 && j <= 15 ? calMulti(xor)(X, Y, Z) : or(and(X, Y), and(not(X), Z)) | ||
138 | } | ||
139 | |||
140 | function T(j) { | ||
141 | return j >= 0 && j <= 15 ? hex2binary('79cc4519') : hex2binary('7a879d8a') | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * 压缩函数 | ||
146 | */ | ||
147 | function CF(V, Bi) { | ||
148 | // 消息扩展 | ||
149 | const wordLength = 32 | ||
150 | const W = [] | ||
151 | const M = [] // W' | ||
152 | |||
153 | // 将消息分组B划分为16个字W0, W1,…… ,W15 (字为长度为32的比特串) | ||
154 | for (let i = 0; i < 16; i++) { | ||
155 | W.push(Bi.substr(i * wordLength, wordLength)) | ||
156 | } | ||
157 | |||
158 | // W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6] | ||
159 | for (let j = 16; j < 68; j++) { | ||
160 | W.push(calMulti(xor)( | ||
161 | P1(calMulti(xor)(W[j - 16], W[j - 9], rol(W[j - 3], 15))), | ||
162 | rol(W[j - 13], 7), | ||
163 | W[j - 6] | ||
164 | )) | ||
165 | } | ||
166 | |||
167 | // W′[j] = W[j] xor W[j+4] | ||
168 | for (let j = 0; j < 64; j++) { | ||
169 | M.push(xor(W[j], W[j + 4])) | ||
170 | } | ||
171 | |||
172 | // 压缩 | ||
173 | const wordRegister = [] // 字寄存器 | ||
174 | for (let j = 0; j < 8; j++) { | ||
175 | wordRegister.push(V.substr(j * wordLength, wordLength)) | ||
176 | } | ||
177 | |||
178 | let A = wordRegister[0] | ||
179 | let B = wordRegister[1] | ||
180 | let C = wordRegister[2] | ||
181 | let D = wordRegister[3] | ||
182 | let E = wordRegister[4] | ||
183 | let F = wordRegister[5] | ||
184 | let G = wordRegister[6] | ||
185 | let H = wordRegister[7] | ||
186 | |||
187 | // 中间变量 | ||
188 | let SS1 | ||
189 | let SS2 | ||
190 | let TT1 | ||
191 | let TT2 | ||
192 | for (let j = 0; j < 64; j++) { | ||
193 | SS1 = rol(calMulti(add)(rol(A, 12), E, rol(T(j), j)), 7) | ||
194 | SS2 = xor(SS1, rol(A, 12)) | ||
195 | |||
196 | TT1 = calMulti(add)(FF(A, B, C, j), D, SS2, M[j]) | ||
197 | TT2 = calMulti(add)(GG(E, F, G, j), H, SS1, W[j]) | ||
198 | |||
199 | D = C | ||
200 | C = rol(B, 9) | ||
201 | B = A | ||
202 | A = TT1 | ||
203 | H = G | ||
204 | G = rol(F, 19) | ||
205 | F = E | ||
206 | E = P0(TT2) | ||
207 | } | ||
208 | |||
209 | return xor([A, B, C, D, E, F, G, H].join(''), V) | ||
210 | } | ||
211 | |||
212 | module.exports = function (str) { | ||
213 | const binary = str2binary(str) | ||
214 | |||
215 | // 填充 | ||
216 | const len = binary.length | ||
217 | |||
218 | // k是满足len + 1 + k = 448mod512的最小的非负整数 | ||
219 | let k = len % 512 | ||
220 | |||
221 | // 如果 448 <= (512 % len) < 512,需要多补充 (len % 448) 比特'0'以满足总比特长度为512的倍数 | ||
222 | k = k >= 448 ? 512 - (k % 448) - 1 : 448 - k - 1 | ||
223 | |||
224 | const m = `${binary}1${leftPad('', k)}${leftPad(len.toString(2), 64)}`.toString() // k个0 | ||
225 | |||
226 | // 迭代压缩 | ||
227 | const n = (len + k + 65) / 512 | ||
228 | |||
229 | let V = hex2binary('7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e') | ||
230 | for (let i = 0; i <= n - 1; i++) { | ||
231 | const B = m.substr(512 * i, 512) | ||
232 | V = CF(V, B) | ||
233 | } | ||
234 | return binary2hex(V) | ||
235 | } |
src/sm4/index.js
0 → 100644
1 | /* eslint-disable no-bitwise, no-mixed-operators */ | ||
2 | const DECRYPT = 0 | ||
3 | const ROUND = 32 | ||
4 | const BLOCK = 16 | ||
5 | |||
6 | const Sbox = [ | ||
7 | 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, | ||
8 | 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, | ||
9 | 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, | ||
10 | 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, | ||
11 | 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, | ||
12 | 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, | ||
13 | 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, | ||
14 | 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, | ||
15 | 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, | ||
16 | 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, | ||
17 | 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, | ||
18 | 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, | ||
19 | 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, | ||
20 | 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, | ||
21 | 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, | ||
22 | 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48 | ||
23 | ] | ||
24 | |||
25 | const CK = [ | ||
26 | 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, | ||
27 | 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, | ||
28 | 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, | ||
29 | 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, | ||
30 | 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, | ||
31 | 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, | ||
32 | 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, | ||
33 | 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 | ||
34 | ] | ||
35 | |||
36 | function rotl(x, y) { | ||
37 | return x << y | x >>> (32 - y) | ||
38 | } | ||
39 | |||
40 | function byteSub(a) { | ||
41 | return (Sbox[a >>> 24 & 0xFF] & 0xFF) << 24 | | ||
42 | (Sbox[a >>> 16 & 0xFF] & 0xFF) << 16 | | ||
43 | (Sbox[a >>> 8 & 0xFF] & 0xFF) << 8 | | ||
44 | (Sbox[a & 0xFF] & 0xFF) | ||
45 | } | ||
46 | |||
47 | function l1(b) { | ||
48 | return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24) | ||
49 | } | ||
50 | |||
51 | function l2(b) { | ||
52 | return b ^ rotl(b, 13) ^ rotl(b, 23) | ||
53 | } | ||
54 | |||
55 | function sms4Crypt(input, output, roundKey) { | ||
56 | let r | ||
57 | let mid | ||
58 | const x = new Array(4) | ||
59 | const tmp = new Array(4) | ||
60 | for (let i = 0; i < 4; i++) { | ||
61 | tmp[0] = input[0 + 4 * i] & 0xff | ||
62 | tmp[1] = input[1 + 4 * i] & 0xff | ||
63 | tmp[2] = input[2 + 4 * i] & 0xff | ||
64 | tmp[3] = input[3 + 4 * i] & 0xff | ||
65 | x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3] | ||
66 | } | ||
67 | |||
68 | for (r = 0; r < 32; r += 4) { | ||
69 | mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0] | ||
70 | mid = byteSub(mid) | ||
71 | x[0] ^= l1(mid) // x4 | ||
72 | |||
73 | mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1] | ||
74 | mid = byteSub(mid) | ||
75 | x[1] ^= l1(mid) // x5 | ||
76 | |||
77 | mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2] | ||
78 | mid = byteSub(mid) | ||
79 | x[2] ^= l1(mid) // x6 | ||
80 | |||
81 | mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3] | ||
82 | mid = byteSub(mid) | ||
83 | x[3] ^= l1(mid) // x7 | ||
84 | } | ||
85 | |||
86 | // Reverse | ||
87 | for (let j = 0; j < 16; j += 4) { | ||
88 | output[j] = x[3 - j / 4] >>> 24 & 0xff | ||
89 | output[j + 1] = x[3 - j / 4] >>> 16 & 0xff | ||
90 | output[j + 2] = x[3 - j / 4] >>> 8 & 0xff | ||
91 | output[j + 3] = x[3 - j / 4] & 0xff | ||
92 | } | ||
93 | } | ||
94 | |||
95 | function sms4KeyExt(key, roundKey, cryptFlag) { | ||
96 | let r | ||
97 | let mid | ||
98 | const x = new Array(4) | ||
99 | const tmp = new Array(4) | ||
100 | |||
101 | for (let i = 0; i < 4; i++) { | ||
102 | tmp[0] = key[0 + 4 * i] & 0xff | ||
103 | tmp[1] = key[1 + 4 * i] & 0xff | ||
104 | tmp[2] = key[2 + 4 * i] & 0xff | ||
105 | tmp[3] = key[3 + 4 * i] & 0xff | ||
106 | x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3] | ||
107 | } | ||
108 | |||
109 | x[0] ^= 0xa3b1bac6 | ||
110 | x[1] ^= 0x56aa3350 | ||
111 | x[2] ^= 0x677d9197 | ||
112 | x[3] ^= 0xb27022dc | ||
113 | |||
114 | for (r = 0; r < 32; r += 4) { | ||
115 | mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0] | ||
116 | mid = byteSub(mid) | ||
117 | roundKey[r + 0] = x[0] ^= l2(mid) // roundKey0 = K4 | ||
118 | |||
119 | mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1] | ||
120 | mid = byteSub(mid) | ||
121 | roundKey[r + 1] = x[1] ^= l2(mid) // roundKey1 = K5 | ||
122 | |||
123 | mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2] | ||
124 | mid = byteSub(mid) | ||
125 | roundKey[r + 2] = x[2] ^= l2(mid) // roundKey2 = K6 | ||
126 | |||
127 | mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3] | ||
128 | mid = byteSub(mid) | ||
129 | roundKey[r + 3] = x[3] ^= l2(mid) // roundKey3 = K7 | ||
130 | } | ||
131 | |||
132 | // 解密时轮密钥使用顺序:roundKey31, roundKey30, ..., roundKey0 | ||
133 | if (cryptFlag === DECRYPT) { | ||
134 | for (r = 0; r < 16; r++) { | ||
135 | mid = roundKey[r] | ||
136 | roundKey[r] = roundKey[31 - r] | ||
137 | roundKey[31 - r] = mid | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
142 | function sm4(inArray, key, cryptFlag) { | ||
143 | const outArray = [] | ||
144 | let point = 0 | ||
145 | const roundKey = new Array(ROUND) | ||
146 | sms4KeyExt(key, roundKey, cryptFlag) | ||
147 | |||
148 | let input = new Array(16) | ||
149 | const output = new Array(16) | ||
150 | |||
151 | let inLen = inArray.length | ||
152 | while (inLen >= BLOCK) { | ||
153 | input = inArray.slice(point, point + 16) | ||
154 | sms4Crypt(input, output, roundKey) | ||
155 | |||
156 | for (let i = 0; i < BLOCK; i++) { | ||
157 | outArray[point + i] = output[i] | ||
158 | } | ||
159 | |||
160 | inLen -= BLOCK | ||
161 | point += BLOCK | ||
162 | } | ||
163 | |||
164 | return outArray | ||
165 | } | ||
166 | |||
167 | module.exports = { | ||
168 | encrypt(inArray, key) { | ||
169 | return sm4(inArray, key, 1) | ||
170 | }, | ||
171 | decrypt(inArray, key) { | ||
172 | return sm4(inArray, key, 0) | ||
173 | } | ||
174 | } |
test/sm2.test.js
0 → 100644
1 | const sm2 = require('../src/index').sm2 | ||
2 | |||
3 | const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3 | ||
4 | |||
5 | // const msgString = 'abcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCDabcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCDabcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCDabcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCDabcdefghABCDEFGH'; | ||
6 | const msgString = 'absasdagfadgadsfdfdsf' | ||
7 | |||
8 | let publicKey | ||
9 | let privateKey | ||
10 | |||
11 | beforeAll(() => { | ||
12 | // 生成密钥对 | ||
13 | let keypair = sm2.generateKeyPairHex() | ||
14 | |||
15 | publicKey = keypair.publicKey | ||
16 | privateKey = keypair.privateKey | ||
17 | }); | ||
18 | |||
19 | test('sm2: generate keypair', () => { | ||
20 | expect(publicKey.length).toBe(130) | ||
21 | expect(privateKey.length).toBe(64) | ||
22 | }); | ||
23 | |||
24 | test('sm2: encrypt and decrypt data', () => { | ||
25 | let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode) | ||
26 | let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) | ||
27 | expect(decryptData).toBe(msgString) | ||
28 | |||
29 | for (let i = 0; i < 100; i++) { | ||
30 | let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode) | ||
31 | let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) | ||
32 | |||
33 | expect(decryptData).toBe(msgString) | ||
34 | } | ||
35 | }) | ||
36 | |||
37 | test('sm2: sign data and verify sign', () => { | ||
38 | // 纯签名 + 生成椭圆曲线点 | ||
39 | let sigValueHex = sm2.doSignature(msgString, privateKey) | ||
40 | let verifyResult = sm2.doVerifySignature(msgString, sigValueHex, publicKey) | ||
41 | expect(verifyResult).toBe(true) | ||
42 | |||
43 | // 纯签名 | ||
44 | let sigValueHex2 = sm2.doSignature(msgString, privateKey, { | ||
45 | pointPool: [sm2.getPoint(), sm2.getPoint(), sm2.getPoint(), sm2.getPoint()], | ||
46 | }) | ||
47 | let verifyResult2 = sm2.doVerifySignature(msgString, sigValueHex2, publicKey); | ||
48 | expect(verifyResult2).toBe(true) | ||
49 | |||
50 | // 纯签名 + 生成椭圆曲线点 + der编解码 | ||
51 | let sigValueHex3 = sm2.doSignature(msgString, privateKey, { | ||
52 | der: true, | ||
53 | }) | ||
54 | let verifyResult3 = sm2.doVerifySignature(msgString, sigValueHex3, publicKey, { | ||
55 | der: true, | ||
56 | }) | ||
57 | expect(verifyResult3).toBe(true) | ||
58 | |||
59 | // 纯签名 + 生成椭圆曲线点 + sm3杂凑 | ||
60 | let sigValueHex4 = sm2.doSignature(msgString, privateKey, { | ||
61 | hash: true, | ||
62 | }) | ||
63 | let verifyResult4 = sm2.doVerifySignature(msgString, sigValueHex4, publicKey, { | ||
64 | hash: true, | ||
65 | }) | ||
66 | expect(verifyResult4).toBe(true) | ||
67 | |||
68 | for (let i = 0; i < 100; i++) { | ||
69 | sigValueHex4 = sm2.doSignature(msgString, privateKey, { | ||
70 | hash: true, | ||
71 | }) | ||
72 | verifyResult4 = sm2.doVerifySignature(msgString, sigValueHex4, publicKey, { | ||
73 | hash: true, | ||
74 | }) | ||
75 | expect(verifyResult4).toBe(true) | ||
76 | } | ||
77 | |||
78 | // 纯签名 + 生成椭圆曲线点 + sm3杂凑(不做公钥推导) | ||
79 | let sigValueHex5 = sm2.doSignature(msgString, privateKey, { | ||
80 | hash: true, | ||
81 | publicKey, | ||
82 | }) | ||
83 | let verifyResult5 = sm2.doVerifySignature(msgString, sigValueHex5, publicKey, { | ||
84 | hash: true, | ||
85 | publicKey, | ||
86 | }) | ||
87 | expect(verifyResult5).toBe(true) | ||
88 | }) |
test/sm3.test.js
0 → 100644
1 | const sm3 = require('../src/index').sm3 | ||
2 | |||
3 | test('sm3: must match the result', () => { | ||
4 | expect(sm3('abc')).toBe('66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0') | ||
5 | |||
6 | expect(sm3('abcdefghABCDEFGH12345678')).toBe('d670c7f027fd5f9f0c163f4bfe98f9003fe597d3f52dbab0885ec2ca8dd23e9b') | ||
7 | |||
8 | expect(sm3('abcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefgh')).toBe('1cf3bafec325d7d9102cd67ba46b09195af4e613b6c2b898122363d810308b11') | ||
9 | |||
10 | expect(sm3('abcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCD')).toBe('b8ac4203969bde27434ce667b0adbf3439ee97e416e73cb96f4431f478a531fe') | ||
11 | |||
12 | expect(sm3('abcdefghABCDEFGH12345678abcdefghABCDEFGH12345678abcdefghABCDEFGH')).toBe('5ef0cdbe0d54426eea7f5c8b44385bb1003548735feaa59137c3dfe608aa9567') | ||
13 | |||
14 | expect(sm3('abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd')).toBe('debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732') | ||
15 | }) |
test/sm4.test.js
0 → 100644
1 | const sm4 = require('../src/index').sm4 | ||
2 | const key = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10] | ||
3 | |||
4 | test('sm4: encrypt a group', () => { | ||
5 | expect(sm4.encrypt([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10], key)).toEqual([0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46]) | ||
6 | }) | ||
7 | |||
8 | test('sm4: decrypt a group', () => { | ||
9 | expect(sm4.decrypt([0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46], key)).toEqual([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10]) | ||
10 | }) | ||
11 | |||
12 | test('sm4: encrypt several groups', () => { | ||
13 | expect(sm4.encrypt([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10], key)).toEqual([0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46]) | ||
14 | }) | ||
15 | |||
16 | test('sm4: decrypt several groups', () => { | ||
17 | expect(sm4.decrypt([0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46], key)).toEqual([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10]) | ||
18 | }) | ||
19 | |||
20 | test('sm4: encrypt a group whit 1000000 times', () => { | ||
21 | let temp = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10] | ||
22 | for (let i = 0; i < 1000000; i++) { | ||
23 | temp = sm4.encrypt(temp, key) | ||
24 | } | ||
25 | |||
26 | expect(temp).toEqual([0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66]) | ||
27 | }) |
tet.js
0 → 100644
1 | const SM = require('./src') | ||
2 | |||
3 | function getKeys(secret) { | ||
4 | // const hash = createHash(Buffer.from(secret)) | ||
5 | |||
6 | // const m = new Uint8Array(nacl.sign.seedLength) | ||
7 | // for (let i = 0; i < m.length; i++) m[i] = hash[i] | ||
8 | |||
9 | // const keypair = nacl.sign.keyPair.fromSeed(m) | ||
10 | /** | ||
11 | * { | ||
12 | publicKey: '0x10d15cb4a3747d9bcf6339ef7b1d8462e86da595e7da3f4dd17bb1b7e3b43cf9c67e41a439ec1ddae15e697b71bbfa2c4f662fce5105fc21c404df9ddae513f7', | ||
13 | privateKey: '5c3e9a13ff5618cca46bdf5780c4391e89af27eeea044c90ad9684f4fb51c453' | ||
14 | } | ||
15 | */ | ||
16 | const hash=SM.sm3(secret) | ||
17 | const keypair =SM.sm2.generateKeyPairHex(hash) | ||
18 | let sigValueHex = SM.sm2.doSignature(secret, keypair.privateKey) | ||
19 | let verifyResult = SM.sm2.doVerifySignature(secret, sigValueHex, keypair.publicKey) | ||
20 | console.log(verifyResult) | ||
21 | return { | ||
22 | publicKey: (keypair.publicKey), | ||
23 | privateKey: (keypair.privateKey) | ||
24 | } | ||
25 | |||
26 | } | ||
27 | function bufToHex(data) { | ||
28 | return Buffer.from(data).toString('hex') | ||
29 | } | ||
30 | console.log(getKeys("enter boring shaft rent essence foil trick vibrant fabric quote indoor output sdfdg deessa")) | ||
31 | |||
32 | console.log(Buffer.from('045e135d451a0dfbb3d01a3357ecae989aced67afe51ff28f6f6a16fc1a67488c47ee1eb00cb70b217f51ae9e1b96141115fca564a1694fe7390474f4c1bd59a51').length) | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
webpack.config.js
0 → 100644
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: 'window', | ||
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 | }; |
-
Please register or sign in to post a comment