diff --git a/lib/certificate.js b/lib/certificate.js index 49514b5..4fbe6ab 100644 --- a/lib/certificate.js +++ b/lib/certificate.js @@ -128,10 +128,19 @@ Certificate.prototype.isSignedByKey = function (issuerKey) { }; Certificate.prototype.signWith = function (key) { + utils.assertCompatible(key, PrivateKey, [1, 2], 'key'); var fmts = Object.keys(formats); + var didOne = false; for (var i = 0; i < fmts.length; ++i) { - if (fmts[i] !== 'pem') - formats[fmts[i]].sign(this, key); + if (fmts[i] !== 'pem') { + var ret = formats[fmts[i]].sign(this, key); + if (ret === true) + didOne = true; + } + } + if (!didOne) { + throw (new Error('Failed to sign the certificate for any ' + + 'available certificate formats')); } }; diff --git a/lib/formats/openssh-cert.js b/lib/formats/openssh-cert.js index a8cfb75..8ce7350 100644 --- a/lib/formats/openssh-cert.js +++ b/lib/formats/openssh-cert.js @@ -58,6 +58,8 @@ function fromBuffer(data, algo, partial) { var innerAlgo = sshbuf.readString(); if (algo !== undefined && innerAlgo !== algo) throw (new Error('SSH certificate algorithm mismatch')); + if (algo === undefined) + algo = innerAlgo; var cert = {}; cert.signatures = {}; @@ -168,15 +170,22 @@ function dateToInt64(date) { } function sign(cert, key) { - assert.ok(PrivateKey.isPrivateKey(key, [1, 2])); if (cert.signatures.openssh === undefined) cert.signatures.openssh = {}; + try { + var blob = toBuffer(cert, true); + } catch (e) { + delete (cert.signatures.openssh); + return (false); + } var sig = cert.signatures.openssh; - - var blob = toBuffer(cert, true); - var signer = key.createSign(); + var hashAlgo = undefined; + if (key.type === 'rsa' || key.type === 'dsa') + hashAlgo = 'sha1'; + var signer = key.createSign(hashAlgo); signer.write(blob); sig.signature = signer.sign(); + return (true); } function write(cert, options) { @@ -262,6 +271,8 @@ function getAlg(certType) { return ('dsa'); if (certType.match(ECDSA_ALGO)) return ('ecdsa'); + if (certType === 'ssh-ed25519-cert-v01@openssh.com') + return ('ed25519'); throw (new Error('Unsupported cert type ' + certType)); } @@ -272,5 +283,7 @@ function getCertType(key) { return ('ssh-dss-cert-v01@openssh.com'); if (key.type === 'ecdsa') return ('ecdsa-sha2-' + key.curve + '-cert-v01@openssh.com'); + if (key.type === 'ed25519') + return ('ssh-ed25519-cert-v01@openssh.com'); throw (new Error('Unsupported key type ' + key.type)); } diff --git a/lib/formats/x509.js b/lib/formats/x509.js index 6e9b1f5..34f70b8 100644 --- a/lib/formats/x509.js +++ b/lib/formats/x509.js @@ -338,7 +338,8 @@ function sign(cert, key) { var sig = cert.signatures.x509; sig.algo = key.type + '-' + key.defaultHashAlgorithm(); - assert.string(SIGN_ALGS[sig.algo]); + if (SIGN_ALGS[sig.algo] === undefined) + return (false); var der = new asn1.BerWriter(); writeTBSCert(cert, der); @@ -348,6 +349,8 @@ function sign(cert, key) { var signer = key.createSign(); signer.write(blob); cert.signatures.x509.signature = signer.sign(); + + return (true); } function write(cert, options) { diff --git a/package.json b/package.json index eebac23..98f3d6e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sshpk", - "version": "1.9.0", + "version": "1.9.1", "description": "A library for finding and using SSH public keys", "main": "lib/index.js", "scripts": { diff --git a/test/certs.js b/test/certs.js index 16bca48..e3e479f 100644 --- a/test/certs.js +++ b/test/certs.js @@ -14,6 +14,7 @@ var GEORGE_KEY, GEORGE_SSH, GEORGE_X509; var BARRY_KEY; var JIM_KEY, JIM_SSH, JIM_X509; var EC_KEY, EC_KEY2; +var SUE_KEY; test('setup', function (t) { var d = fs.readFileSync(path.join(testDir, 'id_dsa')); @@ -34,6 +35,10 @@ test('setup', function (t) { EC_KEY = sshpk.parsePrivateKey(d); d = fs.readFileSync(path.join(testDir, 'id_ecdsa2')); EC2_KEY = sshpk.parsePrivateKey(d); + + d = fs.readFileSync(path.join(testDir, 'id_ed25519')); + SUE_KEY = sshpk.parsePrivateKey(d); + t.end(); }); @@ -169,6 +174,26 @@ test('create ecdsa signed, loopback', function (t) { t.end(); }); +test('create ed25519 self-signed, loopback', function (t) { + var id = sshpk.identityForHost('foobar.com'); + var cert = sshpk.createSelfSignedCertificate(id, SUE_KEY); + + t.throws(function () { + cert.toBuffer('pem'); + }); + t.throws(function () { + cert.toBuffer('x509'); + }); + + var ossh = cert.toBuffer('openssh'); + var cert3 = sshpk.parseCertificate(ossh, 'openssh'); + t.ok(SUE_KEY.fingerprint().matches(cert3.subjectKey)); + t.ok(cert3.subjects[0].equals(cert.subjects[0])); + t.strictEqual(cert3.subjects[0].hostname, 'foobar.com'); + + t.end(); +}); + test('subjectaltname', function (t) { var ids = [ sshpk.identityForHost('foobar.com'),