How to create a pair private/public keys using Node.js crypto?

后端 未结 9 664
逝去的感伤
逝去的感伤 2020-12-23 01:59

I have to generate two keys (private and public) to encrypt a text with the public and let the user with the private key decrypt the text.

Is it possible with the mo

相关标签:
9条回答
  • 2020-12-23 02:31

    The following code works, but I'm not a professional cryptographer, so some comments here would be useful.

    I've used the ursa RSA module, instead of crypto.

    I am concerned that if similar data were encrypted directly, without a pass of AES or similar, then it might be trivial to break this. Comments please...

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

    After some further investigation http://en.wikipedia.org/w/index.php?title=RSA_%28cryptosystem%29&section=12#Attacks_against_plain_RSA it looks like ursa already does padding.

    0 讨论(0)
  • 2020-12-23 02:32

    I dont know if this helps but I also was looking to do something along these lines. Here is what I came up with :

    As mentioned in the answer by Nelson Owalo you can use the crypto library, as follows :

    //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);
      }
    );
    

    I think the key points are which algorithm is used, as older versions of the pem use pkcs1 not pkcs8. The beginning of the key helps identify the version of the key and also includes information on wither it is encrypted or not. Hope this helps!

    0 讨论(0)
  • 2020-12-23 02:37

    If you know how to get what you want from OpenSSL, I think it's perfectly reasonable to run OpenSSL using Node's 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();  
    });
    
    0 讨论(0)
提交回复
热议问题