"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/sshpk/lib/utils.js" (8 Mar 2017, 7069 Bytes) of package /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 = {
    4     bufferSplit: bufferSplit,
    5     addRSAMissing: addRSAMissing,
    6     calculateDSAPublic: calculateDSAPublic,
    7     mpNormalize: mpNormalize,
    8     ecNormalize: ecNormalize,
    9     countZeros: countZeros,
   10     assertCompatible: assertCompatible,
   11     isCompatible: isCompatible,
   12     opensslKeyDeriv: opensslKeyDeriv,
   13     opensshCipherInfo: opensshCipherInfo
   14 };
   15 
   16 var assert = require('assert-plus');
   17 var PrivateKey = require('./private-key');
   18 var crypto = require('crypto');
   19 
   20 var MAX_CLASS_DEPTH = 3;
   21 
   22 function isCompatible(obj, klass, needVer) {
   23     if (obj === null || typeof (obj) !== 'object')
   24         return (false);
   25     if (needVer === undefined)
   26         needVer = klass.prototype._sshpkApiVersion;
   27     if (obj instanceof klass &&
   28         klass.prototype._sshpkApiVersion[0] == needVer[0])
   29         return (true);
   30     var proto = Object.getPrototypeOf(obj);
   31     var depth = 0;
   32     while (proto.constructor.name !== klass.name) {
   33         proto = Object.getPrototypeOf(proto);
   34         if (!proto || ++depth > MAX_CLASS_DEPTH)
   35             return (false);
   36     }
   37     if (proto.constructor.name !== klass.name)
   38         return (false);
   39     var ver = proto._sshpkApiVersion;
   40     if (ver === undefined)
   41         ver = klass._oldVersionDetect(obj);
   42     if (ver[0] != needVer[0] || ver[1] < needVer[1])
   43         return (false);
   44     return (true);
   45 }
   46 
   47 function assertCompatible(obj, klass, needVer, name) {
   48     if (name === undefined)
   49         name = 'object';
   50     assert.ok(obj, name + ' must not be null');
   51     assert.object(obj, name + ' must be an object');
   52     if (needVer === undefined)
   53         needVer = klass.prototype._sshpkApiVersion;
   54     if (obj instanceof klass &&
   55         klass.prototype._sshpkApiVersion[0] == needVer[0])
   56         return;
   57     var proto = Object.getPrototypeOf(obj);
   58     var depth = 0;
   59     while (proto.constructor.name !== klass.name) {
   60         proto = Object.getPrototypeOf(proto);
   61         assert.ok(proto && ++depth <= MAX_CLASS_DEPTH,
   62             name + ' must be a ' + klass.name + ' instance');
   63     }
   64     assert.strictEqual(proto.constructor.name, klass.name,
   65         name + ' must be a ' + klass.name + ' instance');
   66     var ver = proto._sshpkApiVersion;
   67     if (ver === undefined)
   68         ver = klass._oldVersionDetect(obj);
   69     assert.ok(ver[0] == needVer[0] && ver[1] >= needVer[1],
   70         name + ' must be compatible with ' + klass.name + ' klass ' +
   71         'version ' + needVer[0] + '.' + needVer[1]);
   72 }
   73 
   74 var CIPHER_LEN = {
   75     'des-ede3-cbc': { key: 7, iv: 8 },
   76     'aes-128-cbc': { key: 16, iv: 16 }
   77 };
   78 var PKCS5_SALT_LEN = 8;
   79 
   80 function opensslKeyDeriv(cipher, salt, passphrase, count) {
   81     assert.buffer(salt, 'salt');
   82     assert.buffer(passphrase, 'passphrase');
   83     assert.number(count, 'iteration count');
   84 
   85     var clen = CIPHER_LEN[cipher];
   86     assert.object(clen, 'supported cipher');
   87 
   88     salt = salt.slice(0, PKCS5_SALT_LEN);
   89 
   90     var D, D_prev, bufs;
   91     var material = new Buffer(0);
   92     while (material.length < clen.key + clen.iv) {
   93         bufs = [];
   94         if (D_prev)
   95             bufs.push(D_prev);
   96         bufs.push(passphrase);
   97         bufs.push(salt);
   98         D = Buffer.concat(bufs);
   99         for (var j = 0; j < count; ++j)
  100             D = crypto.createHash('md5').update(D).digest();
  101         material = Buffer.concat([material, D]);
  102         D_prev = D;
  103     }
  104 
  105     return ({
  106         key: material.slice(0, clen.key),
  107         iv: material.slice(clen.key, clen.key + clen.iv)
  108     });
  109 }
  110 
  111 /* Count leading zero bits on a buffer */
  112 function countZeros(buf) {
  113     var o = 0, obit = 8;
  114     while (o < buf.length) {
  115         var mask = (1 << obit);
  116         if ((buf[o] & mask) === mask)
  117             break;
  118         obit--;
  119         if (obit < 0) {
  120             o++;
  121             obit = 8;
  122         }
  123     }
  124     return (o*8 + (8 - obit) - 1);
  125 }
  126 
  127 function bufferSplit(buf, chr) {
  128     assert.buffer(buf);
  129     assert.string(chr);
  130 
  131     var parts = [];
  132     var lastPart = 0;
  133     var matches = 0;
  134     for (var i = 0; i < buf.length; ++i) {
  135         if (buf[i] === chr.charCodeAt(matches))
  136             ++matches;
  137         else if (buf[i] === chr.charCodeAt(0))
  138             matches = 1;
  139         else
  140             matches = 0;
  141 
  142         if (matches >= chr.length) {
  143             var newPart = i + 1;
  144             parts.push(buf.slice(lastPart, newPart - matches));
  145             lastPart = newPart;
  146             matches = 0;
  147         }
  148     }
  149     if (lastPart <= buf.length)
  150         parts.push(buf.slice(lastPart, buf.length));
  151 
  152     return (parts);
  153 }
  154 
  155 function ecNormalize(buf, addZero) {
  156     assert.buffer(buf);
  157     if (buf[0] === 0x00 && buf[1] === 0x04) {
  158         if (addZero)
  159             return (buf);
  160         return (buf.slice(1));
  161     } else if (buf[0] === 0x04) {
  162         if (!addZero)
  163             return (buf);
  164     } else {
  165         while (buf[0] === 0x00)
  166             buf = buf.slice(1);
  167         if (buf[0] === 0x02 || buf[0] === 0x03)
  168             throw (new Error('Compressed elliptic curve points ' +
  169                 'are not supported'));
  170         if (buf[0] !== 0x04)
  171             throw (new Error('Not a valid elliptic curve point'));
  172         if (!addZero)
  173             return (buf);
  174     }
  175     var b = new Buffer(buf.length + 1);
  176     b[0] = 0x0;
  177     buf.copy(b, 1);
  178     return (b);
  179 }
  180 
  181 function mpNormalize(buf) {
  182     assert.buffer(buf);
  183     while (buf.length > 1 && buf[0] === 0x00 && (buf[1] & 0x80) === 0x00)
  184         buf = buf.slice(1);
  185     if ((buf[0] & 0x80) === 0x80) {
  186         var b = new Buffer(buf.length + 1);
  187         b[0] = 0x00;
  188         buf.copy(b, 1);
  189         buf = b;
  190     }
  191     return (buf);
  192 }
  193 
  194 function bigintToMpBuf(bigint) {
  195     var buf = new Buffer(bigint.toByteArray());
  196     buf = mpNormalize(buf);
  197     return (buf);
  198 }
  199 
  200 function calculateDSAPublic(g, p, x) {
  201     assert.buffer(g);
  202     assert.buffer(p);
  203     assert.buffer(x);
  204     try {
  205         var bigInt = require('jsbn').BigInteger;
  206     } catch (e) {
  207         throw (new Error('To load a PKCS#8 format DSA private key, ' +
  208             'the node jsbn library is required.'));
  209     }
  210     g = new bigInt(g);
  211     p = new bigInt(p);
  212     x = new bigInt(x);
  213     var y = g.modPow(x, p);
  214     var ybuf = bigintToMpBuf(y);
  215     return (ybuf);
  216 }
  217 
  218 function addRSAMissing(key) {
  219     assert.object(key);
  220     assertCompatible(key, PrivateKey, [1, 1]);
  221     try {
  222         var bigInt = require('jsbn').BigInteger;
  223     } catch (e) {
  224         throw (new Error('To write a PEM private key from ' +
  225             'this source, the node jsbn lib is required.'));
  226     }
  227 
  228     var d = new bigInt(key.part.d.data);
  229     var buf;
  230 
  231     if (!key.part.dmodp) {
  232         var p = new bigInt(key.part.p.data);
  233         var dmodp = d.mod(p.subtract(1));
  234 
  235         buf = bigintToMpBuf(dmodp);
  236         key.part.dmodp = {name: 'dmodp', data: buf};
  237         key.parts.push(key.part.dmodp);
  238     }
  239     if (!key.part.dmodq) {
  240         var q = new bigInt(key.part.q.data);
  241         var dmodq = d.mod(q.subtract(1));
  242 
  243         buf = bigintToMpBuf(dmodq);
  244         key.part.dmodq = {name: 'dmodq', data: buf};
  245         key.parts.push(key.part.dmodq);
  246     }
  247 }
  248 
  249 function opensshCipherInfo(cipher) {
  250     var inf = {};
  251     switch (cipher) {
  252     case '3des-cbc':
  253         inf.keySize = 24;
  254         inf.blockSize = 8;
  255         inf.opensslName = 'des-ede3-cbc';
  256         break;
  257     case 'blowfish-cbc':
  258         inf.keySize = 16;
  259         inf.blockSize = 8;
  260         inf.opensslName = 'bf-cbc';
  261         break;
  262     case 'aes128-cbc':
  263     case 'aes128-ctr':
  264     case 'aes128-gcm@openssh.com':
  265         inf.keySize = 16;
  266         inf.blockSize = 16;
  267         inf.opensslName = 'aes-128-' + cipher.slice(7, 10);
  268         break;
  269     case 'aes192-cbc':
  270     case 'aes192-ctr':
  271     case 'aes192-gcm@openssh.com':
  272         inf.keySize = 24;
  273         inf.blockSize = 16;
  274         inf.opensslName = 'aes-192-' + cipher.slice(7, 10);
  275         break;
  276     case 'aes256-cbc':
  277     case 'aes256-ctr':
  278     case 'aes256-gcm@openssh.com':
  279         inf.keySize = 32;
  280         inf.blockSize = 16;
  281         inf.opensslName = 'aes-256-' + cipher.slice(7, 10);
  282         break;
  283     default:
  284         throw (new Error(
  285             'Unsupported openssl cipher "' + cipher + '"'));
  286     }
  287     return (inf);
  288 }