sign.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
  2. var Buffer = require('safe-buffer').Buffer
  3. var createHmac = require('create-hmac')
  4. var crt = require('browserify-rsa')
  5. var EC = require('elliptic').ec
  6. var BN = require('bn.js')
  7. var parseKeys = require('parse-asn1')
  8. var curves = require('./curves.json')
  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. var out = crt(pad, priv)
  29. return out
  30. }
  31. function ecSign (hash, priv) {
  32. var curveId = curves[priv.curve.join('.')]
  33. if (!curveId) throw new Error('unknown curve ' + priv.curve.join('.'))
  34. var curve = new EC(curveId)
  35. var key = curve.keyFromPrivate(priv.privateKey)
  36. var out = key.sign(hash)
  37. return Buffer.from(out.toDER())
  38. }
  39. function dsaSign (hash, priv, algo) {
  40. var x = priv.params.priv_key
  41. var p = priv.params.p
  42. var q = priv.params.q
  43. var g = priv.params.g
  44. var r = new BN(0)
  45. var k
  46. var H = bits2int(hash, q).mod(q)
  47. var s = false
  48. var kv = getKey(x, q, hash, algo)
  49. while (s === false) {
  50. k = makeKey(q, kv, algo)
  51. r = makeR(g, k, p, q)
  52. s = k.invm(q).imul(H.add(x.mul(r))).mod(q)
  53. if (s.cmpn(0) === 0) {
  54. s = false
  55. r = new BN(0)
  56. }
  57. }
  58. return toDER(r, s)
  59. }
  60. function toDER (r, s) {
  61. r = r.toArray()
  62. s = s.toArray()
  63. // Pad values
  64. if (r[0] & 0x80) r = [0].concat(r)
  65. if (s[0] & 0x80) s = [0].concat(s)
  66. var total = r.length + s.length + 4
  67. var res = [0x30, total, 0x02, r.length]
  68. res = res.concat(r, [0x02, s.length], s)
  69. return Buffer.from(res)
  70. }
  71. function getKey (x, q, hash, algo) {
  72. x = Buffer.from(x.toArray())
  73. if (x.length < q.byteLength()) {
  74. var zeros = Buffer.alloc(q.byteLength() - x.length)
  75. x = Buffer.concat([zeros, x])
  76. }
  77. var hlen = hash.length
  78. var hbits = bits2octets(hash, q)
  79. var v = Buffer.alloc(hlen)
  80. v.fill(1)
  81. var k = Buffer.alloc(hlen)
  82. k = createHmac(algo, k).update(v).update(Buffer.from([0])).update(x).update(hbits).digest()
  83. v = createHmac(algo, k).update(v).digest()
  84. k = createHmac(algo, k).update(v).update(Buffer.from([1])).update(x).update(hbits).digest()
  85. v = createHmac(algo, k).update(v).digest()
  86. return { k: k, v: v }
  87. }
  88. function bits2int (obits, q) {
  89. var bits = new BN(obits)
  90. var shift = (obits.length << 3) - q.bitLength()
  91. if (shift > 0) bits.ishrn(shift)
  92. return bits
  93. }
  94. function bits2octets (bits, q) {
  95. bits = bits2int(bits, q)
  96. bits = bits.mod(q)
  97. var out = Buffer.from(bits.toArray())
  98. if (out.length < q.byteLength()) {
  99. var zeros = Buffer.alloc(q.byteLength() - out.length)
  100. out = Buffer.concat([zeros, out])
  101. }
  102. return out
  103. }
  104. function makeKey (q, kv, algo) {
  105. var t
  106. var k
  107. do {
  108. t = Buffer.alloc(0)
  109. while (t.length * 8 < q.bitLength()) {
  110. kv.v = createHmac(algo, kv.k).update(kv.v).digest()
  111. t = Buffer.concat([t, kv.v])
  112. }
  113. k = bits2int(t, q)
  114. kv.k = createHmac(algo, kv.k).update(kv.v).update(Buffer.from([0])).digest()
  115. kv.v = createHmac(algo, kv.k).update(kv.v).digest()
  116. } while (k.cmp(q) !== -1)
  117. return k
  118. }
  119. function makeR (g, k, p, q) {
  120. return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q)
  121. }
  122. module.exports = sign
  123. module.exports.getKey = getKey
  124. module.exports.makeKey = makeKey