utils.js
4.0 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
const {BigInteger, SecureRandom} = require('jsbn')
const {ECCurveFp} = require('./ec')
const rng = new SecureRandom()
const {curve, G, n} = generateEcparam()
/**
* 获取公共椭圆曲线
*/
function getGlobalCurve() {
return curve
}
/**
* 生成ecparam
*/
function generateEcparam() {
// 椭圆曲线
const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16)
const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16)
const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16)
const curve = new ECCurveFp(p, a, b)
// 基点
const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7'
const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0'
const G = curve.decodePointHex('04' + gxHex + gyHex)
const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16)
return {curve, G, n}
}
/**
* 生成密钥对
*/
function generateKeyPairHex() {
const d = new BigInteger(n.bitLength(), rng).mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数
const privateKey = leftPad(d.toString(16), 64)
const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥
const Px = leftPad(P.getX().toBigInteger().toString(16), 64)
const Py = leftPad(P.getY().toBigInteger().toString(16), 64)
const publicKey = '04' + Px + Py
return {privateKey, publicKey}
}
/**
* 解析utf8字符串到16进制
*/
function parseUtf8StringToHex(input) {
input = unescape(encodeURIComponent(input))
const length = input.length
// 转换到字数组
const words = []
for (let i = 0; i < length; i++) {
words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8)
}
// 转换到16进制
const hexChars = []
for (let i = 0; i < length; i++) {
const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
hexChars.push((bite >>> 4).toString(16))
hexChars.push((bite & 0x0f).toString(16))
}
return hexChars.join('')
}
/**
* 解析arrayBuffer到16进制字符串
*/
function parseArrayBufferToHex(input) {
return Array.prototype.map.call(new Uint8Array(input), x => ('00' + x.toString(16)).slice(-2)).join('')
}
/**
* 补全16进制字符串
*/
function leftPad(input, num) {
if (input.length >= num) return input
return (new Array(num - input.length + 1)).join('0') + input
}
/**
* 转成16进制串
*/
function arrayToHex(arr) {
const words = []
let j = 0
for (let i = 0; i < arr.length * 2; i += 2) {
words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4)
j++
}
// 转换到16进制
const hexChars = []
for (let i = 0; i < arr.length; i++) {
const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
hexChars.push((bite >>> 4).toString(16))
hexChars.push((bite & 0x0f).toString(16))
}
return hexChars.join('')
}
/**
* 转成utf8串
*/
function arrayToUtf8(arr) {
const words = []
let j = 0
for (let i = 0; i < arr.length * 2; i += 2) {
words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4)
j++
}
try {
const latin1Chars = []
for (let i = 0; i < arr.length; i++) {
const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
latin1Chars.push(String.fromCharCode(bite))
}
return decodeURIComponent(escape(latin1Chars.join('')))
} catch (e) {
throw new Error('Malformed UTF-8 data')
}
}
/**
* 转成ascii码数组
*/
function hexToArray(hexStr) {
const words = []
let hexStrLength = hexStr.length
if (hexStrLength % 2 !== 0) {
hexStr = leftPad(hexStr, hexStrLength + 1)
}
hexStrLength = hexStr.length
for (let i = 0; i < hexStrLength; i += 2) {
words.push(parseInt(hexStr.substr(i, 2), 16))
}
return words
}
module.exports = {
getGlobalCurve,
generateEcparam,
generateKeyPairHex,
parseUtf8StringToHex,
parseArrayBufferToHex,
leftPad,
arrayToHex,
arrayToUtf8,
hexToArray,
}