NodeJS 生成用于签名和验证消息的有效 PEM 密钥
NodeJS Generate Valid PEM keys for Signing and Verifying messages
上下文
来自 NodeJS 文档 TLS/SSL for Node v10.9.0 (2018-AUG)
https://nodejs.org/api/tls.html#tls_tls_ssl_concepts
openssl genrsa -out ryans-key.pem 2048
将产生:
-----BEGIN RSA PRIVATE KEY-----
base64 encoded magic here...
-----END RSA PRIVATE KEY-----
然后我可以成功地使用 Sign
class 对消息进行加密签名:
https://nodejs.org/api/crypto.html#crypto_class_sign
const crypto = require('crypto');
const sign = crypto.createSign('RSA-SHA256');
sign.update('some data to sign');
const privateKey = `Insert magic value from above`;
console.log(sign.sign(privateKey, 'base64'));
我尝试了以下但没有成功:
const crypto = require('crypto');
const dhke = crypto.createDiffieHellman(2048);
dhke.generateKeys();
const private_pem = `-----BEGIN RSA PRIVATE KEY-----
${dhke.getPrivateKey('base64')}
-----END RSA PRIVATE KEY-----`;
console.log(private_pem);
const sign = crypto.createSign('RSA-SHA256');
sign.update('some data to sign');
const signature = sign.sign(private_pem, 'base64');
console.log(signature);
出现以下错误:
Error: error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long
at Sign.sign (internal/crypto/sig.js:84:26)
...
问题
我如何使用 NodeJS 中的 crypto
库来实现 openssl
命令行工具(或另一个 NPM 模块)正在执行的操作,以创建有效的 PEM 格式 public/private 密钥- Sign
class?
要求的对
类似未解决的问题
- Generate Key for signing within nodejs
解决方案
由于 from JacobTDC NodeJS v10.12.0 添加了此功能,因此这是从头到尾的工作解决方案。
const crypto = require('crypto'); const sign = crypto.createSign('RSA-SHA256');
sign.update('some data to sign');
// $ openssl genrsa -out ryans-key.pem 2048
// const privateKey = `Insert magic value from above`;
const { generateKeyPairSync } = require('crypto');
const { publicKey, privateKey } = generateKeyPairSync('rsa',
{ modulusLength: 2048, // the length of your key in bits
publicKeyEncoding: {
type: 'spki', // recommended to be 'spki' by the Node.js docs
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8', // recommended to be 'pkcs8' by the Node.js docs
format: 'pem',
//cipher: 'aes-256-cbc', // *optional*
//passphrase: 'top secret' // *optional*
}
});
console.log(privateKey);
console.log(sign.sign(privateKey, 'base64'));
这里的问题是 DH 密钥不是 RSA 密钥并且不完全兼容。
不幸的是,node 也无法通过 crypto
模块生成真正的 RSA 对,这有点令人失望。您需要与本地 openssl
库交互才能执行此操作,或者根据您的要求与第三方模块交互。
至于第三方模块,keypair
是一个简单的库,可以在您给定的情况下工作
const keypair = require('keypair');
const keys: { private: string, public: string } = keypair({ bits : 2056 }); // 2056 is the default but added for example
我还发现 openpgpjs
的效果很好,它的功能更多,同时也专注于成为平台不可知模块。如果您正在考虑在浏览器和节点中进行加密,那么这可能是一个不错的选择。
从 Node.js v10.12.0 开始,您可以使用 crypto.generateKeyPair and crypto.generateKeyPairSync.
我在下面的 Node.js 文档中提供了一个示例(添加了评论):
const { generateKeyPairSync } = require('crypto');
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 4096, // the length of your key in bits
publicKeyEncoding: {
type: 'spki', // recommended to be 'spki' by the Node.js docs
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8', // recommended to be 'pkcs8' by the Node.js docs
format: 'pem',
cipher: 'aes-256-cbc', // *optional*
passphrase: 'top secret' // *optional*
}
});
上下文
来自 NodeJS 文档 TLS/SSL for Node v10.9.0 (2018-AUG)
https://nodejs.org/api/tls.html#tls_tls_ssl_concepts
openssl genrsa -out ryans-key.pem 2048
将产生:
-----BEGIN RSA PRIVATE KEY-----
base64 encoded magic here...
-----END RSA PRIVATE KEY-----
然后我可以成功地使用 Sign
class 对消息进行加密签名:
https://nodejs.org/api/crypto.html#crypto_class_sign
const crypto = require('crypto');
const sign = crypto.createSign('RSA-SHA256');
sign.update('some data to sign');
const privateKey = `Insert magic value from above`;
console.log(sign.sign(privateKey, 'base64'));
我尝试了以下但没有成功:
const crypto = require('crypto');
const dhke = crypto.createDiffieHellman(2048);
dhke.generateKeys();
const private_pem = `-----BEGIN RSA PRIVATE KEY-----
${dhke.getPrivateKey('base64')}
-----END RSA PRIVATE KEY-----`;
console.log(private_pem);
const sign = crypto.createSign('RSA-SHA256');
sign.update('some data to sign');
const signature = sign.sign(private_pem, 'base64');
console.log(signature);
出现以下错误:
Error: error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long
at Sign.sign (internal/crypto/sig.js:84:26)
...
问题
我如何使用 NodeJS 中的 crypto
库来实现 openssl
命令行工具(或另一个 NPM 模块)正在执行的操作,以创建有效的 PEM 格式 public/private 密钥- Sign
class?
类似未解决的问题
- Generate Key for signing within nodejs
解决方案
由于
const crypto = require('crypto'); const sign = crypto.createSign('RSA-SHA256');
sign.update('some data to sign');
// $ openssl genrsa -out ryans-key.pem 2048
// const privateKey = `Insert magic value from above`;
const { generateKeyPairSync } = require('crypto');
const { publicKey, privateKey } = generateKeyPairSync('rsa',
{ modulusLength: 2048, // the length of your key in bits
publicKeyEncoding: {
type: 'spki', // recommended to be 'spki' by the Node.js docs
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8', // recommended to be 'pkcs8' by the Node.js docs
format: 'pem',
//cipher: 'aes-256-cbc', // *optional*
//passphrase: 'top secret' // *optional*
}
});
console.log(privateKey);
console.log(sign.sign(privateKey, 'base64'));
这里的问题是 DH 密钥不是 RSA 密钥并且不完全兼容。
不幸的是,node 也无法通过 crypto
模块生成真正的 RSA 对,这有点令人失望。您需要与本地 openssl
库交互才能执行此操作,或者根据您的要求与第三方模块交互。
至于第三方模块,keypair
是一个简单的库,可以在您给定的情况下工作
const keypair = require('keypair');
const keys: { private: string, public: string } = keypair({ bits : 2056 }); // 2056 is the default but added for example
我还发现 openpgpjs
的效果很好,它的功能更多,同时也专注于成为平台不可知模块。如果您正在考虑在浏览器和节点中进行加密,那么这可能是一个不错的选择。
从 Node.js v10.12.0 开始,您可以使用 crypto.generateKeyPair and crypto.generateKeyPairSync.
我在下面的 Node.js 文档中提供了一个示例(添加了评论):
const { generateKeyPairSync } = require('crypto');
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 4096, // the length of your key in bits
publicKeyEncoding: {
type: 'spki', // recommended to be 'spki' by the Node.js docs
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8', // recommended to be 'pkcs8' by the Node.js docs
format: 'pem',
cipher: 'aes-256-cbc', // *optional*
passphrase: 'top secret' // *optional*
}
});