"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/sshpk/lib/formats/pem.js" (7 Feb 2017, 4827 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 = {
    4     read: read,
    5     write: write
    6 };
    7 
    8 var assert = require('assert-plus');
    9 var asn1 = require('asn1');
   10 var crypto = require('crypto');
   11 var algs = require('../algs');
   12 var utils = require('../utils');
   13 var Key = require('../key');
   14 var PrivateKey = require('../private-key');
   15 
   16 var pkcs1 = require('./pkcs1');
   17 var pkcs8 = require('./pkcs8');
   18 var sshpriv = require('./ssh-private');
   19 var rfc4253 = require('./rfc4253');
   20 
   21 var errors = require('../errors');
   22 
   23 /*
   24  * For reading we support both PKCS#1 and PKCS#8. If we find a private key,
   25  * we just take the public component of it and use that.
   26  */
   27 function read(buf, options, forceType) {
   28     var input = buf;
   29     if (typeof (buf) !== 'string') {
   30         assert.buffer(buf, 'buf');
   31         buf = buf.toString('ascii');
   32     }
   33 
   34     var lines = buf.trim().split('\n');
   35 
   36     var m = lines[0].match(/*JSSTYLED*/
   37         /[-]+[ ]*BEGIN ([A-Z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
   38     assert.ok(m, 'invalid PEM header');
   39 
   40     var m2 = lines[lines.length - 1].match(/*JSSTYLED*/
   41         /[-]+[ ]*END ([A-Z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
   42     assert.ok(m2, 'invalid PEM footer');
   43 
   44     /* Begin and end banners must match key type */
   45     assert.equal(m[2], m2[2]);
   46     var type = m[2].toLowerCase();
   47 
   48     var alg;
   49     if (m[1]) {
   50         /* They also must match algorithms, if given */
   51         assert.equal(m[1], m2[1], 'PEM header and footer mismatch');
   52         alg = m[1].trim();
   53     }
   54 
   55     var headers = {};
   56     while (true) {
   57         lines = lines.slice(1);
   58         m = lines[0].match(/*JSSTYLED*/
   59             /^([A-Za-z0-9-]+): (.+)$/);
   60         if (!m)
   61             break;
   62         headers[m[1].toLowerCase()] = m[2];
   63     }
   64 
   65     var cipher, key, iv;
   66     if (headers['proc-type']) {
   67         var parts = headers['proc-type'].split(',');
   68         if (parts[0] === '4' && parts[1] === 'ENCRYPTED') {
   69             if (typeof (options.passphrase) === 'string') {
   70                 options.passphrase = new Buffer(
   71                     options.passphrase, 'utf-8');
   72             }
   73             if (!Buffer.isBuffer(options.passphrase)) {
   74                 throw (new errors.KeyEncryptedError(
   75                     options.filename, 'PEM'));
   76             } else {
   77                 parts = headers['dek-info'].split(',');
   78                 assert.ok(parts.length === 2);
   79                 cipher = parts[0].toLowerCase();
   80                 iv = new Buffer(parts[1], 'hex');
   81                 key = utils.opensslKeyDeriv(cipher, iv,
   82                     options.passphrase, 1).key;
   83             }
   84         }
   85     }
   86 
   87     /* Chop off the first and last lines */
   88     lines = lines.slice(0, -1).join('');
   89     buf = new Buffer(lines, 'base64');
   90 
   91     if (cipher && key && iv) {
   92         var cipherStream = crypto.createDecipheriv(cipher, key, iv);
   93         var chunk, chunks = [];
   94         cipherStream.once('error', function (e) {
   95             if (e.toString().indexOf('bad decrypt') !== -1) {
   96                 throw (new Error('Incorrect passphrase ' +
   97                     'supplied, could not decrypt key'));
   98             }
   99             throw (e);
  100         });
  101         cipherStream.write(buf);
  102         cipherStream.end();
  103         while ((chunk = cipherStream.read()) !== null)
  104             chunks.push(chunk);
  105         buf = Buffer.concat(chunks);
  106     }
  107 
  108     /* The new OpenSSH internal format abuses PEM headers */
  109     if (alg && alg.toLowerCase() === 'openssh')
  110         return (sshpriv.readSSHPrivate(type, buf, options));
  111     if (alg && alg.toLowerCase() === 'ssh2')
  112         return (rfc4253.readType(type, buf, options));
  113 
  114     var der = new asn1.BerReader(buf);
  115     der.originalInput = input;
  116 
  117     /*
  118      * All of the PEM file types start with a sequence tag, so chop it
  119      * off here
  120      */
  121     der.readSequence();
  122 
  123     /* PKCS#1 type keys name an algorithm in the banner explicitly */
  124     if (alg) {
  125         if (forceType)
  126             assert.strictEqual(forceType, 'pkcs1');
  127         return (pkcs1.readPkcs1(alg, type, der));
  128     } else {
  129         if (forceType)
  130             assert.strictEqual(forceType, 'pkcs8');
  131         return (pkcs8.readPkcs8(alg, type, der));
  132     }
  133 }
  134 
  135 function write(key, options, type) {
  136     assert.object(key);
  137 
  138     var alg = {'ecdsa': 'EC', 'rsa': 'RSA', 'dsa': 'DSA'}[key.type];
  139     var header;
  140 
  141     var der = new asn1.BerWriter();
  142 
  143     if (PrivateKey.isPrivateKey(key)) {
  144         if (type && type === 'pkcs8') {
  145             header = 'PRIVATE KEY';
  146             pkcs8.writePkcs8(der, key);
  147         } else {
  148             if (type)
  149                 assert.strictEqual(type, 'pkcs1');
  150             header = alg + ' PRIVATE KEY';
  151             pkcs1.writePkcs1(der, key);
  152         }
  153 
  154     } else if (Key.isKey(key)) {
  155         if (type && type === 'pkcs1') {
  156             header = alg + ' PUBLIC KEY';
  157             pkcs1.writePkcs1(der, key);
  158         } else {
  159             if (type)
  160                 assert.strictEqual(type, 'pkcs8');
  161             header = 'PUBLIC KEY';
  162             pkcs8.writePkcs8(der, key);
  163         }
  164 
  165     } else {
  166         throw (new Error('key is not a Key or PrivateKey'));
  167     }
  168 
  169     var tmp = der.buffer.toString('base64');
  170     var len = tmp.length + (tmp.length / 64) +
  171         18 + 16 + header.length*2 + 10;
  172     var buf = new Buffer(len);
  173     var o = 0;
  174     o += buf.write('-----BEGIN ' + header + '-----\n', o);
  175     for (var i = 0; i < tmp.length; ) {
  176         var limit = i + 64;
  177         if (limit > tmp.length)
  178             limit = tmp.length;
  179         o += buf.write(tmp.slice(i, limit), o);
  180         buf[o++] = 10;
  181         i = limit;
  182     }
  183     o += buf.write('-----END ' + header + '-----\n', o);
  184 
  185     return (buf.slice(0, o));
  186 }