Encrypting data with Public Key in node.js

▼魔方 西西 提交于 2019-11-27 10:28:06
Jacob McKay

No library necessary friends,

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

The updated public/private decrypt and encryption module is URSA. 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

See: https://github.com/Obvious/ursa

How about this node-rsa module? Here's a link to the test.js file that demonstrates usage.

I tested this in Node 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)
}

TL;DR: Ursa is your best bet. Its really funky that this doesn't come standard with node 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 Open SSL 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:

This is literally all I could find.

This is not supported natively by node version v0.11.13 or below but it seems that next version of node ( 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!