Projekt

Obecné

Profil

Stáhnout (3.83 KB) Statistiky
| Větev: | Revize:
1 3a515b92 cagy
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
2
var createHmac = require('create-hmac')
3
var crt = require('browserify-rsa')
4
var EC = require('elliptic').ec
5
var BN = require('bn.js')
6
var parseKeys = require('parse-asn1')
7
var curves = require('./curves.json')
8
9
function sign (hash, key, hashType, signType, tag) {
10
  var priv = parseKeys(key)
11
  if (priv.curve) {
12
    // rsa keys can be interpreted as ecdsa ones in openssl
13
    if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type')
14
    return ecSign(hash, priv)
15
  } else if (priv.type === 'dsa') {
16
    if (signType !== 'dsa') throw new Error('wrong private key type')
17
    return dsaSign(hash, priv, hashType)
18
  } else {
19
    if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type')
20
  }
21
  hash = Buffer.concat([tag, hash])
22
  var len = priv.modulus.byteLength()
23
  var pad = [ 0, 1 ]
24
  while (hash.length + pad.length + 1 < len) pad.push(0xff)
25
  pad.push(0x00)
26
  var i = -1
27
  while (++i < hash.length) pad.push(hash[i])
28
29
  var out = crt(pad, priv)
30
  return out
31
}
32
33
function ecSign (hash, priv) {
34
  var curveId = curves[priv.curve.join('.')]
35
  if (!curveId) throw new Error('unknown curve ' + priv.curve.join('.'))
36
37
  var curve = new EC(curveId)
38
  var key = curve.keyFromPrivate(priv.privateKey)
39
  var out = key.sign(hash)
40
41
  return new Buffer(out.toDER())
42
}
43
44
function dsaSign (hash, priv, algo) {
45
  var x = priv.params.priv_key
46
  var p = priv.params.p
47
  var q = priv.params.q
48
  var g = priv.params.g
49
  var r = new BN(0)
50
  var k
51
  var H = bits2int(hash, q).mod(q)
52
  var s = false
53
  var kv = getKey(x, q, hash, algo)
54
  while (s === false) {
55
    k = makeKey(q, kv, algo)
56
    r = makeR(g, k, p, q)
57
    s = k.invm(q).imul(H.add(x.mul(r))).mod(q)
58
    if (s.cmpn(0) === 0) {
59
      s = false
60
      r = new BN(0)
61
    }
62
  }
63
  return toDER(r, s)
64
}
65
66
function toDER (r, s) {
67
  r = r.toArray()
68
  s = s.toArray()
69
70
  // Pad values
71
  if (r[0] & 0x80) r = [ 0 ].concat(r)
72
  if (s[0] & 0x80) s = [ 0 ].concat(s)
73
74
  var total = r.length + s.length + 4
75
  var res = [ 0x30, total, 0x02, r.length ]
76
  res = res.concat(r, [ 0x02, s.length ], s)
77
  return new Buffer(res)
78
}
79
80
function getKey (x, q, hash, algo) {
81
  x = new Buffer(x.toArray())
82
  if (x.length < q.byteLength()) {
83
    var zeros = new Buffer(q.byteLength() - x.length)
84
    zeros.fill(0)
85
    x = Buffer.concat([ zeros, x ])
86
  }
87
  var hlen = hash.length
88
  var hbits = bits2octets(hash, q)
89
  var v = new Buffer(hlen)
90
  v.fill(1)
91
  var k = new Buffer(hlen)
92
  k.fill(0)
93
  k = createHmac(algo, k).update(v).update(new Buffer([ 0 ])).update(x).update(hbits).digest()
94
  v = createHmac(algo, k).update(v).digest()
95
  k = createHmac(algo, k).update(v).update(new Buffer([ 1 ])).update(x).update(hbits).digest()
96
  v = createHmac(algo, k).update(v).digest()
97
  return { k: k, v: v }
98
}
99
100
function bits2int (obits, q) {
101
  var bits = new BN(obits)
102
  var shift = (obits.length << 3) - q.bitLength()
103
  if (shift > 0) bits.ishrn(shift)
104
  return bits
105
}
106
107
function bits2octets (bits, q) {
108
  bits = bits2int(bits, q)
109
  bits = bits.mod(q)
110
  var out = new Buffer(bits.toArray())
111
  if (out.length < q.byteLength()) {
112
    var zeros = new Buffer(q.byteLength() - out.length)
113
    zeros.fill(0)
114
    out = Buffer.concat([ zeros, out ])
115
  }
116
  return out
117
}
118
119
function makeKey (q, kv, algo) {
120
  var t
121
  var k
122
123
  do {
124
    t = new Buffer(0)
125
126
    while (t.length * 8 < q.bitLength()) {
127
      kv.v = createHmac(algo, kv.k).update(kv.v).digest()
128
      t = Buffer.concat([ t, kv.v ])
129
    }
130
131
    k = bits2int(t, q)
132
    kv.k = createHmac(algo, kv.k).update(kv.v).update(new Buffer([ 0 ])).digest()
133
    kv.v = createHmac(algo, kv.k).update(kv.v).digest()
134
  } while (k.cmp(q) !== -1)
135
136
  return k
137
}
138
139
function makeR (g, k, p, q) {
140
  return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q)
141
}
142
143
module.exports = sign
144
module.exports.getKey = getKey
145
module.exports.makeKey = makeKey