4

I have been trying to generate a RSA key pair to on an AWS Lambda in order to replace the current manual generation of keys on PuTTYgen. The key generated on PuTTYgen is of RSA type with a length of 2048 which results in a sample key (without comment) as follows -

---- BEGIN SSH2 PUBLIC KEY ---- 
Comment: "" 
AAAAB3NzaC1yc2EAAAABJQAAAQEAjloNCA4mycem+WTb49zUhYK7aRmg1uuorUvD
7GzE97C9EmmhUrVbp4d5dWF8zkT2sh5mRFrAnsSogxEtCzvh59mzbqUj+3Xw+xqJ
DMrHmnT8XKIGep++v3e+SV7RLio06ymp0H7zyHhbxLhZEnpGEKwkXmY53+RSUF7s
wfmvxS5mCo7677lbIZxGvvx65tT5as5m+ng7tKlqDAliuPl2vslyFhQw9B49cvOx
Z+UekK2iHD+DNCMQyxEelOru9YMwRozOwgtWPEyHcLinonAn2fUne28POsT3zXbv
rW10hkGH5JIHzGUoPxP6N7RRCnSN/NgS8rrHs51Skvhl0WzV6w==
---- END SSH2 PUBLIC KEY ----

Now I have been trying to replicate the same on a NodeJS lambda with the following code -

const generation = util.promisify(crypto.generateKeyPair);
    const result = await generation('rsa',{ 
        modulusLength: 2048,
        publicKeyEncoding: { 
            type: 'spki',
            format: 'pem'
        }, 
        privateKeyEncoding: { 
            type: 'pkcs8',
            format: 'pem',
        } 
    });
    console.log(result['publicKey']);
    console.log(result['privateKey']);

On execution of this lambda, the generated public key looks something like this -

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnF1VDHq0vu5iL0nkbum8
cVzdhxiqmR6XcZbcsilF+Se6tlS9VAbN8QTTLdqwhJ5Dw7DvBGUXpCqUIqyT5IU5
wjQGnWHAWhPmalAgYWDwwdiOxxgd6NnNRR2Q5P4PSruxvFG7BtiSKGXSZpMzTIyZ
sXajEY2vhkf77bMEgzJhpXGAvzZsGEDi9jni8FCabVH6jvXh/svpmoCxwhQY1HHh
9RksscuAfllMwOE4uiQvfq6CpPNJUwU4kWtiaAtgX26nnPvqaUX52xMuYBrWQI2m
vUiXuxynqnrVSAFt/QY/0lMKRgnzwkq6YTIf8PeMQQA6TVQbtGN+j0MFQJDxF2/l
dQIDAQAB
-----END PUBLIC KEY-----

As far as I understand about RSA keys, the first and the last line should not make any difference since they are basically comments. But I see that the PuTTYgen key consists of about 5 and 1/2 lines of content whereas the NodeJS key has 6+ lines of content. Why is there a difference between the two when both of them have a length of 2048?

Thank you.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • 1
    See [How can I transform between the two styles of public key format, one “BEGIN RSA PUBLIC KEY”, the other is “BEGIN PUBLIC KEY”](https://stackoverflow.com/q/18039401/850848#29707204). – Martin Prikryl Jul 03 '20 at 06:44
  • 1
    *...the first and the last line should not make any difference since they are basically comments...* Yes, but they do tell you something about the format of the key. Unfortunately there are many RSA formats out there, tailored for specific purposes. The first one is specific to SSH, then second one is more generally accepted but both contain essentially the same information. – President James K. Polk Jul 03 '20 at 12:34
  • 2
    Does this answer your question? [RSA Public Key format](https://stackoverflow.com/questions/12749858/rsa-public-key-format) – President James K. Polk Jul 03 '20 at 12:37
  • I have taken a look at both the links and I think I understand the premise of the different RSA formats. I found a module - 'sshpk' which should help to convert my key to the required format. Will share the code if successful, thanks for the help. –  Jul 03 '20 at 14:17

1 Answers1

1

Thanks for the comments, helped me understand the formats of the keys better. The key generated with the use of the NodeJS code was of PEM format which would need to be converted to OpenSSH format to match the output key from PuTTYgen.

The module sshpk helps in converting the PEM key to a OpenSSH format. The code to do that is as follows -

var sshpk = require('sshpk');
let pemPublicKey = sshpk.parseKey(publicKey, 'pem');
let openSSHPublicKey = pemPublicKey.toString('ssh');
console.log(openSSHPublicKey);

This would result in a key with the following format -

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqWWfYMm/q1Ee4AzRJMc+BgsqzVIZgwTidGDb6E3V2EQ85+iX09pmDF8E23Fsmd9WoUMB2L/FXUIlWZmofPmoInKk740UcsQGT0MVYQfDAiVBqrbymIR/lMBCirFpFq7hIDzACgWYAmSEFtDBdP4LmFozx6Vi3+Ss5g8EjkXcDLkPiBSM8YjCQO6CraH1dMIC4/hywitL1G2rngFdwgFAuG1HEqgXZKRZAm2043OVY2SDVnMvHcYjarPk94BydZ7mzZRCdaetDY73+8opVL0uRol2GfYwAoediz65iIm183w4p4F3JH09W4xSoT8FeTRfIc2iAlde3wFA6aK/NV0G5 (unnamed)

The (unnamed) at the end can be removed by adding a name when you are using the parseKey() method.

Now, you could format this string as per your requirements as follows -

let openSSHPublicKeyMaterial = openSSHPublicKey.split(" ")[1];
let formattedSSH2KeyArray = []
formattedSSH2KeyArray.push('---- BEGIN SSH2 PUBLIC KEY ----');
formattedSSH2KeyArray.push('Comment: ""');
    
for (let index = 0; index <= openSSHPublicKeyMaterial.length; index += 64 ) { // 64 corresponds to the number of characters in a single line
    let singleLine = openSSHPublicKeyMaterial.substring(index, index + 64);
    formattedSSH2KeyArray.push(singleLine);
}
    
formattedSSH2KeyArray.push('---- END SSH2 PUBLIC KEY ----');
let formattedSSH2Key = formattedSSH2KeyArray.join('\n');
console.log(formattedSSH2Key);

The execution of the above section would give you the key in the required format -

---- BEGIN SSH2 PUBLIC KEY ----
Comment: ""
AAAAB3NzaC1yc2EAAAADAQABAAABAQCqWWfYMm/q1Ee4AzRJMc+BgsqzVIZgwTid
GDb6E3V2EQ85+iX09pmDF8E23Fsmd9WoUMB2L/FXUIlWZmofPmoInKk740UcsQGT
0MVYQfDAiVBqrbymIR/lMBCirFpFq7hIDzACgWYAmSEFtDBdP4LmFozx6Vi3+Ss5
g8EjkXcDLkPiBSM8YjCQO6CraH1dMIC4/hywitL1G2rngFdwgFAuG1HEqgXZKRZA
m2043OVY2SDVnMvHcYjarPk94BydZ7mzZRCdaetDY73+8opVL0uRol2GfYwAoedi
z65iIm183w4p4F3JH09W4xSoT8FeTRfIc2iAlde3wFA6aK/NV0G5
---- END SSH2 PUBLIC KEY ----
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992