Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
218 views
in Technique[技术] by (71.8m points)

node.js - How to generate persist and load keys using NodeJS?

I've been learning NodeJS and the crypto library. Specifically, I'd like to generate a signature and then verify it. I have working code for this below. The NodeJS Crypto library docs were adequate to figure this much out. I can also export those keys as PEM, so I can just save to disk using fs.writeFile. But I've run into a wall finding documentation and/or examples of how to load the PEM keys back again. How would I go about saving the keys so that I can load them to validate the signature at a later date? Is there a built in method, or should I just save the PEM and then load it later. And after loading the PEM how would I use the crypto library to convert the PEM string back into an actual 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);
})();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Sorry for being too lazy to change your code, but I'm having a sample code that is doing the requested behavior.

It loads the private and public RSA keys from PEM-files, sign and verifies the data with PSS-padding and a 32 byte long salt.

You can run the example code here in a live compiler: https://repl.it/@javacrypto/SoNodeJsCryptoRsaPssSignatureString#index.js

This is the output (yours will differ due to a random padding):

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

This is my full sample code, please keep in mind that there is no exception handling and the code is for educational purpose only:

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('
* * * sign the plaintext with the RSA private key * * *');

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

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

const public_key = fs.readFileSync(filenamePublicKeyPem);
console.log('used public_key:
', public_key);
const signatureVerified = rsaVerifySignatureFromBase64(public_key, dataToSign, signatureBase64);
console.log('
signature (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')
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...