Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80540 views
1
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
2
var parseKeys = require('parse-asn1')
3
var BN = require('bn.js')
4
var elliptic = require('elliptic')
5
var crt = require('browserify-rsa')
6
var createHmac = require('create-hmac')
7
var curves = require('./curves')
8
9
module.exports = sign
10
function sign (hash, key, hashType, signType) {
11
var priv = parseKeys(key)
12
if (priv.curve) {
13
if (signType !== 'ecdsa') {
14
throw new Error('wrong private key type')
15
}
16
return ecSign(hash, priv)
17
} else if (priv.type === 'dsa') {
18
return dsaSign(hash, priv, hashType)
19
if (signType !== 'dsa') {
20
throw new Error('wrong private key type')
21
}
22
} else {
23
if (signType !== 'rsa') {
24
throw new Error('wrong private key type')
25
}
26
}
27
var len = priv.modulus.byteLength()
28
var pad = [ 0, 1 ]
29
while (hash.length + pad.length + 1 < len) {
30
pad.push(0xff)
31
}
32
pad.push(0x00)
33
var i = -1
34
while (++i < hash.length) {
35
pad.push(hash[i])
36
}
37
38
var out = crt(pad, priv)
39
return out
40
}
41
function ecSign (hash, priv) {
42
var curveId = curves[priv.curve.join('.')]
43
if (!curveId)
44
throw new Error('unknown curve ' + priv.curve.join('.'))
45
46
var curve = new elliptic.ec(curveId)
47
48
var key = curve.genKeyPair()
49
key._importPrivate(priv.privateKey)
50
var out = key.sign(hash)
51
return new Buffer(out.toDER())
52
}
53
function dsaSign (hash, priv, algo) {
54
var x = priv.params.priv_key
55
var p = priv.params.p
56
var q = priv.params.q
57
var montq = BN.mont(q)
58
var g = priv.params.g
59
var r = new BN(0)
60
var k
61
var H = bits2int(hash, q).mod(q)
62
var s = false
63
var kv = getKey(x, q, hash, algo)
64
while (s === false) {
65
k = makeKey(q, kv, algo)
66
r = makeR(g, k, p, q)
67
s = k.invm(q).imul(H.add(x.mul(r))).mod(q)
68
if (!s.cmpn(0)) {
69
s = false
70
r = new BN(0)
71
}
72
}
73
return toDER(r, s)
74
}
75
function toDER (r, s) {
76
r = r.toArray()
77
s = s.toArray()
78
79
// Pad values
80
if (r[0] & 0x80)
81
r = [ 0 ].concat(r)
82
// Pad values
83
if (s[0] & 0x80)
84
s = [0].concat(s)
85
86
var total = r.length + s.length + 4
87
var res = [ 0x30, total, 0x02, r.length ]
88
res = res.concat(r, [ 0x02, s.length ], s)
89
return new Buffer(res)
90
}
91
module.exports.getKey = getKey
92
function getKey (x, q, hash, algo) {
93
x = new Buffer(x.toArray())
94
if (x.length < q.byteLength()) {
95
var zeros = new Buffer(q.byteLength() - x.length)
96
zeros.fill(0)
97
x = Buffer.concat([zeros, x])
98
}
99
var hlen = hash.length
100
var hbits = bits2octets(hash, q)
101
var v = new Buffer(hlen)
102
v.fill(1)
103
var k = new Buffer(hlen)
104
k.fill(0)
105
k = createHmac(algo, k)
106
.update(v)
107
.update(new Buffer([0]))
108
.update(x)
109
.update(hbits)
110
.digest()
111
v = createHmac(algo, k)
112
.update(v)
113
.digest()
114
k = createHmac(algo, k)
115
.update(v)
116
.update(new Buffer([1]))
117
.update(x)
118
.update(hbits)
119
.digest()
120
v = createHmac(algo, k)
121
.update(v)
122
.digest()
123
return {
124
k: k,
125
v: v
126
}
127
}
128
function bits2int (obits, q) {
129
var bits = new BN(obits)
130
var shift = (obits.length << 3) - q.bitLength()
131
if (shift > 0) {
132
bits.ishrn(shift)
133
}
134
return bits
135
}
136
function bits2octets (bits, q) {
137
bits = bits2int(bits, q)
138
bits = bits.mod(q)
139
var out = new Buffer(bits.toArray())
140
if (out.length < q.byteLength()) {
141
var zeros = new Buffer(q.byteLength() - out.length)
142
zeros.fill(0)
143
out = Buffer.concat([zeros, out])
144
}
145
return out
146
}
147
module.exports.makeKey = makeKey
148
function makeKey (q, kv, algo) {
149
var t
150
var k
151
while (true) {
152
t = new Buffer('')
153
while (t.length * 8 < q.bitLength()) {
154
kv.v = createHmac(algo, kv.k)
155
.update(kv.v)
156
.digest()
157
t = Buffer.concat([t, kv.v])
158
}
159
k = bits2int(t, q)
160
kv.k = createHmac(algo, kv.k)
161
.update(kv.v)
162
.update(new Buffer([0]))
163
.digest()
164
kv.v = createHmac(algo, kv.k)
165
.update(kv.v)
166
.digest()
167
if (k.cmp(q) === -1) {
168
return k
169
}
170
}
171
}
172
function makeR (g, k, p, q) {
173
return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q)
174
}
175
176