Nodejs `crypto.publicEncrypt` 不会采用 `ssh-keygen rsa` 生成的公钥

Get*_*ter 2 rsa node.js cryptojs

我曾经ssh-keygen rsa生成 RSA 密钥对。生成的公钥如下所示:

ssh-rsa AAAAB3NzaC1yc2EAAA...
Run Code Online (Sandbox Code Playgroud)

当我尝试crypto在 Node.js 中使用来加密纯字符串时,

const fs = require('fs');
const { publicEncrypt } = require('crypto');

const publicKey = fs.readFileSync('$path/to/publicKey').toString();

const encryptedToken = publicEncrypt(publicKey, Buffer.from('some plain string'));
Run Code Online (Sandbox Code Playgroud)

它会给出以下错误:

Error: error:0909006C:PEM routines:get_name:no start line
  at node:internal/crypto/cipher:78:12
  ...
 library: 'PEM routines',
 function: 'get_name',
 reason: 'no start line',
 code: 'ERR_OSSL_PEM_NO_START_LINE'
Run Code Online (Sandbox Code Playgroud)

我对密码学非常陌生,只知道公钥/私钥加密的一般概念,因此非常感谢任何建议。

编辑:

我知道它crypto附带了生成密钥对的方法,所以我想问题更多是关于为什么公钥ssh-rsa在这里不起作用。

Top*_*aco 7

发布的公钥位于OpenSSH中格式,NodeJS 的 crypto 模块不支持该格式,请参阅 的文档crypto.publicEncrypt(key, buffer)

但是,OpenSSH 格式的密钥可以转换为 NodeJS 可以处理的格式。这可以通过工具完成,例如ssh-keygen或库(例如node-sshpk )

或者,可以使用以下命令直接以所需格式生成密钥或者,可以使用OpenSSL

以下示例使用 node-sshpk 库,并将 OpenSSH 私钥转换为 PEM 编码的 PKCS8 密钥,并将 OpenSSH 公钥转换为 PEM 编码的 X.509/SPKI 密钥。NodeJS 支持这两种目标格式:

var sshpk = require('sshpk');
var crypto = require('crypto');

