publicEncrypt.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. var parseKeys = require('parse-asn1')
  2. var randomBytes = require('randombytes')
  3. var createHash = require('create-hash')
  4. var mgf = require('./mgf')
  5. var xor = require('./xor')
  6. var BN = require('bn.js')
  7. var withPublic = require('./withPublic')
  8. var crt = require('browserify-rsa')
  9. var Buffer = require('safe-buffer').Buffer
  10. module.exports = function publicEncrypt (publicKey, msg, reverse) {
  11. var padding
  12. if (publicKey.padding) {
  13. padding = publicKey.padding
  14. } else if (reverse) {
  15. padding = 1
  16. } else {
  17. padding = 4
  18. }
  19. var key = parseKeys(publicKey)
  20. var paddedMsg
  21. if (padding === 4) {
  22. paddedMsg = oaep(key, msg)
  23. } else if (padding === 1) {
  24. paddedMsg = pkcs1(key, msg, reverse)
  25. } else if (padding === 3) {
  26. paddedMsg = new BN(msg)
  27. if (paddedMsg.cmp(key.modulus) >= 0) {
  28. throw new Error('data too long for modulus')
  29. }
  30. } else {
  31. throw new Error('unknown padding')
  32. }
  33. if (reverse) {
  34. return crt(paddedMsg, key)
  35. } else {
  36. return withPublic(paddedMsg, key)
  37. }
  38. }
  39. function oaep (key, msg) {
  40. var k = key.modulus.byteLength()
  41. var mLen = msg.length
  42. var iHash = createHash('sha1').update(Buffer.alloc(0)).digest()
  43. var hLen = iHash.length
  44. var hLen2 = 2 * hLen
  45. if (mLen > k - hLen2 - 2) {
  46. throw new Error('message too long')
  47. }
  48. var ps = Buffer.alloc(k - mLen - hLen2 - 2)
  49. var dblen = k - hLen - 1
  50. var seed = randomBytes(hLen)
  51. var maskedDb = xor(Buffer.concat([iHash, ps, Buffer.alloc(1, 1), msg], dblen), mgf(seed, dblen))
  52. var maskedSeed = xor(seed, mgf(maskedDb, hLen))
  53. return new BN(Buffer.concat([Buffer.alloc(1), maskedSeed, maskedDb], k))
  54. }
  55. function pkcs1 (key, msg, reverse) {
  56. var mLen = msg.length
  57. var k = key.modulus.byteLength()
  58. if (mLen > k - 11) {
  59. throw new Error('message too long')
  60. }
  61. var ps
  62. if (reverse) {
  63. ps = Buffer.alloc(k - mLen - 3, 0xff)
  64. } else {
  65. ps = nonZero(k - mLen - 3)
  66. }
  67. return new BN(Buffer.concat([Buffer.from([0, reverse ? 1 : 2]), ps, Buffer.alloc(1), msg], k))
  68. }
  69. function nonZero (len) {
  70. var out = Buffer.allocUnsafe(len)
  71. var i = 0
  72. var cache = randomBytes(len * 2)
  73. var cur = 0
  74. var num
  75. while (i < len) {
  76. if (cur === cache.length) {
  77. cache = randomBytes(len * 2)
  78. cur = 0
  79. }
  80. num = cache[cur++]
  81. if (num) {
  82. out[i++] = num
  83. }
  84. }
  85. return out
  86. }