diff --git a/lib/ssh-packer.js b/lib/ssh-packer.js index 961350a..5c4d7c3 100644 --- a/lib/ssh-packer.js +++ b/lib/ssh-packer.js @@ -66,17 +66,17 @@ SSH._packKey = function (opts) { els.push(Enc.binToHex('ssh-rsa')); if (jwk.d) { // unswap n and e for private key format - els.push(SSH._padRsa(Enc.base64ToHex(jwk.n))); - els.push(SSH._padRsa(Enc.base64ToHex(jwk.e))); - els.push(SSH._padRsa(Enc.base64ToHex(jwk.d))); - els.push(SSH._padRsa(Enc.base64ToHex(jwk.qi))); - els.push(SSH._padRsa(Enc.base64ToHex(jwk.p))); - els.push(SSH._padRsa(Enc.base64ToHex(jwk.q))); + els.push(SSH._padBigInt(Enc.base64ToHex(jwk.n))); + els.push(SSH._padBigInt(Enc.base64ToHex(jwk.e))); + els.push(SSH._padBigInt(Enc.base64ToHex(jwk.d))); + els.push(SSH._padBigInt(Enc.base64ToHex(jwk.qi))); + els.push(SSH._padBigInt(Enc.base64ToHex(jwk.p))); + els.push(SSH._padBigInt(Enc.base64ToHex(jwk.q))); els.push(Enc.binToHex(opts.comment || '')); } else { // swap n and e for public key format - els.push(SSH._padRsa(Enc.base64ToHex(jwk.e))); - els.push(SSH._padRsa(Enc.base64ToHex(jwk.n))); + els.push(SSH._padBigInt(Enc.base64ToHex(jwk.e))); + els.push(SSH._padBigInt(Enc.base64ToHex(jwk.n))); } return els; } @@ -94,11 +94,16 @@ SSH._packKey = function (opts) { } els.push('04' - + SSH._padEc(Enc.base64ToHex(jwk.x), len) - + SSH._padEc(Enc.base64ToHex(jwk.y), len) + + SSH._padBytes(Enc.base64ToHex(jwk.x), len) + + SSH._padBytes(Enc.base64ToHex(jwk.y), len) ); if (jwk.d) { - els.push(SSH._padEc(Enc.base64ToHex(jwk.d), len)); + // I was able to empirically confirm that the leading 00 is expected for + // ambiguous BigInt negatives (0x80 set), and that the length can dip down + // to 31 bytes when the leading byte is 0x00. I suspect that if I had tried + // 65k iterations that I'd have seen at least one 30 byte number + els.push(SSH._padBigInt(Enc.base64ToHex(jwk.d))); + //console.warn('els:', els[els.length - 1]); els.push(Enc.binToHex(opts.comment || '')); } @@ -119,18 +124,20 @@ SSH._numToUint32Hex = function (num) { return hex; }; -SSH._padRsa = function (hex) { +SSH._padBigInt = 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); + //console.warn('l', hex.length/2, 'i', i); if (0x80 & i) { + //console.warn('0x80 true'); return '00' + hex; } return hex; }; -SSH._padEc = function (hex, len) { +SSH._padBytes = function (hex, len) { while (hex.length < len * 2) { hex = '00' + hex; }