var privateKeyOpenSSH = `-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAQEApcFmUiObzYdRrKivbYrUwJ8plRfjcgA1nXIHpMKj4q0l4vatprYe
vNS2l06y2Qvz1Txu7AeS9+zT673zczwvLgENcZb6lXA576XMLjcmZhnNKXDRnRV/UCMlea
jdwdhQ93YJpsGRCUewD8k6IOO6G/MVAQ433ybBuCPJysTLWNk2Vv/J3VrLkBWGLiwOUcnZ
pR17/mm6QBOsLRAuBs1jELcid1Jdpc8wfULlrSdCfw/P2mXOqpuTMhSEBy4yE+W6V54MSI
Vw4BaxlrcAmC/Rh7OHJrhuIEmmOStqmMPe7HvFKNTjqzISAiyWmPWWwI9UuP4g7b0p7GAk
0YMevLPQnwAAA9jLWAaqy1gGqgAAAAdzc2gtcnNhAAABAQClwWZSI5vNh1GsqK9titTAny
mVF+NyADWdcgekwqPirSXi9q2mth681LaXTrLZC/PVPG7sB5L37NPrvfNzPC8uAQ1xlvqV
cDnvpcwuNyZmGc0pcNGdFX9QIyV5qN3B2FD3dgmmwZEJR7APyTog47ob8xUBDjffJsG4I8
nKxMtY2TZW/8ndWsuQFYYuLA5RydmlHXv+abpAE6wtEC4GzWMQtyJ3Ul2lzzB9QuWtJ0J/
D8/aZc6qm5MyFIQHLjIT5bpXngxIhXDgFrGWtwCYL9GHs4cmuG4gSaY5K2qYw97se8Uo1O
OrMhICLJaY9ZbAj1S4/iDtvSnsYCTRgx68s9CfAAAAAwEAAQAAAQAstgRxt6U5RX0kg8P+
WmqVItnGm9EAWUodFDs3mEE4zdfgZwXkaE/WQ9KU8eeQYIb/R/PruwdL1Rg9CNn4hY18bV
BBCabCVKlsGV8AQGQdOmx69zGzm67h4Pkk3gYjWcRNXAuybZg/1pSJTZBees8i5ukNhdZQ
XVX347908KyhZFb4jlYws7gbOkVBP7ludHSnnrodL91F2ouKrgplLfWu40sgU3fSpSybby
3Llt+FUW6UjCErp54c2LS5vZtvTJK+wVr2fYF4Y1Sgmv+JZ4bJUkZgaxzcHoOLF5GfuQFo
dvJVxbSXPUhk7JW7ur9hHLkEaJtYf0xf1TwJdPRQxu3xAAAAgQCui5wvYjZrCM9wWDXpWh
1dNGPIJQuX8aCxi2tfTkRYlkPUWFSYd+orQr53/FPTxLdwe9lAe8x0Xkr+wMga6771ywHw
sT6xk7nCabXcN6PQCn5DjYMtLPfa5rY3+yHR01pVSzo9l6JcvangU1xyw7MRYj0LGZVSbp
U/beRO/bXekQAAAIEA0uUTVG9wPiqZRTLT6H8rQ4ZK96VcTF+CnmJUO+3Fsp/D7jfYItZF
2GcqzWYv6tsvumdhZt0dziXBy7fAJDW88k/nq+BNTlDXEYzkEA+x13eaLAzfI08SwlAnF5
zxZUo8yIsjKtyt9gs1+VVgtwpvvqUVDUibjbWxaE4OWtdLjwUAAACBAMk02gcYkJylXw12
4me1vtWpw7/7pga3eK0Y4ZTZgpCZXhrLnl9yWXrVIlvV8dLJQI88s7+1CRU9HPi+2BGtgI
mJ5crYws7q0QgLODg1rDosd4vkkKok5XPUsrKDLxwme+Ipq26IdRyoJF2ZiRHvPG5ajjmK
gWByjcdktmXM+UpTAAAAHHRmbG9yZXNfZHQwMUB0ZmxvcmVzX2R0MDEtUEMBAgMEBQY=
-----END OPENSSH PRIVATE KEY-----`

var publicKeyOpenSSH = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQClwWZSI5vNh1GsqK9titTAnymVF+NyADWdcgekwqPirSXi9q2mth681LaXTrLZC/PVPG7sB5L37NPrvfNzPC8uAQ1xlvqVcDnvpcwuNyZmGc0pcNGdFX9QIyV5qN3B2FD3dgmmwZEJR7APyTog47ob8xUBDjffJsG4I8nKxMtY2TZW/8ndWsuQFYYuLA5RydmlHXv+abpAE6wtEC4GzWMQtyJ3Ul2lzzB9QuWtJ0J/D8/aZc6qm5MyFIQHLjIT5bpXngxIhXDgFrGWtwCYL9GHs4cmuG4gSaY5K2qYw97se8Uo1OOrMhICLJaY9ZbAj1S4/iDtvSnsYCTRgx68s9Cf whatever`;

// Convert
var privateKey = sshpk.parsePrivateKey(privateKeyOpenSSH, 'ssh');
var publicKey = sshpk.parseKey(publicKeyOpenSSH, 'ssh');
var privateKeyPkcs8 = privateKey.toBuffer('pkcs8');
var publicKeyX509 = publicKey.toBuffer('pkcs8');
console.log(privateKey.toString('ssh'));
console.log(publicKey.toString('ssh'));
console.log(privateKeyPkcs8.toString('utf8')); // -----BEGIN PRIVATE KEY-----...
console.log(publicKeyX509.toString('utf8')); // -----BEGIN PUBLIC KEY-----...

// Encrypt/Decrypt
var plaintext = Buffer.from('The quick brown fox jumps over the lazy dog', 'utf8');
var ciphertext = crypto.publicEncrypt(publicKeyX509.toString('utf8'), plaintext);
var decryptedText = crypto.privateDecrypt(privateKeyPkcs8.toString('utf8'), ciphertext);

console.log('Ciphertext, base64 encoded: ', ciphertext.toString('base64'));
console.log('Decrypted text: ', decryptedText.toString('utf8'));    
Run Code Online (Sandbox Code Playgroud)