[6a3a178] | 1 | // Copyright 2012 Joyent, Inc. All rights reserved.
|
---|
| 2 |
|
---|
| 3 | var assert = require('assert-plus');
|
---|
| 4 | var sshpk = require('sshpk');
|
---|
| 5 | var util = require('util');
|
---|
| 6 |
|
---|
| 7 | var HASH_ALGOS = {
|
---|
| 8 | 'sha1': true,
|
---|
| 9 | 'sha256': true,
|
---|
| 10 | 'sha512': true
|
---|
| 11 | };
|
---|
| 12 |
|
---|
| 13 | var PK_ALGOS = {
|
---|
| 14 | 'rsa': true,
|
---|
| 15 | 'dsa': true,
|
---|
| 16 | 'ecdsa': true
|
---|
| 17 | };
|
---|
| 18 |
|
---|
| 19 | function HttpSignatureError(message, caller) {
|
---|
| 20 | if (Error.captureStackTrace)
|
---|
| 21 | Error.captureStackTrace(this, caller || HttpSignatureError);
|
---|
| 22 |
|
---|
| 23 | this.message = message;
|
---|
| 24 | this.name = caller.name;
|
---|
| 25 | }
|
---|
| 26 | util.inherits(HttpSignatureError, Error);
|
---|
| 27 |
|
---|
| 28 | function InvalidAlgorithmError(message) {
|
---|
| 29 | HttpSignatureError.call(this, message, InvalidAlgorithmError);
|
---|
| 30 | }
|
---|
| 31 | util.inherits(InvalidAlgorithmError, HttpSignatureError);
|
---|
| 32 |
|
---|
| 33 | function validateAlgorithm(algorithm) {
|
---|
| 34 | var alg = algorithm.toLowerCase().split('-');
|
---|
| 35 |
|
---|
| 36 | if (alg.length !== 2) {
|
---|
| 37 | throw (new InvalidAlgorithmError(alg[0].toUpperCase() + ' is not a ' +
|
---|
| 38 | 'valid algorithm'));
|
---|
| 39 | }
|
---|
| 40 |
|
---|
| 41 | if (alg[0] !== 'hmac' && !PK_ALGOS[alg[0]]) {
|
---|
| 42 | throw (new InvalidAlgorithmError(alg[0].toUpperCase() + ' type keys ' +
|
---|
| 43 | 'are not supported'));
|
---|
| 44 | }
|
---|
| 45 |
|
---|
| 46 | if (!HASH_ALGOS[alg[1]]) {
|
---|
| 47 | throw (new InvalidAlgorithmError(alg[1].toUpperCase() + ' is not a ' +
|
---|
| 48 | 'supported hash algorithm'));
|
---|
| 49 | }
|
---|
| 50 |
|
---|
| 51 | return (alg);
|
---|
| 52 | }
|
---|
| 53 |
|
---|
| 54 | ///--- API
|
---|
| 55 |
|
---|
| 56 | module.exports = {
|
---|
| 57 |
|
---|
| 58 | HASH_ALGOS: HASH_ALGOS,
|
---|
| 59 | PK_ALGOS: PK_ALGOS,
|
---|
| 60 |
|
---|
| 61 | HttpSignatureError: HttpSignatureError,
|
---|
| 62 | InvalidAlgorithmError: InvalidAlgorithmError,
|
---|
| 63 |
|
---|
| 64 | validateAlgorithm: validateAlgorithm,
|
---|
| 65 |
|
---|
| 66 | /**
|
---|
| 67 | * Converts an OpenSSH public key (rsa only) to a PKCS#8 PEM file.
|
---|
| 68 | *
|
---|
| 69 | * The intent of this module is to interoperate with OpenSSL only,
|
---|
| 70 | * specifically the node crypto module's `verify` method.
|
---|
| 71 | *
|
---|
| 72 | * @param {String} key an OpenSSH public key.
|
---|
| 73 | * @return {String} PEM encoded form of the RSA public key.
|
---|
| 74 | * @throws {TypeError} on bad input.
|
---|
| 75 | * @throws {Error} on invalid ssh key formatted data.
|
---|
| 76 | */
|
---|
| 77 | sshKeyToPEM: function sshKeyToPEM(key) {
|
---|
| 78 | assert.string(key, 'ssh_key');
|
---|
| 79 |
|
---|
| 80 | var k = sshpk.parseKey(key, 'ssh');
|
---|
| 81 | return (k.toString('pem'));
|
---|
| 82 | },
|
---|
| 83 |
|
---|
| 84 |
|
---|
| 85 | /**
|
---|
| 86 | * Generates an OpenSSH fingerprint from an ssh public key.
|
---|
| 87 | *
|
---|
| 88 | * @param {String} key an OpenSSH public key.
|
---|
| 89 | * @return {String} key fingerprint.
|
---|
| 90 | * @throws {TypeError} on bad input.
|
---|
| 91 | * @throws {Error} if what you passed doesn't look like an ssh public key.
|
---|
| 92 | */
|
---|
| 93 | fingerprint: function fingerprint(key) {
|
---|
| 94 | assert.string(key, 'ssh_key');
|
---|
| 95 |
|
---|
| 96 | var k = sshpk.parseKey(key, 'ssh');
|
---|
| 97 | return (k.fingerprint('md5').toString('hex'));
|
---|
| 98 | },
|
---|
| 99 |
|
---|
| 100 | /**
|
---|
| 101 | * Converts a PKGCS#8 PEM file to an OpenSSH public key (rsa)
|
---|
| 102 | *
|
---|
| 103 | * The reverse of the above function.
|
---|
| 104 | */
|
---|
| 105 | pemToRsaSSHKey: function pemToRsaSSHKey(pem, comment) {
|
---|
| 106 | assert.equal('string', typeof (pem), 'typeof pem');
|
---|
| 107 |
|
---|
| 108 | var k = sshpk.parseKey(pem, 'pem');
|
---|
| 109 | k.comment = comment;
|
---|
| 110 | return (k.toString('ssh'));
|
---|
| 111 | }
|
---|
| 112 | };
|
---|