Node.js correct way to make rsa encrypt?
Asked Answered
U

1

3

i'm trying to create a WS for make soap request. In the body of the message there is a field that contains an encrypted text. I have the public key to encrypt the text but the only result that i obtain is that the text is not recognized. I use crypto module of node for making request and the text is crypted but i don't know why is not correclty encrypted.

Ps i made the same thing on php with openssl_public_encrypt function and working. But i have to do it in node.js.

Any idea or suggestion? What is different openssl_public_encrypt from crypto.publicEncrypt function?

Here is the encrypt part in node.js:

var crypto = require("crypto");
var fs = require('fs');

fs.readFile("./certificate.pem", 'utf8', function (err, data) {
    var bufferToEncrypt = new Buffer("textToEncrypt");
    var encrypted = crypto.publicEncrypt({"key":data, padding:crypto.RSA_NO_PADDING}, bufferToEncrypt).toString("base64");
    console.log(encrypted);  // length 128
}

The same thing in php:

<?php

    $publicKey = "./certificate.pem";
    $plaintext = "textToEncrypt";

    openssl_public_encrypt($plaintext, $encrypted, $publicKey);

    echo base64_encode($encrypted);   //encrypted string length 128

?>

I don't have the private key for decrypting the text, i only have the public key.

Also notice that the length of the encrypted text (in base64) is the same in php and in node.js.

Unger answered 22/1, 2016 at 18:40 Comment(2)
It is unlikely that anyone can help you here unless you include the actual code you are using for both encryption and decryption so we can see what you have and try to determine what you have done wrong.Kraft
@Kraft You're right! I've updated the post with pieces of code for the encryption partUnger
L
10

I guess the padding is your problem. In node.js you specify padding:crypto.RSA_NO_PADDING. When looking up the doc of openssl_public_encrypt() it says that it uses OPENSSL_PKCS1_PADDING by default. Try the following:

var constants = require("constants");
var encrypted = crypto.publicEncrypt({"key":data,
    padding:constants.RSA_PKCS1_PADDING}, bufferToEncrypt).toString("base64");

I have prepared an online demo:

  1. Encrypt using node.js
  2. copy the resulting string
  3. and paste it to $encrypted_encoded on PHP decryption example

Advise: As a rule of thumb, don't use asymmetric encryption for actual messages. Use it to protect a symmetric key instead. However, your use case might be valid, I just want to state this every time someone talks RSA encryption.

Loera answered 22/1, 2016 at 21:31 Comment(4)
Sorry but also changing the padding type, according to your solution, the encrypted text generated is not recognized by the system.Unger
I see that the public key that i have is a certificate. Also i try to create a public key from this certificate using openssl, but not workingUnger
@Unger I'have fixed the code, unfortunately the constants were undefined, thus the padding was still wrong. I've also added some only demos for both node.js encryption and php decryption.Loera
I try you new solution and now it work. Thanks a lot for your helpUnger

© 2022 - 2024 — McMap. All rights reserved.