Encrypting data with a public key in Node.js

前端 未结 6 757
不思量自难忘°
不思量自难忘° 2020-11-29 16:13

I need to encrypt a string using a public key (.pem file), and then sign it using a private key (also a .pem).

I am loading the .pem files fine:

public         


        
相关标签:
6条回答
  • 2020-11-29 17:06

    The updated public/private decrypt and encryption module is URSA. The node-rsa module is outdated.

    This Node module provides a fairly complete set of wrappers for the RSA public/private key crypto functionality of OpenSSL.

    npm install ursa
    
    0 讨论(0)
  • 2020-11-29 17:08

    A library is not necessary. Enter crypto.

    Here's a janky little module you could use to encrypt/decrypt strings with RSA keys:

    var crypto = require("crypto");
    var path = require("path");
    var fs = require("fs");
    
    var encryptStringWithRsaPublicKey = function(toEncrypt, relativeOrAbsolutePathToPublicKey) {
        var absolutePath = path.resolve(relativeOrAbsolutePathToPublicKey);
        var publicKey = fs.readFileSync(absolutePath, "utf8");
        var buffer = Buffer.from(toEncrypt);
        var encrypted = crypto.publicEncrypt(publicKey, buffer);
        return encrypted.toString("base64");
    };
    
    var decryptStringWithRsaPrivateKey = function(toDecrypt, relativeOrAbsolutePathtoPrivateKey) {
        var absolutePath = path.resolve(relativeOrAbsolutePathtoPrivateKey);
        var privateKey = fs.readFileSync(absolutePath, "utf8");
        var buffer = Buffer.from(toDecrypt, "base64");
        var decrypted = crypto.privateDecrypt(privateKey, buffer);
        return decrypted.toString("utf8");
    };
    
    module.exports = {
        encryptStringWithRsaPublicKey: encryptStringWithRsaPublicKey,
        decryptStringWithRsaPrivateKey: decryptStringWithRsaPrivateKey
    }
    

    I would recommend not using synchronous fs methods where possible, and you could use promises to make this better, but for simple use cases this is the approach that I have seen work and would take.

    0 讨论(0)
  • 2020-11-29 17:11

    Use the node-rsa module. Here's a link to the test.js file that demonstrates usage.

    0 讨论(0)
  • 2020-11-29 17:13

    I tested this in Node.js 10, you can use encrypt/decrypt functions (small changes on Jacob's answer):

    const crypto = require('crypto')
    const path = require('path')
    const fs = require('fs')
    
    function encrypt(toEncrypt, relativeOrAbsolutePathToPublicKey) {
      const absolutePath = path.resolve(relativeOrAbsolutePathToPublicKey)
      const publicKey = fs.readFileSync(absolutePath, 'utf8')
      const buffer = Buffer.from(toEncrypt, 'utf8')
      const encrypted = crypto.publicEncrypt(publicKey, buffer)
      return encrypted.toString('base64')
    }
    
    function decrypt(toDecrypt, relativeOrAbsolutePathtoPrivateKey) {
      const absolutePath = path.resolve(relativeOrAbsolutePathtoPrivateKey)
      const privateKey = fs.readFileSync(absolutePath, 'utf8')
      const buffer = Buffer.from(toDecrypt, 'base64')
      const decrypted = crypto.privateDecrypt(
        {
          key: privateKey.toString(),
          passphrase: '',
        },
        buffer,
      )
      return decrypted.toString('utf8')
    }
    
    const enc = encrypt('hello', `public.pem`)
    console.log('enc', enc)
    
    const dec = decrypt(enc, `private.pem`)
    console.log('dec', dec)
    

    For the keys you can generate them with

    const { writeFileSync } = require('fs')
    const { generateKeyPairSync } = require('crypto')
    
    function generateKeys() {
      const { privateKey, publicKey } = generateKeyPairSync('rsa', {
        modulusLength: 4096,
        publicKeyEncoding: {
          type: 'pkcs1',
          format: 'pem',
        },
        privateKeyEncoding: {
          type: 'pkcs1',
          format: 'pem',
          cipher: 'aes-256-cbc',
          passphrase: '',
        },
      })
    
      writeFileSync('private.pem', privateKey)
      writeFileSync('public.pem', publicKey)
    }
    
    0 讨论(0)
  • 2020-11-29 17:15

    TL;DR: URSA is your best bet. It's really funky that this doesn't come standard with Node.js' crypto.

    Every other solutions I found either doesn't work in Windows or aren't actually encryption libraries. URSA, recommended by Louie, looks like the best bet. If you don't care about Windows, you're even more golden.

    Note on Ursa: I had to install OpenSSL along with something called "Visual C++ 2008 Redistributables" in order to get the npm install to work. Get that junk here: http://slproweb.com/products/Win32OpenSSL.html

    The breakdown:

    • Annoying additional manual installation steps for Windows
    • https://github.com/Obvious/ursa - probably the best of the lot
    • Not compatible with Windows
    • https://npmjs.org/package/rsautl - says BADPLATFORM
    • https://github.com/katyo/node-rsa - node-waf isn't available on Windows
    • https://github.com/paspao/simple_rsa_encrypt - unistd.h isn't on windows
    • https://npmjs.org/package/pripub - large amounts of linker errors, also not on GitHub

    Not encryption libraries

    • https://github.com/substack/secure-peer
    • https://github.com/substack/rsa-json - just generates keys, but doesn't use them
    • https://github.com/substack/rsa-unpack - just unpacks PEM strings

    This is literally all I could find.

    0 讨论(0)
  • 2020-11-29 17:15

    This is not supported natively by Node.js version v0.11.13 or below, but it seems that next version of Node.js (a.k.a v0.12) will support this.

    Here is the clue: https://github.com/joyent/node/blob/v0.12/lib/crypto.js#L358

    See crypto.publicEncrypt and crypto.privateDecrypt

    Here is the future documentation for this https://github.com/joyent/node/blob/7c0419730b237dbfa0ec4e6fb33a99ff01825a8f/doc/api/crypto.markdown#cryptopublicencryptpublic_key-buffer

    0 讨论(0)
提交回复
热议问题