mirror of
				https://gitea.com/actions/setup-python.git
				synced 2025-10-31 17:18:07 +07:00 
			
		
		
		
	
		
			
				
	
	
		
			295 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // 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]);
 | |
| };
 |