"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/sshpk/lib/dhe.js" (8 Mar 2017, 8317 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2015 Joyent, Inc.
    2 
    3 module.exports = DiffieHellman;
    4 
    5 var assert = require('assert-plus');
    6 var crypto = require('crypto');
    7 var algs = require('./algs');
    8 var utils = require('./utils');
    9 var ed;
   10 
   11 var Key = require('./key');
   12 var PrivateKey = require('./private-key');
   13 
   14 var CRYPTO_HAVE_ECDH = (crypto.createECDH !== undefined);
   15 
   16 var ecdh, ec, jsbn;
   17 
   18 function DiffieHellman(key) {
   19     utils.assertCompatible(key, Key, [1, 4], 'key');
   20     this._isPriv = PrivateKey.isPrivateKey(key, [1, 3]);
   21     this._algo = key.type;
   22     this._curve = key.curve;
   23     this._key = key;
   24     if (key.type === 'dsa') {
   25         if (!CRYPTO_HAVE_ECDH) {
   26             throw (new Error('Due to bugs in the node 0.10 ' +
   27                 'crypto API, node 0.12.x or later is required ' +
   28                 'to use DH'));
   29         }
   30         this._dh = crypto.createDiffieHellman(
   31             key.part.p.data, undefined,
   32             key.part.g.data, undefined);
   33         this._p = key.part.p;
   34         this._g = key.part.g;
   35         if (this._isPriv)
   36             this._dh.setPrivateKey(key.part.x.data);
   37         this._dh.setPublicKey(key.part.y.data);
   38 
   39     } else if (key.type === 'ecdsa') {
   40         if (!CRYPTO_HAVE_ECDH) {
   41             if (ecdh === undefined)
   42                 ecdh = require('ecc-jsbn');
   43             if (ec === undefined)
   44                 ec = require('ecc-jsbn/lib/ec');
   45             if (jsbn === undefined)
   46                 jsbn = require('jsbn').BigInteger;
   47 
   48             this._ecParams = new X9ECParameters(this._curve);
   49 
   50             if (this._isPriv) {
   51                 this._priv = new ECPrivate(
   52                     this._ecParams, key.part.d.data);
   53             }
   54             return;
   55         }
   56 
   57         var curve = {
   58             'nistp256': 'prime256v1',
   59             'nistp384': 'secp384r1',
   60             'nistp521': 'secp521r1'
   61         }[key.curve];
   62         this._dh = crypto.createECDH(curve);
   63         if (typeof (this._dh) !== 'object' ||
   64             typeof (this._dh.setPrivateKey) !== 'function') {
   65             CRYPTO_HAVE_ECDH = false;
   66             DiffieHellman.call(this, key);
   67             return;
   68         }
   69         if (this._isPriv)
   70             this._dh.setPrivateKey(key.part.d.data);
   71         this._dh.setPublicKey(key.part.Q.data);
   72 
   73     } else if (key.type === 'curve25519') {
   74         if (ed === undefined)
   75             ed = require('jodid25519');
   76 
   77         if (this._isPriv) {
   78             this._priv = key.part.r.data;
   79             if (this._priv[0] === 0x00)
   80                 this._priv = this._priv.slice(1);
   81             this._priv = this._priv.slice(0, 32);
   82         }
   83 
   84     } else {
   85         throw (new Error('DH not supported for ' + key.type + ' keys'));
   86     }
   87 }
   88 
   89 DiffieHellman.prototype.getPublicKey = function () {
   90     if (this._isPriv)
   91         return (this._key.toPublic());
   92     return (this._key);
   93 };
   94 
   95 DiffieHellman.prototype.getPrivateKey = function () {
   96     if (this._isPriv)
   97         return (this._key);
   98     else
   99         return (undefined);
  100 };
  101 DiffieHellman.prototype.getKey = DiffieHellman.prototype.getPrivateKey;
  102 
  103 DiffieHellman.prototype._keyCheck = function (pk, isPub) {
  104     assert.object(pk, 'key');
  105     if (!isPub)
  106         utils.assertCompatible(pk, PrivateKey, [1, 3], 'key');
  107     utils.assertCompatible(pk, Key, [1, 4], 'key');
  108 
  109     if (pk.type !== this._algo) {
  110         throw (new Error('A ' + pk.type + ' key cannot be used in ' +
  111             this._algo + ' Diffie-Hellman'));
  112     }
  113 
  114     if (pk.curve !== this._curve) {
  115         throw (new Error('A key from the ' + pk.curve + ' curve ' +
  116             'cannot be used with a ' + this._curve +
  117             ' Diffie-Hellman'));
  118     }
  119 
  120     if (pk.type === 'dsa') {
  121         assert.deepEqual(pk.part.p, this._p,
  122             'DSA key prime does not match');
  123         assert.deepEqual(pk.part.g, this._g,
  124             'DSA key generator does not match');
  125     }
  126 };
  127 
  128 DiffieHellman.prototype.setKey = function (pk) {
  129     this._keyCheck(pk);
  130 
  131     if (pk.type === 'dsa') {
  132         this._dh.setPrivateKey(pk.part.x.data);
  133         this._dh.setPublicKey(pk.part.y.data);
  134 
  135     } else if (pk.type === 'ecdsa') {
  136         if (CRYPTO_HAVE_ECDH) {
  137             this._dh.setPrivateKey(pk.part.d.data);
  138             this._dh.setPublicKey(pk.part.Q.data);
  139         } else {
  140             this._priv = new ECPrivate(
  141                 this._ecParams, pk.part.d.data);
  142         }
  143 
  144     } else if (pk.type === 'curve25519') {
  145         this._priv = pk.part.r.data;
  146         if (this._priv[0] === 0x00)
  147             this._priv = this._priv.slice(1);
  148         this._priv = this._priv.slice(0, 32);
  149     }
  150     this._key = pk;
  151     this._isPriv = true;
  152 };
  153 DiffieHellman.prototype.setPrivateKey = DiffieHellman.prototype.setKey;
  154 
  155 DiffieHellman.prototype.computeSecret = function (otherpk) {
  156     this._keyCheck(otherpk, true);
  157     if (!this._isPriv)
  158         throw (new Error('DH exchange has not been initialized with ' +
  159             'a private key yet'));
  160 
  161     var pub;
  162     if (this._algo === 'dsa') {
  163         return (this._dh.computeSecret(
  164             otherpk.part.y.data));
  165 
  166     } else if (this._algo === 'ecdsa') {
  167         if (CRYPTO_HAVE_ECDH) {
  168             return (this._dh.computeSecret(
  169                 otherpk.part.Q.data));
  170         } else {
  171             pub = new ECPublic(
  172                 this._ecParams, otherpk.part.Q.data);
  173             return (this._priv.deriveSharedSecret(pub));
  174         }
  175 
  176     } else if (this._algo === 'curve25519') {
  177         pub = otherpk.part.R.data;
  178         if (pub[0] === 0x00)
  179             pub = pub.slice(1);
  180 
  181         var secret = ed.dh.computeKey(
  182             this._priv.toString('binary'),
  183             pub.toString('binary'));
  184 
  185         return (new Buffer(secret, 'binary'));
  186     }
  187 
  188     throw (new Error('Invalid algorithm: ' + this._algo));
  189 };
  190 
  191 DiffieHellman.prototype.generateKey = function () {
  192     var parts = [];
  193     var priv, pub;
  194     if (this._algo === 'dsa') {
  195         this._dh.generateKeys();
  196 
  197         parts.push({name: 'p', data: this._p.data});
  198         parts.push({name: 'q', data: this._key.part.q.data});
  199         parts.push({name: 'g', data: this._g.data});
  200         parts.push({name: 'y', data: this._dh.getPublicKey()});
  201         parts.push({name: 'x', data: this._dh.getPrivateKey()});
  202         this._key = new PrivateKey({
  203             type: 'dsa',
  204             parts: parts
  205         });
  206         this._isPriv = true;
  207         return (this._key);
  208 
  209     } else if (this._algo === 'ecdsa') {
  210         if (CRYPTO_HAVE_ECDH) {
  211             this._dh.generateKeys();
  212 
  213             parts.push({name: 'curve',
  214                 data: new Buffer(this._curve)});
  215             parts.push({name: 'Q', data: this._dh.getPublicKey()});
  216             parts.push({name: 'd', data: this._dh.getPrivateKey()});
  217             this._key = new PrivateKey({
  218                 type: 'ecdsa',
  219                 curve: this._curve,
  220                 parts: parts
  221             });
  222             this._isPriv = true;
  223             return (this._key);
  224 
  225         } else {
  226             var n = this._ecParams.getN();
  227             var r = new jsbn(crypto.randomBytes(n.bitLength()));
  228             var n1 = n.subtract(jsbn.ONE);
  229             priv = r.mod(n1).add(jsbn.ONE);
  230             pub = this._ecParams.getG().multiply(priv);
  231 
  232             priv = new Buffer(priv.toByteArray());
  233             pub = new Buffer(this._ecParams.getCurve().
  234                 encodePointHex(pub), 'hex');
  235 
  236             this._priv = new ECPrivate(this._ecParams, priv);
  237 
  238             parts.push({name: 'curve',
  239                 data: new Buffer(this._curve)});
  240             parts.push({name: 'Q', data: pub});
  241             parts.push({name: 'd', data: priv});
  242 
  243             this._key = new PrivateKey({
  244                 type: 'ecdsa',
  245                 curve: this._curve,
  246                 parts: parts
  247             });
  248             this._isPriv = true;
  249             return (this._key);
  250         }
  251 
  252     } else if (this._algo === 'curve25519') {
  253         priv = ed.dh.generateKey();
  254         pub = ed.dh.publicKey(priv);
  255         this._priv = priv = new Buffer(priv, 'binary');
  256         pub = new Buffer(pub, 'binary');
  257 
  258         parts.push({name: 'R', data: pub});
  259         parts.push({name: 'r', data: Buffer.concat([priv, pub])});
  260         this._key = new PrivateKey({
  261             type: 'curve25519',
  262             parts: parts
  263         });
  264         this._isPriv = true;
  265         return (this._key);
  266     }
  267 
  268     throw (new Error('Invalid algorithm: ' + this._algo));
  269 };
  270 DiffieHellman.prototype.generateKeys = DiffieHellman.prototype.generateKey;
  271 
  272 /* These are helpers for using ecc-jsbn (for node 0.10 compatibility). */
  273 
  274 function X9ECParameters(name) {
  275     var params = algs.curves[name];
  276     assert.object(params);
  277 
  278     var p = new jsbn(params.p);
  279     var a = new jsbn(params.a);
  280     var b = new jsbn(params.b);
  281     var n = new jsbn(params.n);
  282     var h = jsbn.ONE;
  283     var curve = new ec.ECCurveFp(p, a, b);
  284     var G = curve.decodePointHex(params.G.toString('hex'));
  285 
  286     this.curve = curve;
  287     this.g = G;
  288     this.n = n;
  289     this.h = h;
  290 }
  291 X9ECParameters.prototype.getCurve = function () { return (this.curve); };
  292 X9ECParameters.prototype.getG = function () { return (this.g); };
  293 X9ECParameters.prototype.getN = function () { return (this.n); };
  294 X9ECParameters.prototype.getH = function () { return (this.h); };
  295 
  296 function ECPublic(params, buffer) {
  297     this._params = params;
  298     if (buffer[0] === 0x00)
  299         buffer = buffer.slice(1);
  300     this._pub = params.getCurve().decodePointHex(buffer.toString('hex'));
  301 }
  302 
  303 function ECPrivate(params, buffer) {
  304     this._params = params;
  305     this._priv = new jsbn(utils.mpNormalize(buffer));
  306 }
  307 ECPrivate.prototype.deriveSharedSecret = function (pubKey) {
  308     assert.ok(pubKey instanceof ECPublic);
  309     var S = pubKey._pub.multiply(this._priv);
  310     return (new Buffer(S.getX().toBigInteger().toByteArray()));
  311 };