react / wstein / node_modules / jest-cli / node_modules / jsdom / node_modules / request / node_modules / http-signature / lib / util.js
81146 views// Copyright 2012 Joyent, Inc. All rights reserved.12var assert = require('assert-plus');3var crypto = require('crypto');45var asn1 = require('asn1');6var ctype = require('ctype');78910///--- Helpers1112function readNext(buffer, offset) {13var len = ctype.ruint32(buffer, 'big', offset);14offset += 4;1516var newOffset = offset + len;1718return {19data: buffer.slice(offset, newOffset),20offset: newOffset21};22}232425function writeInt(writer, buffer) {26writer.writeByte(0x02); // ASN1.Integer27writer.writeLength(buffer.length);2829for (var i = 0; i < buffer.length; i++)30writer.writeByte(buffer[i]);3132return writer;33}343536function rsaToPEM(key) {37var buffer;38var der;39var exponent;40var i;41var modulus;42var newKey = '';43var offset = 0;44var type;45var tmp;4647try {48buffer = new Buffer(key.split(' ')[1], 'base64');4950tmp = readNext(buffer, offset);51type = tmp.data.toString();52offset = tmp.offset;5354if (type !== 'ssh-rsa')55throw new Error('Invalid ssh key type: ' + type);5657tmp = readNext(buffer, offset);58exponent = tmp.data;59offset = tmp.offset;6061tmp = readNext(buffer, offset);62modulus = tmp.data;63} catch (e) {64throw new Error('Invalid ssh key: ' + key);65}6667// DER is a subset of BER68der = new asn1.BerWriter();6970der.startSequence();7172der.startSequence();73der.writeOID('1.2.840.113549.1.1.1');74der.writeNull();75der.endSequence();7677der.startSequence(0x03); // bit string78der.writeByte(0x00);7980// Actual key81der.startSequence();82writeInt(der, modulus);83writeInt(der, exponent);84der.endSequence();8586// bit string87der.endSequence();8889der.endSequence();9091tmp = der.buffer.toString('base64');92for (i = 0; i < tmp.length; i++) {93if ((i % 64) === 0)94newKey += '\n';95newKey += tmp.charAt(i);96}9798if (!/\\n$/.test(newKey))99newKey += '\n';100101return '-----BEGIN PUBLIC KEY-----' + newKey + '-----END PUBLIC KEY-----\n';102}103104105function dsaToPEM(key) {106var buffer;107var offset = 0;108var tmp;109var der;110var newKey = '';111112var type;113var p;114var q;115var g;116var y;117118try {119buffer = new Buffer(key.split(' ')[1], 'base64');120121tmp = readNext(buffer, offset);122type = tmp.data.toString();123offset = tmp.offset;124125/* JSSTYLED */126if (!/^ssh-ds[as].*/.test(type))127throw new Error('Invalid ssh key type: ' + type);128129tmp = readNext(buffer, offset);130p = tmp.data;131offset = tmp.offset;132133tmp = readNext(buffer, offset);134q = tmp.data;135offset = tmp.offset;136137tmp = readNext(buffer, offset);138g = tmp.data;139offset = tmp.offset;140141tmp = readNext(buffer, offset);142y = tmp.data;143} catch (e) {144console.log(e.stack);145throw new Error('Invalid ssh key: ' + key);146}147148// DER is a subset of BER149der = new asn1.BerWriter();150151der.startSequence();152153der.startSequence();154der.writeOID('1.2.840.10040.4.1');155156der.startSequence();157writeInt(der, p);158writeInt(der, q);159writeInt(der, g);160der.endSequence();161162der.endSequence();163164der.startSequence(0x03); // bit string165der.writeByte(0x00);166writeInt(der, y);167der.endSequence();168169der.endSequence();170171tmp = der.buffer.toString('base64');172for (var i = 0; i < tmp.length; i++) {173if ((i % 64) === 0)174newKey += '\n';175newKey += tmp.charAt(i);176}177178if (!/\\n$/.test(newKey))179newKey += '\n';180181return '-----BEGIN PUBLIC KEY-----' + newKey + '-----END PUBLIC KEY-----\n';182}183184185///--- API186187module.exports = {188189/**190* Converts an OpenSSH public key (rsa only) to a PKCS#8 PEM file.191*192* The intent of this module is to interoperate with OpenSSL only,193* specifically the node crypto module's `verify` method.194*195* @param {String} key an OpenSSH public key.196* @return {String} PEM encoded form of the RSA public key.197* @throws {TypeError} on bad input.198* @throws {Error} on invalid ssh key formatted data.199*/200sshKeyToPEM: function sshKeyToPEM(key) {201assert.string(key, 'ssh_key');202203/* JSSTYLED */204if (/^ssh-rsa.*/.test(key))205return rsaToPEM(key);206207/* JSSTYLED */208if (/^ssh-ds[as].*/.test(key))209return dsaToPEM(key);210211throw new Error('Only RSA and DSA public keys are allowed');212},213214215/**216* Generates an OpenSSH fingerprint from an ssh public key.217*218* @param {String} key an OpenSSH public key.219* @return {String} key fingerprint.220* @throws {TypeError} on bad input.221* @throws {Error} if what you passed doesn't look like an ssh public key.222*/223fingerprint: function fingerprint(key) {224assert.string(key, 'ssh_key');225226var pieces = key.split(' ');227if (!pieces || !pieces.length || pieces.length < 2)228throw new Error('invalid ssh key');229230var data = new Buffer(pieces[1], 'base64');231232var hash = crypto.createHash('md5');233hash.update(data);234var digest = hash.digest('hex');235236var fp = '';237for (var i = 0; i < digest.length; i++) {238if (i && i % 2 === 0)239fp += ':';240241fp += digest[i];242}243244return fp;245},246247/**248* Converts a PKGCS#8 PEM file to an OpenSSH public key (rsa)249*250* The reverse of the above function.251*/252pemToRsaSSHKey: function pemToRsaSSHKey(pem, comment) {253assert.equal('string', typeof (pem), 'typeof pem');254255// chop off the BEGIN PUBLIC KEY and END PUBLIC KEY portion256var cleaned = pem.split('\n').slice(1, -2).join('');257258var buf = new Buffer(cleaned, 'base64');259260var der = new asn1.BerReader(buf);261262der.readSequence();263der.readSequence();264265var oid = der.readOID();266assert.equal(oid, '1.2.840.113549.1.1.1', 'pem not in RSA format');267268// Null -- XXX this probably isn't good practice269der.readByte();270der.readByte();271272// bit string sequence273der.readSequence(0x03);274der.readByte();275der.readSequence();276277// modulus278assert.equal(der.peek(), asn1.Ber.Integer, 'modulus not an integer');279der._offset = der.readLength(der.offset + 1);280var modulus = der._buf.slice(der.offset, der.offset + der.length);281der._offset += der.length;282283// exponent284assert.equal(der.peek(), asn1.Ber.Integer, 'exponent not an integer');285der._offset = der.readLength(der.offset + 1);286var exponent = der._buf.slice(der.offset, der.offset + der.length);287der._offset += der.length;288289// now, make the key290var type = new Buffer('ssh-rsa');291var buffer = new Buffer(4 + type.length + 4 + modulus.length +2924 + exponent.length);293var i = 0;294buffer.writeUInt32BE(type.length, i); i += 4;295type.copy(buffer, i); i += type.length;296buffer.writeUInt32BE(exponent.length, i); i += 4;297exponent.copy(buffer, i); i += exponent.length;298buffer.writeUInt32BE(modulus.length, i); i += 4;299modulus.copy(buffer, i); i += modulus.length;300301var s = (type.toString() + ' ' + buffer.toString('base64') + ' ' +302(comment || ''));303return s;304}305};306307308