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

Dai*_*ail 37 node.js node-crypto

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

有可能使用Crypto模块吗?

Nel*_*alo 29

nodejs v10.12现在使用crypto.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.
});
Run Code Online (Sandbox Code Playgroud)

  • 不,我需要 OpenSSH 格式,以 ssh-rsa 开头。RSA PUBLIC KEY 是一种不同的格式,它是 PKCS#1 (2认同)
  • @DavidDeAnda,你可以使用 lib `node-forge` 来做到这一点。如上所述生成“publicKey”和“privateKey”后,您可以执行“forge.ssh.publicKeyToOpenSSH(forge.pki.publicKeyFromPem(publicKey))”和“forge.ssh.privateKeyToOpenSSH(forge.pki.privateKeyFromPem(privateKey))” 。这些函数确实会返回 OpenSSH 所需的字符串。 (2认同)

Aks*_*Aks 20

使用npm中的crypto模块生成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'));
Run Code Online (Sandbox Code Playgroud)

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

  • 这会产生一个DH密钥对,与普通的RSA或DSA密钥对非常不同.你被警告了 (30认同)
  • 这个问题没有要求加密和解密.它只要求密钥对生成.加密和解密在文档中得到了很好的解释. (13认同)
  • 我喜欢这个,但是如何使用加密来获得PEM格式的密钥对? (4认同)
  • @Aks是一个相当新的加密人员,我没有在http://nodejs.org/api/crypto.html#crypto_diffiehellman_computesecret_other_public_key_input_encoding_output_encoding上找到它解释 - 我错过了什么吗? (3认同)

fad*_*bee 16

以下代码有效,但我不是专业的密码学家,所以这里的一些评论会很有用.

我使用了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);
Run Code Online (Sandbox Code Playgroud)

经过一些进一步的调查http://en.wikipedia.org/w/index.php?title=RSA_%28cryptosystem%29§ion=12#Attacks_against_plain_RSA后,看起来ursa已经填充了.

  • 克里斯:你在代码中的评论说用私有加密和用公共解密,但代码反其道而行之:用public加密,用private加密.当我尝试使用private加密时,pub.decrypt(enc)告诉我pub上的解密函数是未定义的!有什么想法吗.谢谢 (4认同)

kgi*_*pin 10

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

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();  
});
Run Code Online (Sandbox Code Playgroud)

  • 在我看来,非常依赖操作系统. (9认同)
  • 肯定不会对我不存在的amstrad起作用. (6认同)

小智 9

const crypto = require('crypto');

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


小智 9

我不知道这是否有帮助,但我也想沿着这些思路做一些事情。这是我想出的:

正如 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);
  }
);
Run Code Online (Sandbox Code Playgroud)

我认为关键点是使用哪种算法,因为旧版本的 pem 使用 pkcs1 而不是 pkcs8。密钥的开头有助于识别密钥的版本,并且还包括有关其是否加密的信息。希望这可以帮助!


Ste*_*ell 0

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

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

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