10

In crypto, I see only Signer/Verifier for doing digital signature and Cipher/Decipher with symmetric key encryption.

How do I encrypt data with public key?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
teerapap
  • 5,303
  • 7
  • 33
  • 40

3 Answers3

12

As mentioned in the official nodejs api docs here: crypto.publicEncrypt(key, buffer)

Encrypts the content of buffer with key and returns a new Buffer with encrypted content. The returned data can be decrypted using the corresponding private key, for example using crypto.privateDecrypt().

If key is not a KeyObject, this function behaves as if key had been passed to crypto.createPublicKey(). If it is an object, the padding property can be passed. Otherwise, this function uses RSA_PKCS1_OAEP_PADDING.

Because RSA public keys can be derived from private keys, a private key may be passed instead of a public key.

So the answer is:

var encrypted = crypto.publicEncrypt(publicKey, buffer);
Jalaleddin Hosseini
  • 2,142
  • 2
  • 25
  • 28
2

You might be interested in my NaCl bindings. From its API:

// Encrypt and sign
box(message, nonce, pubkey, privkey)

// Decrypt and validate
unbox(box, nonce, pubkey, privkey)
// Generates a new keypair, returns {private: <buffer>, public: <buffer>}
boxKeypair()

// Lengths of nonces and public and private keys in bytes
// { nonce: x, pubkey: x, privkey: x }
lengths.box
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
thejh
  • 44,854
  • 16
  • 96
  • 107
0

Yet another approach is using Cryptographic Message Syntax (CMS). It's not a pure Node.js solution, but you likely have all tools you need in the box. Below is the example using OpenSSL:

Generate x509 certificate (recipient) and private key files (in Bash):

openssl req  -nodes -new -x509  -keyout key.pem -out cert.pem

Encrypt/Decrypt message from standard input (in Bash):

 echo 123 | openssl cms -encrypt -recip cert.pem | openssl cms -decrypt -inkey key.pem

You can use -in/-out parameters to work with files. Below is an example you can use for Node.js:

require('child_process').execSync("openssl cms -encrypt -in file.json -recip cert.pem -out file.json.cms")

On Linux you'll likely have OpenSSL installed already. You can get OpenSSL on Windows by installing Git Bash, although you can also use built-in PowerShell commands. You'll need to generate a PFX certificate (using New-SelfSignedCertificate) or install existing one (can be generated with OpenSSL too). Once the certificate installed in the certificate store, you can use below commands for encryption/decryption:

Protect-CmsMessage -to CN=MyCertName -Path file.json -OutFile file.json.cms
Unprotect-CmsMessage -Path file.json # It will find proper cert in cert store for you

Below is an example how to generate .pem and PFX certificates from the same private key using OpenSSL, and make messages interchangeable between OpenSSL and PowerShell.

Generate certificate with extensions (that's required on Windows):

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout key.pem -out cert.pem -subj '/CN=MyCertName' -addext extendedKeyUsage=1.3.6.1.4.1.311.80.1 -addext keyUsage=keyEncipherment

The above snippet will work only for newer versions of OpenSSL (1.1.1). Otherwise you need a separate file to define extensions. Then generate a PFX certificate (protect it with some password):

openssl pkcs12 -export -out certificate.pfx -inkey key.pem -in cert.pem -passout pass:P@ssw0rd

Then copy that PFX file to your Windows machine. You should be able to install it via PowerShell (Import-PfxCertificate) or manually (click on it and follow wizard, use all defaults). In order to make messages interchangeable use the -inform \ -outform parameter when using OpenSSL. For example:

openssl cms -encrypt -in file.json -recip cert.pem -outform PEM 
openssl cms -decrypt -in file.json.cms -inkey key.pem -inform PEM
# If having both OpenSSL/PowerShell on the same OS, use this for testing:
echo test | Protect-CmsMessage -to CN=MyCertName | openssl cms -decrypt -inform PEM -inkey key.pem

Btw, the CmsMessage commands will be available on PowerShell Core 7.1, so you can use it on Linux/Mac too (it's in preview now, and a stable version will be released in Dec 2020).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mike Twc
  • 2,230
  • 2
  • 14
  • 19