Something went wrong. Try again.
A Twitter-Bot that is going to increase your followers.
Something went wrong. Try again.
8.1 kB · 294 lines
JavaScript
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295// Copyright 2018 Joyent, Inc.
module.exports = Key;
var assert = require('assert-plus');var algs = require('./algs');var crypto = require('crypto');var Fingerprint = require('./fingerprint');var Signature = require('./signature');var DiffieHellman = require('./dhe').DiffieHellman;var errs = require('./errors');var utils = require('./utils');var PrivateKey = require('./private-key');var edCompat;
try { edCompat = require('./ed-compat');} catch (e) { /* Just continue through, and bail out if we try to use it. */}
var InvalidAlgorithmError = errs.InvalidAlgorithmError;var KeyParseError = errs.KeyParseError;
var formats = {};formats['auto'] = require('./formats/auto');formats['pem'] = require('./formats/pem');formats['pkcs1'] = require('./formats/pkcs1');formats['pkcs8'] = require('./formats/pkcs8');formats['rfc4253'] = require('./formats/rfc4253');formats['ssh'] = require('./formats/ssh');formats['ssh-private'] = require('./formats/ssh-private');formats['openssh'] = formats['ssh-private'];formats['dnssec'] = require('./formats/dnssec');formats['putty'] = require('./formats/putty');formats['ppk'] = formats['putty'];
function Key(opts) { assert.object(opts, 'options'); assert.arrayOfObject(opts.parts, 'options.parts'); assert.string(opts.type, 'options.type'); assert.optionalString(opts.comment, 'options.comment');
var algInfo = algs.info[opts.type]; if (typeof (algInfo) !== 'object') throw (new InvalidAlgorithmError(opts.type));
var partLookup = {}; for (var i = 0; i < opts.parts.length; ++i) { var part = opts.parts[i]; partLookup[part.name] = part; }
this.type = opts.type; this.parts = opts.parts; this.part = partLookup; this.comment = undefined; this.source = opts.source;
/* for speeding up hashing/fingerprint operations */ this._rfc4253Cache = opts._rfc4253Cache; this._hashCache = {};
var sz; this.curve = undefined; if (this.type === 'ecdsa') { var curve = this.part.curve.data.toString(); this.curve = curve; sz = algs.curves[curve].size; } else if (this.type === 'ed25519' || this.type === 'curve25519') { sz = 256; this.curve = 'curve25519'; } else { var szPart = this.part[algInfo.sizePart]; sz = szPart.data.length; sz = sz * 8 - utils.countZeros(szPart.data); } this.size = sz;}
Key.formats = formats;
Key.prototype.toBuffer = function (format, options) { if (format === undefined) format = 'ssh'; assert.string(format, 'format'); assert.object(formats[format], 'formats[format]'); assert.optionalObject(options, 'options');
if (format === 'rfc4253') { if (this._rfc4253Cache === undefined) this._rfc4253Cache = formats['rfc4253'].write(this); return (this._rfc4253Cache); }
return (formats[format].write(this, options));};
Key.prototype.toString = function (format, options) { return (this.toBuffer(format, options).toString());};
Key.prototype.hash = function (algo, type) { assert.string(algo, 'algorithm'); assert.optionalString(type, 'type'); if (type === undefined) type = 'ssh'; algo = algo.toLowerCase(); if (algs.hashAlgs[algo] === undefined) throw (new InvalidAlgorithmError(algo));
var cacheKey = algo + '||' + type; if (this._hashCache[cacheKey]) return (this._hashCache[cacheKey]);
var buf; if (type === 'ssh') { buf = this.toBuffer('rfc4253'); } else if (type === 'spki') { buf = formats.pkcs8.pkcs8ToBuffer(this); } else { throw (new Error('Hash type ' + type + ' not supported')); } var hash = crypto.createHash(algo).update(buf).digest(); this._hashCache[cacheKey] = hash; return (hash);};
Key.prototype.fingerprint = function (algo, type) { if (algo === undefined) algo = 'sha256'; if (type === undefined) type = 'ssh'; assert.string(algo, 'algorithm'); assert.string(type, 'type'); var opts = { type: 'key', hash: this.hash(algo, type), algorithm: algo, hashType: type }; return (new Fingerprint(opts));};
Key.prototype.defaultHashAlgorithm = function () { var hashAlgo = 'sha1'; if (this.type === 'rsa') hashAlgo = 'sha256'; if (this.type === 'dsa' && this.size > 1024) hashAlgo = 'sha256'; if (this.type === 'ed25519') hashAlgo = 'sha512'; if (this.type === 'ecdsa') { if (this.size <= 256) hashAlgo = 'sha256'; else if (this.size <= 384) hashAlgo = 'sha384'; else hashAlgo = 'sha512'; } return (hashAlgo);};
Key.prototype.createVerify = function (hashAlgo) { if (hashAlgo === undefined) hashAlgo = this.defaultHashAlgorithm(); assert.string(hashAlgo, 'hash algorithm');
/* ED25519 is not supported by OpenSSL, use a javascript impl. */ if (this.type === 'ed25519' && edCompat !== undefined) return (new edCompat.Verifier(this, hashAlgo)); if (this.type === 'curve25519') throw (new Error('Curve25519 keys are not suitable for ' + 'signing or verification'));
var v, nm, err; try { nm = hashAlgo.toUpperCase(); v = crypto.createVerify(nm); } catch (e) { err = e; } if (v === undefined || (err instanceof Error && err.message.match(/Unknown message digest/))) { nm = 'RSA-'; nm += hashAlgo.toUpperCase(); v = crypto.createVerify(nm); } assert.ok(v, 'failed to create verifier'); var oldVerify = v.verify.bind(v); var key = this.toBuffer('pkcs8'); var curve = this.curve; var self = this; v.verify = function (signature, fmt) { if (Signature.isSignature(signature, [2, 0])) { if (signature.type !== self.type) return (false); if (signature.hashAlgorithm && signature.hashAlgorithm !== hashAlgo) return (false); if (signature.curve && self.type === 'ecdsa' && signature.curve !== curve) return (false); return (oldVerify(key, signature.toBuffer('asn1')));
} else if (typeof (signature) === 'string' || Buffer.isBuffer(signature)) { return (oldVerify(key, signature, fmt));
/* * Avoid doing this on valid arguments, walking the prototype * chain can be quite slow. */ } else if (Signature.isSignature(signature, [1, 0])) { throw (new Error('signature was created by too old ' + 'a version of sshpk and cannot be verified'));
} else { throw (new TypeError('signature must be a string, ' + 'Buffer, or Signature object')); } }; return (v);};
Key.prototype.createDiffieHellman = function () { if (this.type === 'rsa') throw (new Error('RSA keys do not support Diffie-Hellman'));
return (new DiffieHellman(this));};Key.prototype.createDH = Key.prototype.createDiffieHellman;
Key.parse = function (data, format, options) { if (typeof (data) !== 'string') assert.buffer(data, 'data'); if (format === undefined) format = 'auto'; assert.string(format, 'format'); if (typeof (options) === 'string') options = { filename: options }; assert.optionalObject(options, 'options'); if (options === undefined) options = {}; assert.optionalString(options.filename, 'options.filename'); if (options.filename === undefined) options.filename = '(unnamed)';
assert.object(formats[format], 'formats[format]');
try { var k = formats[format].read(data, options); if (k instanceof PrivateKey) k = k.toPublic(); if (!k.comment) k.comment = options.filename; return (k); } catch (e) { if (e.name === 'KeyEncryptedError') throw (e); throw (new KeyParseError(options.filename, format, e)); }};
Key.isKey = function (obj, ver) { return (utils.isCompatible(obj, Key, ver));};
/* * API versions for Key: * [1,0] -- initial ver, may take Signature for createVerify or may not * [1,1] -- added pkcs1, pkcs8 formats * [1,2] -- added auto, ssh-private, openssh formats * [1,3] -- added defaultHashAlgorithm * [1,4] -- added ed support, createDH * [1,5] -- first explicitly tagged version * [1,6] -- changed ed25519 part names * [1,7] -- spki hash types */Key.prototype._sshpkApiVersion = [1, 7];
Key._oldVersionDetect = function (obj) { assert.func(obj.toBuffer); assert.func(obj.fingerprint); if (obj.createDH) return ([1, 4]); if (obj.defaultHashAlgorithm) return ([1, 3]); if (obj.formats['auto']) return ([1, 2]); if (obj.formats['pkcs1']) return ([1, 1]); return ([1, 0]);};