77 lines
1.7 KiB
JavaScript
77 lines
1.7 KiB
JavaScript
'use strict';
|
|
|
|
var Enc = require('./encoding.js');
|
|
var SSH = module.exports;
|
|
|
|
SSH.pack = function (opts) {
|
|
var jwk = opts.jwk;
|
|
var els = [];
|
|
var ssh = {
|
|
type: ''
|
|
, _elements: els
|
|
, comment: opts.comment || ''
|
|
};
|
|
var len;
|
|
|
|
if ("RSA" === jwk.kty) {
|
|
ssh.type = 'ssh-rsa';
|
|
els.push(Enc.binToHex(ssh.type));
|
|
els.push(SSH._padRsa(Enc.base64ToHex(jwk.e)));
|
|
els.push(SSH._padRsa(Enc.base64ToHex(jwk.n)));
|
|
return SSH._packElements(ssh);
|
|
}
|
|
|
|
if ("P-256" === jwk.crv) {
|
|
ssh.type = 'ecdsa-sha2-nistp256';
|
|
els.push(Enc.binToHex(ssh.type));
|
|
els.push(Enc.binToHex('nistp256'));
|
|
len = 32;
|
|
} else if ("P-384" === jwk.crv) {
|
|
ssh.type = 'ecdsa-sha2-nistp384';
|
|
els.push(Enc.binToHex(ssh.type));
|
|
els.push(Enc.binToHex('nistp384'));
|
|
len = 48;
|
|
} else {
|
|
throw new Error("unknown key type " + (jwk.crv || jwk.kty));
|
|
}
|
|
|
|
els.push('04'
|
|
+ SSH._padEc(Enc.base64ToHex(jwk.x), len)
|
|
+ SSH._padEc(Enc.base64ToHex(jwk.y), len)
|
|
);
|
|
return SSH._packElements(ssh);
|
|
};
|
|
|
|
SSH._packElements = function (ssh) {
|
|
var hex = ssh._elements.map(function (hex) {
|
|
return SSH._numToUint32Hex(hex.length/2) + hex;
|
|
}).join('');
|
|
return [ ssh.type, Enc.hexToBase64(hex), ssh.comment ].join(' ');
|
|
};
|
|
|
|
SSH._numToUint32Hex = function (num) {
|
|
var hex = num.toString(16);
|
|
while (hex.length < 8) {
|
|
hex = '0' + hex;
|
|
}
|
|
return hex;
|
|
};
|
|
|
|
SSH._padRsa = function (hex) {
|
|
// BigInt is negative if the high order bit 0x80 is set,
|
|
// so ASN1, SSH, and many other formats pad with '0x00'
|
|
// to signifiy a positive number.
|
|
var i = parseInt(hex.slice(0, 2), 16);
|
|
if (0x80 & i) {
|
|
return '00' + hex;
|
|
}
|
|
return hex;
|
|
};
|
|
|
|
SSH._padEc = function (hex, len) {
|
|
while (hex.length < len * 2) {
|
|
hex = '00' + hex;
|
|
}
|
|
return hex;
|
|
};
|