'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; };