| var parseKeys = require('parse-asn1') |
| var randomBytes = require('randombytes') |
| var createHash = require('create-hash') |
| var mgf = require('./mgf') |
| var xor = require('./xor') |
| var BN = require('bn.js') |
| var withPublic = require('./withPublic') |
| var crt = require('browserify-rsa') |
| var Buffer = require('safe-buffer').Buffer |
| |
| module.exports = function publicEncrypt (publicKey, msg, reverse) { |
| var padding |
| if (publicKey.padding) { |
| padding = publicKey.padding |
| } else if (reverse) { |
| padding = 1 |
| } else { |
| padding = 4 |
| } |
| var key = parseKeys(publicKey) |
| var paddedMsg |
| if (padding === 4) { |
| paddedMsg = oaep(key, msg) |
| } else if (padding === 1) { |
| paddedMsg = pkcs1(key, msg, reverse) |
| } else if (padding === 3) { |
| paddedMsg = new BN(msg) |
| if (paddedMsg.cmp(key.modulus) >= 0) { |
| throw new Error('data too long for modulus') |
| } |
| } else { |
| throw new Error('unknown padding') |
| } |
| if (reverse) { |
| return crt(paddedMsg, key) |
| } else { |
| return withPublic(paddedMsg, key) |
| } |
| } |
| |
| function oaep (key, msg) { |
| var k = key.modulus.byteLength() |
| var mLen = msg.length |
| var iHash = createHash('sha1').update(Buffer.alloc(0)).digest() |
| var hLen = iHash.length |
| var hLen2 = 2 * hLen |
| if (mLen > k - hLen2 - 2) { |
| throw new Error('message too long') |
| } |
| var ps = Buffer.alloc(k - mLen - hLen2 - 2) |
| var dblen = k - hLen - 1 |
| var seed = randomBytes(hLen) |
| var maskedDb = xor(Buffer.concat([iHash, ps, Buffer.alloc(1, 1), msg], dblen), mgf(seed, dblen)) |
| var maskedSeed = xor(seed, mgf(maskedDb, hLen)) |
| return new BN(Buffer.concat([Buffer.alloc(1), maskedSeed, maskedDb], k)) |
| } |
| function pkcs1 (key, msg, reverse) { |
| var mLen = msg.length |
| var k = key.modulus.byteLength() |
| if (mLen > k - 11) { |
| throw new Error('message too long') |
| } |
| var ps |
| if (reverse) { |
| ps = Buffer.alloc(k - mLen - 3, 0xff) |
| } else { |
| ps = nonZero(k - mLen - 3) |
| } |
| return new BN(Buffer.concat([Buffer.from([0, reverse ? 1 : 2]), ps, Buffer.alloc(1), msg], k)) |
| } |
| function nonZero (len) { |
| var out = Buffer.allocUnsafe(len) |
| var i = 0 |
| var cache = randomBytes(len * 2) |
| var cur = 0 |
| var num |
| while (i < len) { |
| if (cur === cache.length) { |
| cache = randomBytes(len * 2) |
| cur = 0 |
| } |
| num = cache[cur++] |
| if (num) { |
| out[i++] = num |
| } |
| } |
| return out |
| } |