如何使用 Node.js 加密创建一对私钥/公钥?

我必须生成两个密钥(私钥和公钥)来使用公钥加密文本,并让使用私钥的用户解密文本。

有没有可能用加密模块?

95051 次浏览

我还没用过,但这个可能有用:

Http://ox.no/posts/diffie-hellman-support-in-node-js

这方面的文档严重缺乏(我找不到任何示例)。

如果您知道如何从 OpenSSL 获得您想要的东西,我认为使用 Node 的 child_process运行 OpenSSL 是完全合理的。

var cp = require('child_process')
, assert = require('assert')
;


var privateKey, publicKey;
publicKey = '';
cp.exec('openssl genrsa 2048', function(err, stdout, stderr) {
assert.ok(!err);
privateKey = stdout;
console.log(privateKey);
makepub = cp.spawn('openssl', ['rsa', '-pubout']);
makepub.on('exit', function(code) {
assert.equal(code, 0);
console.log(publicKey);
});
makepub.stdout.on('data', function(data) {
publicKey += data;
});
makepub.stdout.setEncoding('ascii');
makepub.stdin.write(privateKey);
makepub.stdin.end();
});

你可以使用 这个 rsa-json 模块。它只是生成一个 openssl 进程,所以它非常依赖于操作系统(默认情况下它不能在 windows 上工作)。

Child _ process 路由是一个糟糕的、不可伸缩的解决方案。

我选择了 钥匙对

使用 npm 中的加密模块生成 KeyPair。

var crypto = require('crypto');


var prime_length = 60;
var diffHell = crypto.createDiffieHellman(prime_length);


diffHell.generateKeys('base64');
console.log("Public Key : " ,diffHell.getPublicKey('base64'));
console.log("Private Key : " ,diffHell.getPrivateKey('base64'));


console.log("Public Key : " ,diffHell.getPublicKey('hex'));
console.log("Private Key : " ,diffHell.getPrivateKey('hex'));

以上是一个示例片段。了解更多的结帐文档 http://nodejs.org/api/crypto.html

下面的代码可以工作,但是我不是一个专业的密码学家,所以这里的一些注释会很有用。

我使用了 ursa RSA 模块,而不是加密。

我担心,如果类似的数据直接加密,没有通过 AES 或类似的,那么它可能是微不足道的破解这一点。请评论..。

var ursa = require('ursa');
var fs = require('fs');


// create a pair of keys (a private key contains both keys...)
var keys = ursa.generatePrivateKey();
console.log('keys:', keys);


// reconstitute the private key from a base64 encoding
var privPem = keys.toPrivatePem('base64');
console.log('privPem:', privPem);


var priv = ursa.createPrivateKey(privPem, '', 'base64');


// make a public key, to be used for encryption
var pubPem = keys.toPublicPem('base64');
console.log('pubPem:', pubPem);


var pub = ursa.createPublicKey(pubPem, 'base64');


// encrypt, with the public key, then decrypt with the private
var data = new Buffer('hello world');
console.log('data:', data);


var enc = pub.encrypt(data);
console.log('enc:', enc);


var unenc = priv.decrypt(enc);
console.log('unenc:', unenc);

经过一些进一步的调查 http://en.wikipedia.org/w/index.php?title=RSA_%28cryptosystem%29&section=12#Attacks_against_plain_RSA看起来熊座已经做了填充。

Nodejs v10.12现在通过 GenerateKeyPair本机支持这一点

const { generateKeyPair } = require('crypto');
generateKeyPair('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: 'top secret'
}
}, (err, publicKey, privateKey) => {
// Handle errors and use the generated key pair.
});
const crypto = require('crypto');


const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
});

我不知道这是否有帮助,但我也正在寻找沿着这些线索做一些事情。 以下是我的想法:

正如 Nelson Owalo 在答案中提到的,可以使用加密库,如下所示:

//import the methods
const { generateKeyPair, createSign, createVerify } = require("crypto");
//generate the key pair
generateKeyPair(
"rsa",
{
modulusLength: 2048, // It holds a number. It is the key size in bits and is applicable for RSA, and DSA algorithm only.
publicKeyEncoding: {
type: "pkcs1", //Note the type is pkcs1 not spki
format: "pem",
},
privateKeyEncoding: {
type: "pkcs1", //Note again the type is set to pkcs1
format: "pem",
//cipher: "aes-256-cbc", //Optional
//passphrase: "", //Optional
},
},
(err, publicKey, privateKey) => {
// Handle errors and use the generated key pair.
if (err) console.log("Error!", err);
console.log({
publicKey,
privateKey,
});//Print the keys to the console or save them to a file.
/*
* At this point you will have to pem files,
* the public key which will start with
* '-----BEGIN RSA PUBLIC KEY-----\n' +
* and the private key which will start with
* '-----BEGIN RSA PRIVATE KEY-----\n' +
*/
//Verify it works by signing some data and verifying it.
//Create some sample data that we want to sign
const verifiableData = "this need to be verified";


// The signature method takes the data we want to sign, the
// hashing algorithm, and the padding scheme, and generates
// a signature in the form of bytes
const signature = require("crypto").sign("sha256", Buffer.from(verifiableData),
{
key: privateKey,
padding: require("crypto").constants.RSA_PKCS1_PSS_PADDING,
});
//Convert the signature to base64 for storage.
console.log(signature.toString("base64"));


// To verify the data, we provide the same hashing algorithm and
// padding scheme we provided to generate the signature, along
// with the signature itself, the data that we want to
// verify against the signature, and the public key
const isVerified = require("crypto").verify(
"sha256",
Buffer.from(verifiableData),
{
key: publicKey,
padding: require("crypto").constants.RSA_PKCS1_PSS_PADDING,
},
Buffer.from(signature.toString("base64"), "base64")
);


// isVerified should be `true` if the signature is valid
console.log("signature verified: ", isVerified);
}
);

我认为关键点在于使用哪种算法,因为旧版本的 pem 使用 pkcs1而不是 pkcs8。密钥的开头有助于标识密钥的版本,还包括关于密钥是否加密的信息。希望这个能帮上忙!