Puttygen 和 NodeJS 上生成的 RSA 密钥的长度不同

Posted

技术标签:

【中文标题】Puttygen 和 NodeJS 上生成的 RSA 密钥的长度不同【英文标题】:Length of generated RSA key is different on Puttygen and NodeJS 【发布时间】:2020-10-23 18:57:26 【问题描述】:

我一直在尝试在 AWS Lambda 上生成 RSA 密钥对,以替换当前在 PuTTYgen 上手动生成的密钥。 PuTTYgen 上生成的密钥为 RSA 类型,长度为 2048,生成的示例密钥(无注释)如下 -

---- 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 ----

现在我一直在尝试使用以下代码在 NodeJS lambda 上复制相同的内容 -

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']);

在执行这个 lambda 时,生成的公钥看起来像这样 -

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

据我对 RSA 密钥的了解,第一行和最后一行应该没有任何区别,因为它们基本上是 cmets。但是我看到 PuTTYgen 键包含大约 5 和 1/2 行内容,而 NodeJS 键包含 6 行以上的内容。为什么两者的长度都是2048,为什么会有区别?

谢谢。

【问题讨论】:

见How can I transform between the two styles of public key format, one “BEGIN RSA PUBLIC KEY”, the other is “BEGIN PUBLIC KEY”。 ...第一行和最后一行不应该有任何区别,因为它们基本上是 cmets... 是的,但它们确实告诉您有关钥匙。不幸的是,有许多 RSA 格式是为特定目的量身定制的。第一个特定于 SSH,然后第二个更普遍接受,但两者都包含基本相同的信息。 这能回答你的问题吗? RSA Public Key format 我查看了这两个链接,我想我理解不同 RSA 格式的前提。我找到了一个模块 - 'sshpk',它应该有助于将我的密钥转换为所需的格式。如果成功将分享代码,感谢您的帮助。 【参考方案1】:

感谢 cmets,帮助我更好地理解密钥的格式。使用 NodeJS 代码生成的密钥是 PEM 格式,需要将其转换为 OpenSSH 格式以匹配 PuTTYgen 的输出密钥。

sshpk 模块有助于将 PEM 密钥转换为 OpenSSH 格式。执行此操作的代码如下 -

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

这将导致具有以下格式的密钥 -

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

使用parseKey()方法时,可以通过添加名称来删除末尾的(未命名)。

现在,您可以按照您的要求格式化此字符串,如下所示 -

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);

上述部分的执行将为您提供所需格式的密钥 -

---- BEGIN SSH2 PUBLIC KEY ----
Comment: ""
AAAAB3NzaC1yc2EAAAADAQABAAABAQCqWWfYMm/q1Ee4AzRJMc+BgsqzVIZgwTid
GDb6E3V2EQ85+iX09pmDF8E23Fsmd9WoUMB2L/FXUIlWZmofPmoInKk740UcsQGT
0MVYQfDAiVBqrbymIR/lMBCirFpFq7hIDzACgWYAmSEFtDBdP4LmFozx6Vi3+Ss5
g8EjkXcDLkPiBSM8YjCQO6CraH1dMIC4/hywitL1G2rngFdwgFAuG1HEqgXZKRZA
m2043OVY2SDVnMvHcYjarPk94BydZ7mzZRCdaetDY73+8opVL0uRol2GfYwAoedi
z65iIm183w4p4F3JH09W4xSoT8FeTRfIc2iAlde3wFA6aK/NV0G5
---- END SSH2 PUBLIC KEY ----

【讨论】:

以上是关于Puttygen 和 NodeJS 上生成的 RSA 密钥的长度不同的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS10 上生成的 GIF 图像不再在浏览器上永远循环

如何在 xls 中下载由 play 1.2.7 后端在 java 上生成的 html 表的内容

Apollo Android 客户端 - 无法访问类路径上生成的类

如何下载我的服务器(springboot)上生成的角度pdf文件?

Beanstalk:如何将服务器上生成的文件同步回 beanstalk 存储库?

如何保证对我的服务器的请求是由我的 iOS 应用程序在真实设备上生成的?