Search code examples
reactjsnode.jscryptojsjsencrypt

How do I encrypt data on react app and decrypt it in NodeJS?


I'm trying to encrypt data in my react app using RSA encryption then decrypt it on my backend. For the front end I want to use JSEencrypt, and in the backend I want to use the built-in crypto library. I know the encryption aspect is working as I tested it with https://travistidwell.com/jsencrypt/demo/ and it worked fine. But I can't decrypt it. I always get an error:

Error during decryption (probably incorrect key).

Original error: Error: error:02000079:rsa routines::oaep decoding error

This is my frontend code:

var encrypt = new JSEncrypt();

var publicKey = `
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlOJu6TyygqxfWT7eLtGDwajtN
FOb9I5XRb6khyfD1Yt3YiCgQWMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76
xFxdU6jE0NQ+Z+zEdhUTooNRaY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4
gwQco1KRMDSmXSMkDwIDAQAB
-----END PUBLIC KEY-----`;

encrypt.setPublicKey(publicKey);
const objectToEncrypt = {product_name: 'Testing', product_price: 10 };
const jsonString = JSON.stringify(objectToEncrypt);
var encrypted = encrypt.encrypt(jsonString);

It's then sent through an API. This is my backend code:

const crypto = require('crypto');

var privateKey = `
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDlOJu6TyygqxfWT7eLtGDwajtNFOb9I5XRb6khyfD1Yt3YiCgQ
WMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76xFxdU6jE0NQ+Z+zEdhUTooNR
aY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4gwQco1KRMDSmXSMkDwIDAQAB
AoGAfY9LpnuWK5Bs50UVep5c93SJdUi82u7yMx4iHFMc/Z2hfenfYEzu+57fI4fv
xTQ//5DbzRR/XKb8ulNv6+CHyPF31xk7YOBfkGI8qjLoq06V+FyBfDSwL8KbLyeH
m7KUZnLNQbk8yGLzB3iYKkRHlmUanQGaNMIJziWOkN+N9dECQQD0ONYRNZeuM8zd
8XJTSdcIX4a3gy3GGCJxOzv16XHxD03GW6UNLmfPwenKu+cdrQeaqEixrCejXdAF
z/7+BSMpAkEA8EaSOeP5Xr3ZrbiKzi6TGMwHMvC7HdJxaBJbVRfApFrE0/mPwmP5
rN7QwjrMY+0+AbXcm8mRQyQ1+IGEembsdwJBAN6az8Rv7QnD/YBvi52POIlRSSIM
V7SwWvSK4WSMnGb1ZBbhgdg57DXaspcwHsFV7hByQ5BvMtIduHcT14ECfcECQATe
aTgjFnqE/lQ22Rk0eGaYO80cc643BXVGafNfd9fcvwBMnk0iGX0XRsOozVt5Azil
psLBYuApa66NcVHJpCECQQDTjI2AQhFc1yRnCU/YgDnSpJVm1nASoRUnU8Jfm3Oz
uku7JUXcVpt08DFSceCEX9unCuMcT72rAQlLpdZir876
-----END RSA PRIVATE KEY-----`

const encryptedData = req.body.encrypted;

const decryptedData = crypto.privateDecrypt({
    key: privateKey,
    padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
    oaepHash: 'sha256', // Adjust hash function if needed
}, Buffer.from(encryptedData, 'base64'));

console.log('Decrypted data:', decryptedData.toString('utf8'));

Solution

  • JSEncrypt uses PKCS#1 v1.5 padding and does not support OAEP (s. issue #84). Since OAEP is used in the crypto-code, the implementations are incompatible.

    Fix: Use PKCS#1 v1.5 padding in the crypto-code as well (i.e. apply crypto.constants.RSA_PKCS1_PADDING):

    ...
    const decryptedData = crypto.privateDecrypt({
        key: privateKey,
        padding: crypto.constants.RSA_PKCS1_PADDING,            // Fix, apply PKCS#1 v1.5 padding 
        oaepHash: 'sha256',                                     // Ignored for PKCS#1 v1.5, can be removed
      }, Buffer.from(encryptedData, 'base64'));
    ...
    

    or use another library than JSEncrypt which also supports OAEP.