"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/sshpk/lib/certificate.js" (8 Mar 2017, 10717 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 2016 Joyent, Inc.
    2 
    3 module.exports = Certificate;
    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 errs = require('./errors');
   11 var util = require('util');
   12 var utils = require('./utils');
   13 var Key = require('./key');
   14 var PrivateKey = require('./private-key');
   15 var Identity = require('./identity');
   16 
   17 var formats = {};
   18 formats['openssh'] = require('./formats/openssh-cert');
   19 formats['x509'] = require('./formats/x509');
   20 formats['pem'] = require('./formats/x509-pem');
   21 
   22 var CertificateParseError = errs.CertificateParseError;
   23 var InvalidAlgorithmError = errs.InvalidAlgorithmError;
   24 
   25 function Certificate(opts) {
   26     assert.object(opts, 'options');
   27     assert.arrayOfObject(opts.subjects, 'options.subjects');
   28     utils.assertCompatible(opts.subjects[0], Identity, [1, 0],
   29         'options.subjects');
   30     utils.assertCompatible(opts.subjectKey, Key, [1, 0],
   31         'options.subjectKey');
   32     utils.assertCompatible(opts.issuer, Identity, [1, 0], 'options.issuer');
   33     if (opts.issuerKey !== undefined) {
   34         utils.assertCompatible(opts.issuerKey, Key, [1, 0],
   35             'options.issuerKey');
   36     }
   37     assert.object(opts.signatures, 'options.signatures');
   38     assert.buffer(opts.serial, 'options.serial');
   39     assert.date(opts.validFrom, 'options.validFrom');
   40     assert.date(opts.validUntil, 'optons.validUntil');
   41 
   42     assert.optionalArrayOfString(opts.purposes, 'options.purposes');
   43 
   44     this._hashCache = {};
   45 
   46     this.subjects = opts.subjects;
   47     this.issuer = opts.issuer;
   48     this.subjectKey = opts.subjectKey;
   49     this.issuerKey = opts.issuerKey;
   50     this.signatures = opts.signatures;
   51     this.serial = opts.serial;
   52     this.validFrom = opts.validFrom;
   53     this.validUntil = opts.validUntil;
   54     this.purposes = opts.purposes;
   55 }
   56 
   57 Certificate.formats = formats;
   58 
   59 Certificate.prototype.toBuffer = function (format, options) {
   60     if (format === undefined)
   61         format = 'x509';
   62     assert.string(format, 'format');
   63     assert.object(formats[format], 'formats[format]');
   64     assert.optionalObject(options, 'options');
   65 
   66     return (formats[format].write(this, options));
   67 };
   68 
   69 Certificate.prototype.toString = function (format, options) {
   70     if (format === undefined)
   71         format = 'pem';
   72     return (this.toBuffer(format, options).toString());
   73 };
   74 
   75 Certificate.prototype.fingerprint = function (algo) {
   76     if (algo === undefined)
   77         algo = 'sha256';
   78     assert.string(algo, 'algorithm');
   79     var opts = {
   80         type: 'certificate',
   81         hash: this.hash(algo),
   82         algorithm: algo
   83     };
   84     return (new Fingerprint(opts));
   85 };
   86 
   87 Certificate.prototype.hash = function (algo) {
   88     assert.string(algo, 'algorithm');
   89     algo = algo.toLowerCase();
   90     if (algs.hashAlgs[algo] === undefined)
   91         throw (new InvalidAlgorithmError(algo));
   92 
   93     if (this._hashCache[algo])
   94         return (this._hashCache[algo]);
   95 
   96     var hash = crypto.createHash(algo).
   97         update(this.toBuffer('x509')).digest();
   98     this._hashCache[algo] = hash;
   99     return (hash);
  100 };
  101 
  102 Certificate.prototype.isExpired = function (when) {
  103     if (when === undefined)
  104         when = new Date();
  105     return (!((when.getTime() >= this.validFrom.getTime()) &&
  106         (when.getTime() < this.validUntil.getTime())));
  107 };
  108 
  109 Certificate.prototype.isSignedBy = function (issuerCert) {
  110     utils.assertCompatible(issuerCert, Certificate, [1, 0], 'issuer');
  111 
  112     if (!this.issuer.equals(issuerCert.subjects[0]))
  113         return (false);
  114     if (this.issuer.purposes && this.issuer.purposes.length > 0 &&
  115         this.issuer.purposes.indexOf('ca') === -1) {
  116         return (false);
  117     }
  118 
  119     return (this.isSignedByKey(issuerCert.subjectKey));
  120 };
  121 
  122 Certificate.prototype.isSignedByKey = function (issuerKey) {
  123     utils.assertCompatible(issuerKey, Key, [1, 2], 'issuerKey');
  124 
  125     if (this.issuerKey !== undefined) {
  126         return (this.issuerKey.
  127             fingerprint('sha512').matches(issuerKey));
  128     }
  129 
  130     var fmt = Object.keys(this.signatures)[0];
  131     var valid = formats[fmt].verify(this, issuerKey);
  132     if (valid)
  133         this.issuerKey = issuerKey;
  134     return (valid);
  135 };
  136 
  137 Certificate.prototype.signWith = function (key) {
  138     utils.assertCompatible(key, PrivateKey, [1, 2], 'key');
  139     var fmts = Object.keys(formats);
  140     var didOne = false;
  141     for (var i = 0; i < fmts.length; ++i) {
  142         if (fmts[i] !== 'pem') {
  143             var ret = formats[fmts[i]].sign(this, key);
  144             if (ret === true)
  145                 didOne = true;
  146         }
  147     }
  148     if (!didOne) {
  149         throw (new Error('Failed to sign the certificate for any ' +
  150             'available certificate formats'));
  151     }
  152 };
  153 
  154 Certificate.createSelfSigned = function (subjectOrSubjects, key, options) {
  155     var subjects;
  156     if (Array.isArray(subjectOrSubjects))
  157         subjects = subjectOrSubjects;
  158     else
  159         subjects = [subjectOrSubjects];
  160 
  161     assert.arrayOfObject(subjects);
  162     subjects.forEach(function (subject) {
  163         utils.assertCompatible(subject, Identity, [1, 0], 'subject');
  164     });
  165 
  166     utils.assertCompatible(key, PrivateKey, [1, 2], 'private key');
  167 
  168     assert.optionalObject(options, 'options');
  169     if (options === undefined)
  170         options = {};
  171     assert.optionalObject(options.validFrom, 'options.validFrom');
  172     assert.optionalObject(options.validUntil, 'options.validUntil');
  173     var validFrom = options.validFrom;
  174     var validUntil = options.validUntil;
  175     if (validFrom === undefined)
  176         validFrom = new Date();
  177     if (validUntil === undefined) {
  178         assert.optionalNumber(options.lifetime, 'options.lifetime');
  179         var lifetime = options.lifetime;
  180         if (lifetime === undefined)
  181             lifetime = 10*365*24*3600;
  182         validUntil = new Date();
  183         validUntil.setTime(validUntil.getTime() + lifetime*1000);
  184     }
  185     assert.optionalBuffer(options.serial, 'options.serial');
  186     var serial = options.serial;
  187     if (serial === undefined)
  188         serial = new Buffer('0000000000000001', 'hex');
  189 
  190     var purposes = options.purposes;
  191     if (purposes === undefined)
  192         purposes = [];
  193 
  194     if (purposes.indexOf('signature') === -1)
  195         purposes.push('signature');
  196 
  197     /* Self-signed certs are always CAs. */
  198     if (purposes.indexOf('ca') === -1)
  199         purposes.push('ca');
  200     if (purposes.indexOf('crl') === -1)
  201         purposes.push('crl');
  202 
  203     /*
  204      * If we weren't explicitly given any other purposes, do the sensible
  205      * thing and add some basic ones depending on the subject type.
  206      */
  207     if (purposes.length <= 3) {
  208         var hostSubjects = subjects.filter(function (subject) {
  209             return (subject.type === 'host');
  210         });
  211         var userSubjects = subjects.filter(function (subject) {
  212             return (subject.type === 'user');
  213         });
  214         if (hostSubjects.length > 0) {
  215             if (purposes.indexOf('serverAuth') === -1)
  216                 purposes.push('serverAuth');
  217         }
  218         if (userSubjects.length > 0) {
  219             if (purposes.indexOf('clientAuth') === -1)
  220                 purposes.push('clientAuth');
  221         }
  222         if (userSubjects.length > 0 || hostSubjects.length > 0) {
  223             if (purposes.indexOf('keyAgreement') === -1)
  224                 purposes.push('keyAgreement');
  225             if (key.type === 'rsa' &&
  226                 purposes.indexOf('encryption') === -1)
  227                 purposes.push('encryption');
  228         }
  229     }
  230 
  231     var cert = new Certificate({
  232         subjects: subjects,
  233         issuer: subjects[0],
  234         subjectKey: key.toPublic(),
  235         issuerKey: key.toPublic(),
  236         signatures: {},
  237         serial: serial,
  238         validFrom: validFrom,
  239         validUntil: validUntil,
  240         purposes: purposes
  241     });
  242     cert.signWith(key);
  243 
  244     return (cert);
  245 };
  246 
  247 Certificate.create =
  248     function (subjectOrSubjects, key, issuer, issuerKey, options) {
  249     var subjects;
  250     if (Array.isArray(subjectOrSubjects))
  251         subjects = subjectOrSubjects;
  252     else
  253         subjects = [subjectOrSubjects];
  254 
  255     assert.arrayOfObject(subjects);
  256     subjects.forEach(function (subject) {
  257         utils.assertCompatible(subject, Identity, [1, 0], 'subject');
  258     });
  259 
  260     utils.assertCompatible(key, Key, [1, 0], 'key');
  261     if (PrivateKey.isPrivateKey(key))
  262         key = key.toPublic();
  263     utils.assertCompatible(issuer, Identity, [1, 0], 'issuer');
  264     utils.assertCompatible(issuerKey, PrivateKey, [1, 2], 'issuer key');
  265 
  266     assert.optionalObject(options, 'options');
  267     if (options === undefined)
  268         options = {};
  269     assert.optionalObject(options.validFrom, 'options.validFrom');
  270     assert.optionalObject(options.validUntil, 'options.validUntil');
  271     var validFrom = options.validFrom;
  272     var validUntil = options.validUntil;
  273     if (validFrom === undefined)
  274         validFrom = new Date();
  275     if (validUntil === undefined) {
  276         assert.optionalNumber(options.lifetime, 'options.lifetime');
  277         var lifetime = options.lifetime;
  278         if (lifetime === undefined)
  279             lifetime = 10*365*24*3600;
  280         validUntil = new Date();
  281         validUntil.setTime(validUntil.getTime() + lifetime*1000);
  282     }
  283     assert.optionalBuffer(options.serial, 'options.serial');
  284     var serial = options.serial;
  285     if (serial === undefined)
  286         serial = new Buffer('0000000000000001', 'hex');
  287 
  288     var purposes = options.purposes;
  289     if (purposes === undefined)
  290         purposes = [];
  291 
  292     if (purposes.indexOf('signature') === -1)
  293         purposes.push('signature');
  294 
  295     if (options.ca === true) {
  296         if (purposes.indexOf('ca') === -1)
  297             purposes.push('ca');
  298         if (purposes.indexOf('crl') === -1)
  299             purposes.push('crl');
  300     }
  301 
  302     var hostSubjects = subjects.filter(function (subject) {
  303         return (subject.type === 'host');
  304     });
  305     var userSubjects = subjects.filter(function (subject) {
  306         return (subject.type === 'user');
  307     });
  308     if (hostSubjects.length > 0) {
  309         if (purposes.indexOf('serverAuth') === -1)
  310             purposes.push('serverAuth');
  311     }
  312     if (userSubjects.length > 0) {
  313         if (purposes.indexOf('clientAuth') === -1)
  314             purposes.push('clientAuth');
  315     }
  316     if (userSubjects.length > 0 || hostSubjects.length > 0) {
  317         if (purposes.indexOf('keyAgreement') === -1)
  318             purposes.push('keyAgreement');
  319         if (key.type === 'rsa' &&
  320             purposes.indexOf('encryption') === -1)
  321             purposes.push('encryption');
  322     }
  323 
  324     var cert = new Certificate({
  325         subjects: subjects,
  326         issuer: issuer,
  327         subjectKey: key,
  328         issuerKey: issuerKey.toPublic(),
  329         signatures: {},
  330         serial: serial,
  331         validFrom: validFrom,
  332         validUntil: validUntil,
  333         purposes: purposes
  334     });
  335     cert.signWith(issuerKey);
  336 
  337     return (cert);
  338 };
  339 
  340 Certificate.parse = function (data, format, options) {
  341     if (typeof (data) !== 'string')
  342         assert.buffer(data, 'data');
  343     if (format === undefined)
  344         format = 'auto';
  345     assert.string(format, 'format');
  346     if (typeof (options) === 'string')
  347         options = { filename: options };
  348     assert.optionalObject(options, 'options');
  349     if (options === undefined)
  350         options = {};
  351     assert.optionalString(options.filename, 'options.filename');
  352     if (options.filename === undefined)
  353         options.filename = '(unnamed)';
  354 
  355     assert.object(formats[format], 'formats[format]');
  356 
  357     try {
  358         var k = formats[format].read(data, options);
  359         return (k);
  360     } catch (e) {
  361         throw (new CertificateParseError(options.filename, format, e));
  362     }
  363 };
  364 
  365 Certificate.isCertificate = function (obj, ver) {
  366     return (utils.isCompatible(obj, Certificate, ver));
  367 };
  368 
  369 /*
  370  * API versions for Certificate:
  371  * [1,0] -- initial ver
  372  */
  373 Certificate.prototype._sshpkApiVersion = [1, 0];
  374 
  375 Certificate._oldVersionDetect = function (obj) {
  376     return ([1, 0]);
  377 };