summaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/http-signature/lib/util.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/node_modules/http-signature/lib/util.js')
-rw-r--r--deps/npm/node_modules/http-signature/lib/util.js306
1 files changed, 306 insertions, 0 deletions
diff --git a/deps/npm/node_modules/http-signature/lib/util.js b/deps/npm/node_modules/http-signature/lib/util.js
new file mode 100644
index 0000000000..2e1ce4d468
--- /dev/null
+++ b/deps/npm/node_modules/http-signature/lib/util.js
@@ -0,0 +1,306 @@
+// Copyright 2012 Joyent, Inc. All rights reserved.
+
+var assert = require('assert-plus');
+var crypto = require('crypto');
+
+var asn1 = require('asn1');
+var ctype = require('ctype');
+
+
+
+///--- Helpers
+
+function readNext(buffer, offset) {
+ var len = ctype.ruint32(buffer, 'big', offset);
+ offset += 4;
+
+ var newOffset = offset + len;
+
+ return {
+ data: buffer.slice(offset, newOffset),
+ offset: newOffset
+ };
+}
+
+
+function writeInt(writer, buffer) {
+ writer.writeByte(0x02); // ASN1.Integer
+ writer.writeLength(buffer.length);
+
+ for (var i = 0; i < buffer.length; i++)
+ writer.writeByte(buffer[i]);
+
+ return writer;
+}
+
+
+function rsaToPEM(key) {
+ var buffer;
+ var der;
+ var exponent;
+ var i;
+ var modulus;
+ var newKey = '';
+ var offset = 0;
+ var type;
+ var tmp;
+
+ try {
+ buffer = new Buffer(key.split(' ')[1], 'base64');
+
+ tmp = readNext(buffer, offset);
+ type = tmp.data.toString();
+ offset = tmp.offset;
+
+ if (type !== 'ssh-rsa')
+ throw new Error('Invalid ssh key type: ' + type);
+
+ tmp = readNext(buffer, offset);
+ exponent = tmp.data;
+ offset = tmp.offset;
+
+ tmp = readNext(buffer, offset);
+ modulus = tmp.data;
+ } catch (e) {
+ throw new Error('Invalid ssh key: ' + key);
+ }
+
+ // DER is a subset of BER
+ der = new asn1.BerWriter();
+
+ der.startSequence();
+
+ der.startSequence();
+ der.writeOID('1.2.840.113549.1.1.1');
+ der.writeNull();
+ der.endSequence();
+
+ der.startSequence(0x03); // bit string
+ der.writeByte(0x00);
+
+ // Actual key
+ der.startSequence();
+ writeInt(der, modulus);
+ writeInt(der, exponent);
+ der.endSequence();
+
+ // bit string
+ der.endSequence();
+
+ der.endSequence();
+
+ tmp = der.buffer.toString('base64');
+ for (i = 0; i < tmp.length; i++) {
+ if ((i % 64) === 0)
+ newKey += '\n';
+ newKey += tmp.charAt(i);
+ }
+
+ if (!/\\n$/.test(newKey))
+ newKey += '\n';
+
+ return '-----BEGIN PUBLIC KEY-----' + newKey + '-----END PUBLIC KEY-----\n';
+}
+
+
+function dsaToPEM(key) {
+ var buffer;
+ var offset = 0;
+ var tmp;
+ var der;
+ var newKey = '';
+
+ var type;
+ var p;
+ var q;
+ var g;
+ var y;
+
+ try {
+ buffer = new Buffer(key.split(' ')[1], 'base64');
+
+ tmp = readNext(buffer, offset);
+ type = tmp.data.toString();
+ offset = tmp.offset;
+
+ /* JSSTYLED */
+ if (!/^ssh-ds[as].*/.test(type))
+ throw new Error('Invalid ssh key type: ' + type);
+
+ tmp = readNext(buffer, offset);
+ p = tmp.data;
+ offset = tmp.offset;
+
+ tmp = readNext(buffer, offset);
+ q = tmp.data;
+ offset = tmp.offset;
+
+ tmp = readNext(buffer, offset);
+ g = tmp.data;
+ offset = tmp.offset;
+
+ tmp = readNext(buffer, offset);
+ y = tmp.data;
+ } catch (e) {
+ console.log(e.stack);
+ throw new Error('Invalid ssh key: ' + key);
+ }
+
+ // DER is a subset of BER
+ der = new asn1.BerWriter();
+
+ der.startSequence();
+
+ der.startSequence();
+ der.writeOID('1.2.840.10040.4.1');
+
+ der.startSequence();
+ writeInt(der, p);
+ writeInt(der, q);
+ writeInt(der, g);
+ der.endSequence();
+
+ der.endSequence();
+
+ der.startSequence(0x03); // bit string
+ der.writeByte(0x00);
+ writeInt(der, y);
+ der.endSequence();
+
+ der.endSequence();
+
+ tmp = der.buffer.toString('base64');
+ for (var i = 0; i < tmp.length; i++) {
+ if ((i % 64) === 0)
+ newKey += '\n';
+ newKey += tmp.charAt(i);
+ }
+
+ if (!/\\n$/.test(newKey))
+ newKey += '\n';
+
+ return '-----BEGIN PUBLIC KEY-----' + newKey + '-----END PUBLIC KEY-----\n';
+}
+
+
+///--- API
+
+module.exports = {
+
+ /**
+ * Converts an OpenSSH public key (rsa only) to a PKCS#8 PEM file.
+ *
+ * The intent of this module is to interoperate with OpenSSL only,
+ * specifically the node crypto module's `verify` method.
+ *
+ * @param {String} key an OpenSSH public key.
+ * @return {String} PEM encoded form of the RSA public key.
+ * @throws {TypeError} on bad input.
+ * @throws {Error} on invalid ssh key formatted data.
+ */
+ sshKeyToPEM: function sshKeyToPEM(key) {
+ assert.string(key, 'ssh_key');
+
+ /* JSSTYLED */
+ if (/^ssh-rsa.*/.test(key))
+ return rsaToPEM(key);
+
+ /* JSSTYLED */
+ if (/^ssh-ds[as].*/.test(key))
+ return dsaToPEM(key);
+
+ throw new Error('Only RSA and DSA public keys are allowed');
+ },
+
+
+ /**
+ * Generates an OpenSSH fingerprint from an ssh public key.
+ *
+ * @param {String} key an OpenSSH public key.
+ * @return {String} key fingerprint.
+ * @throws {TypeError} on bad input.
+ * @throws {Error} if what you passed doesn't look like an ssh public key.
+ */
+ fingerprint: function fingerprint(key) {
+ assert.string(key, 'ssh_key');
+
+ var pieces = key.split(' ');
+ if (!pieces || !pieces.length || pieces.length < 2)
+ throw new Error('invalid ssh key');
+
+ var data = new Buffer(pieces[1], 'base64');
+
+ var hash = crypto.createHash('md5');
+ hash.update(data);
+ var digest = hash.digest('hex');
+
+ var fp = '';
+ for (var i = 0; i < digest.length; i++) {
+ if (i && i % 2 === 0)
+ fp += ':';
+
+ fp += digest[i];
+ }
+
+ return fp;
+ },
+
+ /**
+ * Converts a PKGCS#8 PEM file to an OpenSSH public key (rsa)
+ *
+ * The reverse of the above function.
+ */
+ pemToRsaSSHKey: function pemToRsaSSHKey(pem, comment) {
+ assert.equal('string', typeof (pem), 'typeof pem');
+
+ // chop off the BEGIN PUBLIC KEY and END PUBLIC KEY portion
+ var cleaned = pem.split('\n').slice(1, -2).join('');
+
+ var buf = new Buffer(cleaned, 'base64');
+
+ var der = new asn1.BerReader(buf);
+
+ der.readSequence();
+ der.readSequence();
+
+ var oid = der.readOID();
+ assert.equal(oid, '1.2.840.113549.1.1.1', 'pem not in RSA format');
+
+ // Null -- XXX this probably isn't good practice
+ der.readByte();
+ der.readByte();
+
+ // bit string sequence
+ der.readSequence(0x03);
+ der.readByte();
+ der.readSequence();
+
+ // modulus
+ assert.equal(der.peek(), asn1.Ber.Integer, 'modulus not an integer');
+ der._offset = der.readLength(der.offset + 1);
+ var modulus = der._buf.slice(der.offset, der.offset + der.length);
+ der._offset += der.length;
+
+ // exponent
+ assert.equal(der.peek(), asn1.Ber.Integer, 'exponent not an integer');
+ der._offset = der.readLength(der.offset + 1);
+ var exponent = der._buf.slice(der.offset, der.offset + der.length);
+ der._offset += der.length;
+
+ // now, make the key
+ var type = new Buffer('ssh-rsa');
+ var buffer = new Buffer(4 + type.length + 4 + modulus.length +
+ 4 + exponent.length);
+ var i = 0;
+ buffer.writeUInt32BE(type.length, i); i += 4;
+ type.copy(buffer, i); i += type.length;
+ buffer.writeUInt32BE(exponent.length, i); i += 4;
+ exponent.copy(buffer, i); i += exponent.length;
+ buffer.writeUInt32BE(modulus.length, i); i += 4;
+ modulus.copy(buffer, i); i += modulus.length;
+
+ var s = (type.toString() + ' ' + buffer.toString('base64') + ' ' +
+ (comment || ''));
+ return s;
+ }
+};