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

如何使用Node.js crypto创建一对私钥/公钥?,node.js,node-crypto,Node.js,Node Crypto,我必须生成两个密钥(private和public)来用public加密文本,并让用户用私钥解密文本 是否可以使用模块Crypto?我没有使用它,但这可能有用: 这方面的文档非常缺乏(我找不到任何示例)。如果您知道如何从OpenSSL获取所需内容,我认为使用Node的子进程运行OpenSSL是完全合理的 var cp = require('child_process') , assert = require('assert') ; var privateKey, publicKey;

我必须生成两个密钥(private和public)来用public加密文本,并让用户用私钥解密文本


是否可以使用模块Crypto?

我没有使用它,但这可能有用:


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

如果您知道如何从OpenSSL获取所需内容,我认为使用Node的
子进程运行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();  
});

你可以用。它只是产生了一个openssl进程,因此它非常依赖于操作系统(默认情况下在windows上不起作用)。

child\u进程路由在我看来是一个糟糕且不可扩展的解决方案。请远离


我选择了和他一起去

使用npm的加密模块生成密钥对

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

上面是一个示例代码段。要了解更多的签出文档,下面的代码可以工作,但我不是一个专业的密码学家,所以这里的一些注释会很有用

我使用了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);

经过进一步的调查,看起来ursa已经在进行填充了。

nodejs v10.12现在通过


我不知道这是否有帮助,但我也希望能按照这些思路做些事情。 以下是我的想法:

如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。密钥的开头有助于识别密钥的版本,还包括是否加密的信息。希望这有帮助

我不知道你将如何安全地给用户他们的私钥。如果他们在本地生成密钥对并将公钥给您,我会更好。@Bruno是的,没问题。。。我的目标是了解如何使用Node.js创建一对密钥(private、public),这可能吗?我认为这非常依赖操作系统。大多数服务器都运行在Linux上,我想我会把它作为一个临时解决方案,直到nodejs内部支持RSA密钥生成。这个答案没有包括加密和解密。这个问题没有要求加密和解密。它只要求生成密钥对。文档中对加密和解密做了很好的解释。我喜欢这个,但是如何使用加密获得PEM格式的密钥对?@Aks作为一个对加密相当陌生的人,我没有找到任何解释-我遗漏了什么吗?这会生成一个DH密钥对,与普通RSA或DSA密钥对非常不同。您收到了警告。
密钥对
比OpenSSL慢得多,而且是同步的,而OpenSSL路由是异步的。子进程路由更具可伸缩性。我支持这一点。在我的笔记本电脑上,在shild进程中运行
openssl
keypair
快约80倍,比本机加密模块快无限多。但child_进程依赖于本机库。如果库不在那里,它可能会出错克里斯:代码中的注释表示encrypt with private和decrypt with public,但代码的作用相反:encrypt with public和decrypt with private。当我尝试使用private加密时,pub.decrypt(enc)告诉我pub上的decrypt函数未定义!任何想法。这将生成PEM编码的RSA公钥。如果我需要OpenSSH(ssh rsa)公钥怎么办?在没有第三方模块的情况下,有没有一种原生的js方式呢?你是什么意思<代码>ssh密钥生成
?PEM只是一种文件格式,它们(两个函数)提供相同的结果。您将拥有一个公钥和一个私钥,可以使用。此代码输出为PKCS#8格式(-----开始公钥------),我需要ssh rsa格式,可以在.ssh/authorized_keys文件中使用-我知道如何使用ssh gen或openssl进行转换,但我只想使用JavaScript。不,我需要OpenSSH格式,它以ssh rsa开始。RSA公钥是另一种格式,它是PKCS#1@DavidDeAnda您可以使用lib
节点forge
实现这一点。在生成上述
publicKey
privateKey
之后,您可以执行
forge.ssh.publicKeyToOpenSSH(forge.pki.publickeyfromfrompem(publicKey))
forge.ssh.privateKeyToOpenSSH(forge.pki.privatekeyfromfrompem(privateKey))
。这些函数确实返回OpenSSH所需的字符串。
const crypto = require('crypto');

  const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
    modulusLength: 2048,
    publicKeyEncoding: {
      type: 'spki',
      format: 'pem'
    },
    privateKeyEncoding: {
      type: 'pkcs8',
      format: 'pem'
    }
  }); 
//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);
  }
);