Skip to content

Commit f6d36e7

Browse files
author
Alex Wilson
committed
TritonDataCenter#10 add support for rsa-sha2-256 signatures
Reviewed by: Brittany Wald <brittany.wald@joyent.com> Approved by: Brittany Wald <brittany.wald@joyent.com>
1 parent dfb19d8 commit f6d36e7

6 files changed

+85
-44
lines changed

lib/client.js

+22-19
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ Client.prototype.sign = function (key, data, opts, cb) {
125125
type: 'sign-request',
126126
publicKey: key.toBuffer('rfc4253'),
127127
data: data,
128-
flags: []
128+
flags: ['rsa-sha2-256']
129129
};
130130
var resps = ['failure', 'sign-response'];
131131

@@ -146,25 +146,28 @@ Client.prototype.sign = function (key, data, opts, cb) {
146146
key.type, 'ssh');
147147

148148
/* Emulate the openssh hash algorithm choice */
149-
switch (key.type) {
150-
case 'rsa':
151-
case 'dsa':
152-
sig.hashAlgorithm = 'sha1';
153-
break;
154-
case 'ecdsa':
155-
if (key.size <= 256)
156-
sig.hashAlgorithm = 'sha256';
157-
else if (key.size <= 384)
158-
sig.hashAlgorithm = 'sha384';
159-
else
149+
if (typeof (sig.hashAlgorithm) !== 'string') {
150+
switch (key.type) {
151+
case 'rsa':
152+
case 'dsa':
153+
sig.hashAlgorithm = 'sha1';
154+
break;
155+
case 'ecdsa':
156+
if (key.size <= 256)
157+
sig.hashAlgorithm = 'sha256';
158+
else if (key.size <= 384)
159+
sig.hashAlgorithm = 'sha384';
160+
else
161+
sig.hashAlgorithm = 'sha512';
162+
break;
163+
case 'ed25519':
160164
sig.hashAlgorithm = 'sha512';
161-
break;
162-
case 'ed25519':
163-
sig.hashAlgorithm = 'sha512';
164-
break;
165-
default:
166-
/* what */
167-
break;
165+
break;
166+
default:
167+
throw (new Error('Failed to ' +
168+
'determine hash algorithm in use ' +
169+
'with key type ' + key.type));
170+
}
168171
}
169172
} catch (e) {
170173
var err2 = new AgentProtocolError(resp,

lib/protocol.js

+8
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ var SignReqFlags = {
6666
var x = 0x0;
6767
if (v.indexOf('old-signature') !== -1)
6868
x |= 0x01;
69+
if (v.indexOf('rsa-sha2-256') !== -1)
70+
x |= 0x02;
71+
if (v.indexOf('rsa-sha2-512') !== -1)
72+
x |= 0x04;
6973
return (U32.encode(x, buf, offset));
7074
},
7175
decodeSize: U32.decodeSize,
@@ -74,6 +78,10 @@ var SignReqFlags = {
7478
var v = [];
7579
if ((r.value & 0x01) === 0x01)
7680
v.push('old-signature');
81+
if ((r.value & 0x02) === 0x02)
82+
v.push('rsa-sha2-256');
83+
if ((r.value & 0x04) === 0x04)
84+
v.push('rsa-sha2-512');
7785
r.value = v;
7886
return (r);
7987
}

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sshpk-agent",
3-
"version": "1.4.2",
3+
"version": "1.5.0",
44
"description": "ssh-agent client for use with sshpk",
55
"main": "lib/index.js",
66
"scripts": {
@@ -29,7 +29,7 @@
2929
"assert-plus": "^1.0.0",
3030
"mooremachine": "^2.0.1",
3131
"readable-stream": "^2.1.4",
32-
"sshpk": ">=1.9.1 < 1.11.0"
32+
"sshpk": ">=1.13.0 < 1.14.0"
3333
},
3434
"devDependencies": {
3535
"tape": "^3.5.0",

test/basic.test.js

+21-14
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ test('agent setup', function (t) {
4646
});
4747
});
4848

49+
var ver = Agent.getVersion();
50+
if (!ver.zero()) {
51+
console.log('using OpenSSH version ' + ver);
52+
}
53+
4954
test('Client takes path to socket in constructor', function (t) {
5055
var c = new sshpkAgent.Client({
5156
socketPath: agent.env['SSH_AUTH_SOCK']
@@ -221,9 +226,14 @@ test('Client can sign data with an rsa key', function (t) {
221226
t.ok(sig);
222227
t.ok(sig instanceof sshpk.Signature);
223228

224-
t.strictEqual(sig.hashAlgorithm, 'sha1');
229+
t.notStrictEqual(sig.hashAlgorithm, undefined);
230+
if (ver.gte(7, 0, 1)) {
231+
t.strictEqual(sig.hashAlgorithm, 'sha256');
232+
} else {
233+
t.strictEqual(sig.hashAlgorithm, 'sha1');
234+
}
225235

226-
var v = key.createVerify('sha1');
236+
var v = key.createVerify(sig.hashAlgorithm);
227237
v.update('foobar');
228238
t.ok(v.verify(sig));
229239

@@ -246,9 +256,9 @@ test('Client can sign data with an ecdsa key', function (t) {
246256
t.ok(sig);
247257
t.ok(sig instanceof sshpk.Signature);
248258

249-
t.strictEqual(sig.hashAlgorithm, 'sha384');
259+
t.notStrictEqual(sig.hashAlgorithm, undefined);
250260

251-
var v = key.createVerify('sha384');
261+
var v = key.createVerify(sig.hashAlgorithm);
252262
v.update('foobar');
253263
t.ok(v.verify(sig));
254264

@@ -258,13 +268,8 @@ test('Client can sign data with an ecdsa key', function (t) {
258268
});
259269

260270
var usedEd = false;
261-
var ver = Agent.getVersion();
262-
if (ver === undefined)
263-
ver = [0, 0, 0];
264-
else
265-
console.log('using OpenSSH version %d.%dp%d', ver[0], ver[1], ver[2]);
266271

267-
if (ver >= [6, 5, 1]) {
272+
if (ver.gte(6, 5, 1)) {
268273
usedEd = true;
269274
test('Client can sign data with an ed25519 key', function (t) {
270275
var c = new sshpkAgent.Client();
@@ -282,9 +287,11 @@ if (ver >= [6, 5, 1]) {
282287
t.ok(sig);
283288
t.ok(sig instanceof sshpk.Signature);
284289

285-
t.strictEqual(sig.hashAlgorithm, 'sha512');
290+
t.notStrictEqual(sig.hashAlgorithm,
291+
undefined);
286292

287-
var v = key.createVerify('sha512');
293+
var v = key.createVerify(
294+
sig.hashAlgorithm);
288295
v.update('foobar');
289296
t.ok(v.verify(sig));
290297

@@ -314,9 +321,9 @@ test('Client can sign data with a dsa key', function (t) {
314321
t.ok(sig);
315322
t.ok(sig instanceof sshpk.Signature);
316323

317-
t.strictEqual(sig.hashAlgorithm, 'sha1');
324+
t.notStrictEqual(sig.hashAlgorithm, undefined);
318325

319-
var v = key.createVerify('sha1');
326+
var v = key.createVerify(sig.hashAlgorithm);
320327
v.update('foobar');
321328
t.ok(v.verify(sig));
322329

test/key-mgmt.test.js

+6-7
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ test('Client can add an RSA certificate', function (t) {
125125
});
126126
});
127127

128+
var ver = Agent.getVersion();
129+
if (!ver.zero()) {
130+
console.log('using OpenSSH version ' + ver);
131+
}
132+
128133
test('Client can add an ECDSA certificate', function (t) {
129134
var pem = fs.readFileSync(path.join(testDir, 'id_ecdsa'));
130135
var pk = sshpk.parsePrivateKey(pem, 'pem', 'test/id_ecdsa');
@@ -152,13 +157,7 @@ test('Client can add an ECDSA certificate', function (t) {
152157
});
153158
});
154159

155-
var ver = Agent.getVersion();
156-
if (ver === undefined)
157-
ver = [0, 0, 0];
158-
else
159-
console.log('using OpenSSH version %d.%dp%d', ver[0], ver[1], ver[2]);
160-
161-
if (ver >= [6, 5, 1]) {
160+
if (ver.gte(6, 5, 1)) {
162161
test('Client can add an ED25519 certificate', function (t) {
163162
var pem = fs.readFileSync(path.join(testDir, 'id_ed25519'));
164163
var pk = sshpk.parsePrivateKey(pem, 'pem', 'test/id_ed25519');

test/ssh-agent-ctl.js

+26-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,29 @@ function Agent(opts) {
1818
}
1919
util.inherits(Agent, EventEmitter);
2020

21+
function SSHVersion(maj, min, patch) {
22+
this.major = maj;
23+
this.minor = min;
24+
this.patch = patch;
25+
}
26+
SSHVersion.prototype.gte = function (maj, min, patch) {
27+
var v;
28+
if (maj instanceof SSHVersion)
29+
v = maj;
30+
else
31+
v = new SSHVersion(maj, min, patch);
32+
33+
return (this.major > v.major ||
34+
(this.major == v.major && (this.minor > v.minor ||
35+
(this.minor == v.minor && this.patch >= v.patch))));
36+
};
37+
SSHVersion.prototype.zero = function () {
38+
return (this.major == 0 && this.minor == 0 && this.patch == 0);
39+
};
40+
SSHVersion.prototype.toString = function () {
41+
return (this.major + '.' + this.minor + 'p' + this.patch);
42+
};
43+
2144
Agent.getVersion = function () {
2245
if (typeof (spawnSync) !== 'function')
2346
return (undefined);
@@ -29,9 +52,10 @@ Agent.getVersion = function () {
2952
var m = out.trim().match(/^OpenSSH_([0-9]+)\.([0-9]+)p([0-9]+)[, ]|$/);
3053
if (!m) {
3154
console.error('ssh -V: %s', out);
32-
return (undefined);
55+
return (new SSHVersion(0, 0, 0));
3356
}
34-
return ([parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10)]);
57+
return (new SSHVersion(parseInt(m[1], 10), parseInt(m[2], 10),
58+
parseInt(m[3], 10)));
3559
};
3660

3761
Agent.prototype.open = function () {

0 commit comments

Comments
 (0)