You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					89 lines
				
				2.3 KiB
			
		
		
			
		
	
	
					89 lines
				
				2.3 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								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
							 | 
						||
| 
								 | 
							
								}
							 |