"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/sshpk/lib/key.js" (8 Mar 2017, 7323 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 = Key;
    4 
    5 var assert = require('assert-plus');
    6 var algs = require('./algs');
    7 var crypto = require('crypto');
    8 var Fingerprint = require('./fingerprint');
    9 var Signature = require('./signature');
   10 var DiffieHellman = require('./dhe');
   11 var errs = require('./errors');
   12 var utils = require('./utils');
   13 var PrivateKey = require('./private-key');
   14 var edCompat;
   15 
   16 try {
   17     edCompat = require('./ed-compat');
   18 } catch (e) {
   19     /* Just continue through, and bail out if we try to use it. */
   20 }
   21 
   22 var InvalidAlgorithmError = errs.InvalidAlgorithmError;
   23 var KeyParseError = errs.KeyParseError;
   24 
   25 var formats = {};
   26 formats['auto'] = require('./formats/auto');
   27 formats['pem'] = require('./formats/pem');
   28 formats['pkcs1'] = require('./formats/pkcs1');
   29 formats['pkcs8'] = require('./formats/pkcs8');
   30 formats['rfc4253'] = require('./formats/rfc4253');
   31 formats['ssh'] = require('./formats/ssh');
   32 formats['ssh-private'] = require('./formats/ssh-private');
   33 formats['openssh'] = formats['ssh-private'];
   34 
   35 function Key(opts) {
   36     assert.object(opts, 'options');
   37     assert.arrayOfObject(opts.parts, 'options.parts');
   38     assert.string(opts.type, 'options.type');
   39     assert.optionalString(opts.comment, 'options.comment');
   40 
   41     var algInfo = algs.info[opts.type];
   42     if (typeof (algInfo) !== 'object')
   43         throw (new InvalidAlgorithmError(opts.type));
   44 
   45     var partLookup = {};
   46     for (var i = 0; i < opts.parts.length; ++i) {
   47         var part = opts.parts[i];
   48         partLookup[part.name] = part;
   49     }
   50 
   51     this.type = opts.type;
   52     this.parts = opts.parts;
   53     this.part = partLookup;
   54     this.comment = undefined;
   55     this.source = opts.source;
   56 
   57     /* for speeding up hashing/fingerprint operations */
   58     this._rfc4253Cache = opts._rfc4253Cache;
   59     this._hashCache = {};
   60 
   61     var sz;
   62     this.curve = undefined;
   63     if (this.type === 'ecdsa') {
   64         var curve = this.part.curve.data.toString();
   65         this.curve = curve;
   66         sz = algs.curves[curve].size;
   67     } else if (this.type === 'ed25519') {
   68         sz = 256;
   69         this.curve = 'curve25519';
   70     } else {
   71         var szPart = this.part[algInfo.sizePart];
   72         sz = szPart.data.length;
   73         sz = sz * 8 - utils.countZeros(szPart.data);
   74     }
   75     this.size = sz;
   76 }
   77 
   78 Key.formats = formats;
   79 
   80 Key.prototype.toBuffer = function (format, options) {
   81     if (format === undefined)
   82         format = 'ssh';
   83     assert.string(format, 'format');
   84     assert.object(formats[format], 'formats[format]');
   85     assert.optionalObject(options, 'options');
   86 
   87     if (format === 'rfc4253') {
   88         if (this._rfc4253Cache === undefined)
   89             this._rfc4253Cache = formats['rfc4253'].write(this);
   90         return (this._rfc4253Cache);
   91     }
   92 
   93     return (formats[format].write(this, options));
   94 };
   95 
   96 Key.prototype.toString = function (format, options) {
   97     return (this.toBuffer(format, options).toString());
   98 };
   99 
  100 Key.prototype.hash = function (algo) {
  101     assert.string(algo, 'algorithm');
  102     algo = algo.toLowerCase();
  103     if (algs.hashAlgs[algo] === undefined)
  104         throw (new InvalidAlgorithmError(algo));
  105 
  106     if (this._hashCache[algo])
  107         return (this._hashCache[algo]);
  108 
  109     var hash = crypto.createHash(algo).
  110         update(this.toBuffer('rfc4253')).digest();
  111     this._hashCache[algo] = hash;
  112     return (hash);
  113 };
  114 
  115 Key.prototype.fingerprint = function (algo) {
  116     if (algo === undefined)
  117         algo = 'sha256';
  118     assert.string(algo, 'algorithm');
  119     var opts = {
  120         type: 'key',
  121         hash: this.hash(algo),
  122         algorithm: algo
  123     };
  124     return (new Fingerprint(opts));
  125 };
  126 
  127 Key.prototype.defaultHashAlgorithm = function () {
  128     var hashAlgo = 'sha1';
  129     if (this.type === 'rsa')
  130         hashAlgo = 'sha256';
  131     if (this.type === 'dsa' && this.size > 1024)
  132         hashAlgo = 'sha256';
  133     if (this.type === 'ed25519')
  134         hashAlgo = 'sha512';
  135     if (this.type === 'ecdsa') {
  136         if (this.size <= 256)
  137             hashAlgo = 'sha256';
  138         else if (this.size <= 384)
  139             hashAlgo = 'sha384';
  140         else
  141             hashAlgo = 'sha512';
  142     }
  143     return (hashAlgo);
  144 };
  145 
  146 Key.prototype.createVerify = function (hashAlgo) {
  147     if (hashAlgo === undefined)
  148         hashAlgo = this.defaultHashAlgorithm();
  149     assert.string(hashAlgo, 'hash algorithm');
  150 
  151     /* ED25519 is not supported by OpenSSL, use a javascript impl. */
  152     if (this.type === 'ed25519' && edCompat !== undefined)
  153         return (new edCompat.Verifier(this, hashAlgo));
  154     if (this.type === 'curve25519')
  155         throw (new Error('Curve25519 keys are not suitable for ' +
  156             'signing or verification'));
  157 
  158     var v, nm, err;
  159     try {
  160         nm = hashAlgo.toUpperCase();
  161         v = crypto.createVerify(nm);
  162     } catch (e) {
  163         err = e;
  164     }
  165     if (v === undefined || (err instanceof Error &&
  166         err.message.match(/Unknown message digest/))) {
  167         nm = 'RSA-';
  168         nm += hashAlgo.toUpperCase();
  169         v = crypto.createVerify(nm);
  170     }
  171     assert.ok(v, 'failed to create verifier');
  172     var oldVerify = v.verify.bind(v);
  173     var key = this.toBuffer('pkcs8');
  174     var self = this;
  175     v.verify = function (signature, fmt) {
  176         if (Signature.isSignature(signature, [2, 0])) {
  177             if (signature.type !== self.type)
  178                 return (false);
  179             if (signature.hashAlgorithm &&
  180                 signature.hashAlgorithm !== hashAlgo)
  181                 return (false);
  182             return (oldVerify(key, signature.toBuffer('asn1')));
  183 
  184         } else if (typeof (signature) === 'string' ||
  185             Buffer.isBuffer(signature)) {
  186             return (oldVerify(key, signature, fmt));
  187 
  188         /*
  189          * Avoid doing this on valid arguments, walking the prototype
  190          * chain can be quite slow.
  191          */
  192         } else if (Signature.isSignature(signature, [1, 0])) {
  193             throw (new Error('signature was created by too old ' +
  194                 'a version of sshpk and cannot be verified'));
  195 
  196         } else {
  197             throw (new TypeError('signature must be a string, ' +
  198                 'Buffer, or Signature object'));
  199         }
  200     };
  201     return (v);
  202 };
  203 
  204 Key.prototype.createDiffieHellman = function () {
  205     if (this.type === 'rsa')
  206         throw (new Error('RSA keys do not support Diffie-Hellman'));
  207 
  208     return (new DiffieHellman(this));
  209 };
  210 Key.prototype.createDH = Key.prototype.createDiffieHellman;
  211 
  212 Key.parse = function (data, format, options) {
  213     if (typeof (data) !== 'string')
  214         assert.buffer(data, 'data');
  215     if (format === undefined)
  216         format = 'auto';
  217     assert.string(format, 'format');
  218     if (typeof (options) === 'string')
  219         options = { filename: options };
  220     assert.optionalObject(options, 'options');
  221     if (options === undefined)
  222         options = {};
  223     assert.optionalString(options.filename, 'options.filename');
  224     if (options.filename === undefined)
  225         options.filename = '(unnamed)';
  226 
  227     assert.object(formats[format], 'formats[format]');
  228 
  229     try {
  230         var k = formats[format].read(data, options);
  231         if (k instanceof PrivateKey)
  232             k = k.toPublic();
  233         if (!k.comment)
  234             k.comment = options.filename;
  235         return (k);
  236     } catch (e) {
  237         if (e.name === 'KeyEncryptedError')
  238             throw (e);
  239         throw (new KeyParseError(options.filename, format, e));
  240     }
  241 };
  242 
  243 Key.isKey = function (obj, ver) {
  244     return (utils.isCompatible(obj, Key, ver));
  245 };
  246 
  247 /*
  248  * API versions for Key:
  249  * [1,0] -- initial ver, may take Signature for createVerify or may not
  250  * [1,1] -- added pkcs1, pkcs8 formats
  251  * [1,2] -- added auto, ssh-private, openssh formats
  252  * [1,3] -- added defaultHashAlgorithm
  253  * [1,4] -- added ed support, createDH
  254  * [1,5] -- first explicitly tagged version
  255  */
  256 Key.prototype._sshpkApiVersion = [1, 5];
  257 
  258 Key._oldVersionDetect = function (obj) {
  259     assert.func(obj.toBuffer);
  260     assert.func(obj.fingerprint);
  261     if (obj.createDH)
  262         return ([1, 4]);
  263     if (obj.defaultHashAlgorithm)
  264         return ([1, 3]);
  265     if (obj.formats['auto'])
  266         return ([1, 2]);
  267     if (obj.formats['pkcs1'])
  268         return ([1, 1]);
  269     return ([1, 0]);
  270 };