如何使用 NodeJS 生成持久和加载密钥?

How to generate persist and load keys using NodeJS?

我一直在学习 NodeJS 和加密库。具体来说,我想生成一个签名然后进行验证。我在下面有这方面的工作代码。 NodeJS Crypto 库文档足以解决这个问题。我还可以将这些密钥导出为 PEM,这样我就可以使用 fs.writeFile 保存到磁盘。但是我已经 运行 找到了关于如何再次加载 PEM 密钥的文档 and/or 示例。我将如何保存密钥以便我可以加载它们以在以后验证签名?是否有内置方法,或者我应该只保存 PEM 然后稍后加载它。在加载 PEM 之后,我将如何使用加密库将 PEM 字符串转换回实际的 crypto.KeyObject?

const crypto = require('crypto');

(async () => {
    const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
        //The standard secure default length for RSA keys is 2048 bits
        modulusLength: 2048,
    });

    let data = "Signing Data";

    const signature = crypto.sign("sha256", Buffer.from(data), {
        key: privateKey,
        padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
    });

    console.log(signature.toString("base64"))

    const isVerified = crypto.verify(
        "sha256",
        Buffer.from(data),
        {
            key: publicKey,
            padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
        },
        signature
    )

    console.log("signature verified: ", isVerified);
})();

就像你说的那样,你可以使用 writeFile 保存你的密钥,然后你可以使用 readFile 取回它们。

此外,您应该使用 require("fs/promises") 而不是 require("fs"),因为您使用的是异步自动调用函数。

const fs = require("fs/promises")

const KEY_FILE_PATH = `${__dirname}/MY_KEY`

(async () => {
  const privateKey = "..."
  
  await fs.writeFile(KEY_FILE_PATH, privateKey)

  // Later

  const key = await fs.readFile(KEY_FILE_PATH)

})()

抱歉懒得更改您的代码,但我有一个示例代码可以执行请求的行为。

它从 PEM 文件加载私钥和 public RSA 密钥,使用 PSS 填充和 32 字节长的盐对数据进行签名和验证。

您可以在实时编译器中 运行 示例代码:https://repl.it/@javacrypto/SoNodeJsCryptoRsaPssSignatureString#index.js

这是输出(由于随机填充,您的输出会有所不同):

RSA PSS signature string
dataToSign:   The quick brown fox jumps over the lazy dog

* * * sign the plaintext with the RSA private key * * *
used private key:
 <Buffer 2d 2d 2d 2d 2d 42 45 47 49 4e 20 50 52 49 56 41 54 45 20 4b 45 59 2d 2d 2d 2d 2d 0d 0a 4d 49 49 45 76 67 49 42 41 44 41 4e 42 67 6b 71 68 6b 69 47 39 ... 1682 more bytes>
signature (Base64):  vCSB4744p30IBl/sCLjvKm2nix7wfScQn99YX9tVIDNQIvU3QnSCLc2cF+J6R9WMRIXOsY94MxjKCQANW0CuaSs+w31ePHaounFVnmXyY092SicZrtpwlxw2CHqJ0NSyciDpxlRId1vjKlp9E5IJmYtVMtL2hfb711P+nb+m+1sPplNXPpJpdnWIzfLsDMVxCkplAdrcoH2HuWgOtOCHAf3vWbUC/vkvi388NT1UXJRPoERM0m1v11ogP9DiycMdoJxg3fbdH3HknbR02MLNEr7q4ZMzlrKxnYChwp2hnnBvJDcXpPDnQz7sG8zrim1nL/PS8CRG5lxhYYAZqTc+Vg==

* * * verify the signature against the plaintext with the RSA public key * * *
used public_key:
 <Buffer 2d 2d 2d 2d 2d 42 45 47 49 4e 20 50 55 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d 0d 0a 4d 49 49 42 49 6a 41 4e 42 67 6b 71 68 6b 69 47 39 77 30 42 41 51 ... 410 more bytes>

signature (Base64) verified:  true

这是我的完整示例代码,请记住没有异常处理,代码仅用于教育目的:

const crypto = require('crypto');
const fs = require('fs');

console.log('RSA PSS signature string');
const dataToSign = 'The quick brown fox jumps over the lazy dog';
console.log('dataToSign:  ', dataToSign);

var filenamePrivateKeyPem = "privatekey2048.pem";
var filenamePublicKeyPem = "publickey2048.pem";

console.log('\n* * * sign the plaintext with the RSA private key * * *');

const private_key = fs.readFileSync(filenamePrivateKeyPem);
console.log('used private key:\n', private_key);
const signatureBase64 = rsaSignToBase64(private_key, dataToSign);
console.log('signature (Base64): ', signatureBase64);

console.log('\n* * * verify the signature against the plaintext with the RSA public key * * *');

const public_key = fs.readFileSync(filenamePublicKeyPem);
console.log('used public_key:\n', public_key);
const signatureVerified = rsaVerifySignatureFromBase64(public_key, dataToSign, signatureBase64);
console.log('\nsignature (Base64) verified: ', signatureVerified)

function rsaSignToBase64(privateKey, message) {
  const signer = crypto.createSign('sha256');
  signer.update(message);
  signer.end();
  const signature = signer.sign(private_key)
  return signature.toString('Base64')
}

function rsaVerifySignatureFromBase64(publicKey, message, signatureBase64) {
  const signature = base64Decoding(signatureBase64);
  const verifier = crypto.createVerify('sha256');
  verifier.update(message);
  verifier.end();
  return verifier.verify(public_key, signature);
}

function base64Decoding(input) {
  return Buffer.from(input, 'base64')
}