125 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| var elliptic = require('elliptic')
 | |
| var BN = require('bn.js')
 | |
| 
 | |
| module.exports = function createECDH (curve) {
 | |
|   return new ECDH(curve)
 | |
| }
 | |
| 
 | |
| var aliases = {
 | |
|   secp256k1: {
 | |
|     name: 'secp256k1',
 | |
|     byteLength: 32
 | |
|   },
 | |
|   secp224r1: {
 | |
|     name: 'p224',
 | |
|     byteLength: 28
 | |
|   },
 | |
|   prime256v1: {
 | |
|     name: 'p256',
 | |
|     byteLength: 32
 | |
|   },
 | |
|   prime192v1: {
 | |
|     name: 'p192',
 | |
|     byteLength: 24
 | |
|   },
 | |
|   ed25519: {
 | |
|     name: 'ed25519',
 | |
|     byteLength: 32
 | |
|   },
 | |
|   secp384r1: {
 | |
|     name: 'p384',
 | |
|     byteLength: 48
 | |
|   },
 | |
|   secp521r1: {
 | |
|     name: 'p521',
 | |
|     byteLength: 66
 | |
|   }
 | |
| }
 | |
| 
 | |
| aliases.p224 = aliases.secp224r1
 | |
| aliases.p256 = aliases.secp256r1 = aliases.prime256v1
 | |
| aliases.p192 = aliases.secp192r1 = aliases.prime192v1
 | |
| aliases.p384 = aliases.secp384r1
 | |
| aliases.p521 = aliases.secp521r1
 | |
| 
 | |
| function ECDH (curve) {
 | |
|   this.curveType = aliases[curve]
 | |
|   if (!this.curveType) {
 | |
|     this.curveType = {
 | |
|       name: curve
 | |
|     }
 | |
|   }
 | |
|   this.curve = new elliptic.ec(this.curveType.name) // eslint-disable-line new-cap
 | |
|   this.keys = void 0
 | |
| }
 | |
| 
 | |
| ECDH.prototype.generateKeys = function (enc, format) {
 | |
|   this.keys = this.curve.genKeyPair()
 | |
|   return this.getPublicKey(enc, format)
 | |
| }
 | |
| 
 | |
| ECDH.prototype.computeSecret = function (other, inenc, enc) {
 | |
|   inenc = inenc || 'utf8'
 | |
|   if (!Buffer.isBuffer(other)) {
 | |
|     other = new Buffer(other, inenc)
 | |
|   }
 | |
|   var otherPub = this.curve.keyFromPublic(other).getPublic()
 | |
|   var out = otherPub.mul(this.keys.getPrivate()).getX()
 | |
|   return formatReturnValue(out, enc, this.curveType.byteLength)
 | |
| }
 | |
| 
 | |
| ECDH.prototype.getPublicKey = function (enc, format) {
 | |
|   var key = this.keys.getPublic(format === 'compressed', true)
 | |
|   if (format === 'hybrid') {
 | |
|     if (key[key.length - 1] % 2) {
 | |
|       key[0] = 7
 | |
|     } else {
 | |
|       key[0] = 6
 | |
|     }
 | |
|   }
 | |
|   return formatReturnValue(key, enc)
 | |
| }
 | |
| 
 | |
| ECDH.prototype.getPrivateKey = function (enc) {
 | |
|   return formatReturnValue(this.keys.getPrivate(), enc)
 | |
| }
 | |
| 
 | |
| ECDH.prototype.setPublicKey = function (pub, enc) {
 | |
|   enc = enc || 'utf8'
 | |
|   if (!Buffer.isBuffer(pub)) {
 | |
|     pub = new Buffer(pub, enc)
 | |
|   }
 | |
|   this.keys._importPublic(pub)
 | |
|   return this
 | |
| }
 | |
| 
 | |
| ECDH.prototype.setPrivateKey = function (priv, enc) {
 | |
|   enc = enc || 'utf8'
 | |
|   if (!Buffer.isBuffer(priv)) {
 | |
|     priv = new Buffer(priv, enc)
 | |
|   }
 | |
| 
 | |
|   var _priv = new BN(priv)
 | |
|   _priv = _priv.toString(16)
 | |
|   this.keys = this.curve.genKeyPair()
 | |
|   this.keys._importPrivate(_priv)
 | |
|   return this
 | |
| }
 | |
| 
 | |
| function formatReturnValue (bn, enc, len) {
 | |
|   if (!Array.isArray(bn)) {
 | |
|     bn = bn.toArray()
 | |
|   }
 | |
|   var buf = new Buffer(bn)
 | |
|   if (len && buf.length < len) {
 | |
|     var zeros = new Buffer(len - buf.length)
 | |
|     zeros.fill(0)
 | |
|     buf = Buffer.concat([zeros, buf])
 | |
|   }
 | |
|   if (!enc) {
 | |
|     return buf
 | |
|   } else {
 | |
|     return buf.toString(enc)
 | |
|   }
 | |
| }
 |