Commit a6d35a62 a6d35a62b5bd55f0f6501bbe737c6b6d3c68a14b by wulianyou

first commit

0 parents
1 {
2 "presets": ["es2015"]
3 }
...\ No newline at end of file ...\ No newline at end of file
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 }
1 .DS_Store
2 .idea
3
4 node_modules
5
6 npm-debug.log
7 package-lock.json
...\ No newline at end of file ...\ No newline at end of file
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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"))
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"))
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"))
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"))
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"))
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"))
1 .DS_Store
2 .idea
3
4 node_modules
5
6 npm-debug.log
7 package-lock.json
8
9 docs
10 test
...\ No newline at end of file ...\ No newline at end of file
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
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
This diff is collapsed. Click to expand it.
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
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
No preview for this file type
No preview for this file type
No preview for this file type
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 }
1 module.exports = {
2 sm2: require('./sm2/index'),
3 sm3: require('./sm3/index'),
4 sm4: require('./sm4/index'),
5 }
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 }
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 }
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 }
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
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
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 }
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 }
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 }
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 })
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 })
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 })
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
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 };