0

How to do I decrypt data using PHP that I have encrypted with using JSEcrypt

Following is how I encrypted my code

async function Encrypt(form = {}) {
  const JSEncrypt = (await import("jsencrypt")).default;
  let encrypt = new JSEncrypt();
  encrypt.setPublicKey(publicKey);
  let data = btoa(JSON.stringify(form));
  let encrypted = encrypt.encrypt(data);
  return encrypted;
}

When I decrypt it using JS, it works fine

async function Decrypt(encrypted) {
  const JSEncrypt = (await import("jsencrypt")).default;
  let encrypt = new JSEncrypt();
  encrypt.setPrivateKey(privateKey);
  let decrypted = encrypt.decrypt(encrypted);
  return decrypted;
}

How do I do the same decrypt function in PHP ?

This is what I have tried and it does not work

function decrypt($data) {
    $privateKey = file_get_contents("../keys/private_key.pem");
    $key = openssl_get_privatekey($privateKey);
    $data = base64_decode($data);
    $result = openssl_private_decrypt($data, $decrypted, $key , OPENSSL_PKCS1_PADDING); //Keeps returning false
    if ($result) {
        # code...
        $decrypted_data = base64_decode($decrypted);
        return json_decode($decrypted_data);
    }
    return "No data";
}

PHP decrypt function returns "No data" because $result keeps returning a false value.

Thank you.

Sample Data that I am using

Blockquote

**Public Key** 

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+QJEeRV7zs0Eh3W1/A1L
Bi9Rh8CXO8mdC1GICj3CUfUJ5xHoNGo03XsMZl7rU2szcmYh/T4Iidnr5hkZB/FG
RqmBy9xUA6IKTJANIkhuAGuzhkCXwnKiCjHBHr3HlqBq201BzPqw4+6+TMTmOe1p
DJ6xmy4YALqf5ovZ9HxJ9DcBzzuDgcNBTMcHAskGZexK3C66OJTFeDXqUS8VuYfa
robAuLeH/8LPnFfAKAYvoZQvUM0zvfn/VIJkvPbCeTr5RYvcpCj2t53tSBpaGKRa
EmiIfT3gKUraJDGz4BEtw7skc4Li3vZAt96UA6XoJdglphxwNztA1ZUaovVg2foN
EQIDAQAB
-----END PUBLIC KEY-----


**Private Key**

-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD5AkR5FXvOzQSH
dbX8DUsGL1GHwJc7yZ0LUYgKPcJR9QnnEeg0ajTdewxmXutTazNyZiH9PgiJ2evm
GRkH8UZGqYHL3FQDogpMkA0iSG4Aa7OGQJfCcqIKMcEevceWoGrbTUHM+rDj7r5M
xOY57WkMnrGbLhgAup/mi9n0fEn0NwHPO4OBw0FMxwcCyQZl7ErcLro4lMV4NepR
LxW5h9quhsC4t4f/ws+cV8AoBi+hlC9QzTO9+f9UgmS89sJ5OvlFi9ykKPa3ne1I
GloYpFoSaIh9PeApStokMbPgES3DuyRzguLe9kC33pQDpegl2CWmHHA3O0DVlRqi
9WDZ+g0RAgMBAAECggEBAO7twg39E0MnbYUc6XXku2w/0xdTMMnpdor5vHM3N1G0
sb/KauiAUCGEhC1mPp9YaZEHdu2rrD25oKS0yFPaqvf6hdS6oNKrlP5J6pBOt14n
+aaELBokLF9jxk5dAzoAyweKZeztTvYmiurWs6I5r2awjvK7k8R/ThbFcmkpKTzt
9oOvq2QoA+fCeqby63SAvl+KmQs3SCEYYQHAkNhwa6BvYTld6FbzL23BxZs2Zr5F
156X91D4lh1eAtgKW/Qq3O0y+Jgeff1VFYasVEsg26XjzY4cVzYtLjXT0SogKxEy
zQS0xPczkweN+LWNo0TzpKzfCdgqPIc5hxxUK+Aj8AECgYEA/KrkKPO0d+AJQoo3
/9ehf7DLKzvpa1qjdw8GI0w/XVzc1nt2YTziZgH1Rj+f17DqbEZFn8c2dl7Cqk7x
XVW16js92g265avovy745xTZ/GhG/4IvS12cZLggedV33RHXrZ035vy/Ahs/QAOJ
WIkV0u3fcopkIewPnJ/XlxWzCsECgYEA/EsF441w/r1FoYUQ8UqVKsFPsJLKLiGL
FNGyUvhoeI+DpBXAz4ZNYAILHYqOKoV60uZhg73FN0m5ihtgCBT7pnsSTkugDLsv
9zjkogdeRypN4Of/PIKUyylDJCGvIX+YmQ06STuH9H2lbvwg9E0/vElUVL+qC0Bj
UanVmb57JlECgYAVs6PnNI9yoGaLNY37xoyTiB7bNskktGNH7Z1sWLc0kK5TKcWQ
MoeLlW14vCxBfWuVIzAFujmeTyNPN3qZtqvqU25LlVRRN8PE8Abm6i6S9G3sskTX
p1GwgPQhIsmpzkeFHPTZPSo2xxpWqDcayKN8O3wuvV4+X6UzobMFwhJfwQKBgQCA
56AppOH/9hr2rPN8JZxTjRO3ZzjQGylhyMaxJ+TQ/JrJIqgyIC+2hzTAskNzLGIW
EcnvMu3qEswu6U/GsVnmtOkkgfVTq+yVB0eiFduwxsely0OY2itGJl38vw0pM3V3
dc+7DSSo4e296Cq6SCHxhRIGfytVtl9IoVrWxAFOEQKBgFmITpM9StkIHJqd/Lkb
gscOOHRpWd20lPos/n42LoIspz7zgbiEi2saiO+yZZ+xK56PYaGkAIyNvzqOVoKi
HBy3FrbxOc+EGIMemvVPv0rK0Jpz8vdgTmXf+4NbWu7jRCvQCrNbCflWyka/w438
mqlInSoviiAMRu2BcS2cojys
-----END PRIVATE KEY-----

Data Set 1

**Clear Text**

o4XuRo4Im3wkJImjLq96XvODUzR5Y+1GCqViKQqStyoidS8+9aQbLrWFpjhyHuE019YzJLHhuWxWlo7yfR3aebm5kObvq/QBe821dZgnOLtvdeUM4NP8iapjV945DsjRkp9g8vEwH3gGN0p/RrzWvbsF57OZ3eLRFjkFv2TS9PcUVlVHYbxpTjfhskpOQrDJeJJZjnCaRyPOa2VG4k3Y3p7WJzU+oT9DJK2aUscuS8zyDvLHSWvS09KOe/5xu+554Q54QHaLmAUxqu//4EjK+8yDko8Ji3mnmpFD0eyXfO2uMlw8dAUJ4w1++hNr7pr60K4rV47aCP1mh6za9lzmUg==

**Signature String**

7MC7xeKz+wbBTm1uxcKKV6AS3hM5TUS9T2ZWOxnxZNptBvClsoVktdfb8LVCTaDOKU9dopawZhcLl1fPZwHSoeQMhkkI2IRq9eHry4XWmXyDwSTLn+90AIdyxh+RuFrasGvcOmjRc75Eij393eDfl/MHyVeipIZXMUrWmRTgIjekXEffsoVrpuEGygGnltHMINXA+H1EbsFfJL4ok8zm4JhX8NdZSAcM3zeHrsf1DXbDRPOm4rwdZiuR5y4JGiVKXnEqfu3MA+tllQObE0UTngaUVVea5BFAjMYgE58cvYslzUbQAzKJERfABMg+LeBBuWTRPMrA4y+xKf8r2UHUBg==

Signature passes smoothly

enter image description here

Data Set 2

**Clear Text**
34JPmAmu4avmsBDL2A9t3NvC5ljfQgcLNNcEclXbTs+Efi6vj3QZb2eMjIA2uOKgBP3ChVJIAI4Zj9rjq31CmrRVtCMPPX5okgOVOH0wK/v+tScwW87SMWOdGhiBn+HXSYQQO3gpLYczVuD+RHzs5/7FEYSnyfg4aT+UTKDrkIxJFOdbdYUKB9zDeGFDiCqSgphU8qZdVoxAk+yCg5gec+/JnK4hrd209fj1tbE4vzFax9fW+jGscHsIn2Fr6gwpVs2zUAHYn8lbiTfI8ao3TJ2BE7aEkcwsq+SZAsKmWDFnwf7aUtZtr8pCkSvT6A/dMeH1Ib9tWl1A6KpczfHH6g==


**Signature**

x6mXZvdZggPBKxMtmnHIdw2j+7WJgfqfsc8udymJE+Z6tEonQvgr5RKr2OUdLUuYul13G/GCgkm+BpbensfsM7G7IwJenjCJs4FXgtYjLCG3QTLNz2OalgLy1dw1SyRW4XETmsbTZysjxvpaBh0/ggC/Dh2oYFsZYVRGDnFgQTWzmMfMIuq2cDT95MmUyN1wLjRxuiQD4vAowkmf5igJpaw1Bd9+ifT3K7LS9dtmq9bl3n1RKV9I7nWbTgT6qgujOsOwTpYjfuGT2xBuqBvDd+al4FPiMaVSt8oDVr5SLuClXYc9Ky+1OcXEgsjdyHqP7kio58PvitUa++q6m+i5bA==

Signature passes smoothly as well enter image description here

These are my sample data . Hopefully, it is sufficient enough. Thank you

FULL PHP CODE

Decrypt.php

<?php



function decrypt($data) {
    $privateKey = file_get_contents("../keys/private_key.pem");
    $key = openssl_get_privatekey($privateKey);
    $data = base64_decode($data);
    $result = openssl_private_decrypt($data, $decrypted, $key,OPENSSL_PKCS1_OAEP_PADDING);
    if ($result) {
        # code...
        $decrypted_data = base64_decode($decrypted);
        return json_decode($decrypted_data);
    }
    return "No data";
}

?>

VerifySignature.php

<?php
include('./Decrypt.php');


$cert = file_get_contents("../keys/public_key.pem");
/**Run node index.js in terminal to get data & signature */
$data = "o4XuRo4Im3wkJImjLq96XvODUzR5Y+1GCqViKQqStyoidS8+9aQbLrWFpjhyHuE019YzJLHhuWxWlo7yfR3aebm5kObvq/QBe821dZgnOLtvdeUM4NP8iapjV945DsjRkp9g8vEwH3gGN0p/RrzWvbsF57OZ3eLRFjkFv2TS9PcUVlVHYbxpTjfhskpOQrDJeJJZjnCaRyPOa2VG4k3Y3p7WJzU+oT9DJK2aUscuS8zyDvLHSWvS09KOe/5xu+554Q54QHaLmAUxqu//4EjK+8yDko8Ji3mnmpFD0eyXfO2uMlw8dAUJ4w1++hNr7pr60K4rV47aCP1mh6za9lzmUg==";


$signature = "7MC7xeKz+wbBTm1uxcKKV6AS3hM5TUS9T2ZWOxnxZNptBvClsoVktdfb8LVCTaDOKU9dopawZhcLl1fPZwHSoeQMhkkI2IRq9eHry4XWmXyDwSTLn+90AIdyxh+RuFrasGvcOmjRc75Eij393eDfl/MHyVeipIZXMUrWmRTgIjekXEffsoVrpuEGygGnltHMINXA+H1EbsFfJL4ok8zm4JhX8NdZSAcM3zeHrsf1DXbDRPOm4rwdZiuR5y4JGiVKXnEqfu3MA+tllQObE0UTngaUVVea5BFAjMYgE58cvYslzUbQAzKJERfABMg+LeBBuWTRPMrA4y+xKf8r2UHUBg==";

$pubkeyid = openssl_pkey_get_public($cert);
//verify signature
$result = openssl_verify($data, base64_decode($signature), $pubkeyid,OPENSSL_ALGO_SHA256);
// $result = openssl_verify($data, $signature, $pubkeyid,OPENSSL_ALGO_SHA256);

if ($result == 1) {
    # code...
    var_dump("Valid Signature");
    $decrypted = decrypt($data);
} else {
    var_dump("Invalid Signature");
}
?>
desh
  • 627
  • 1
  • 7
  • 19
  • 2
    This seems to be a very complex approach to solving a program that would probably be better addressed by just using HTTPS. – Quentin Jan 16 '23 at 13:58
  • Have to ask, is the private key actually located at `../keys/private_key.pem`? – zanderwar Jan 16 '23 at 13:58
  • @Quentin he doesn't stipulate what he's using it for, there is a plethora of reasons why you would want to send an encrypted string over the wire – zanderwar Jan 16 '23 at 13:59
  • @zanderwar Yes it is , – desh Jan 16 '23 at 14:01
  • 2
    [openssl_error_string](https://www.php.net/manual/en/function.openssl-error-string.php) will tell you what the issue was if it's related – zanderwar Jan 16 '23 at 14:01
  • 1
    @zanderwar — Yes, and almost all of those reasons are best addressed by using a tried and tested method instead of reinventing the wheel. There are some exceptions, but it looks like the OP didn't consider just using HTTPS. – Quentin Jan 16 '23 at 14:01
  • @zanderwar I am actually using it for assymetric encryption, where we need to encrypt a data and generate a signature on the client's side & sending it over to a server. Both client and server exist in two different domains. – desh Jan 16 '23 at 14:03
  • @desh — Well, that's what HTTPS is designed for. – Quentin Jan 16 '23 at 14:03
  • 1
    Crude assumptions none the less. OP could require it to be sent via query string, HTTPS is hardly relevant in that scenario – zanderwar Jan 16 '23 at 14:07
  • 1
    Decryption with the PHP code works on my machine (using my own data/keys), so it's probably your data/keys. Post some sample data that can be used to reproduce the problem. – Topaco Jan 16 '23 at 14:13
  • @Topaco can, let me pass some sample data. You most probably need the public key and private key i am using right ? – desh Jan 16 '23 at 14:21
  • 3
    You should post complete test data: plaintext, ciphertext, private and public key. Of course sample keys (no productive keys). – Topaco Jan 16 '23 at 14:30
  • @zanderwar: The query string is encrypted when using HTTPS. – President James K. Polk Jan 16 '23 at 14:37
  • 1
    So does he leave it unencrypted so that his users can see everything within it simply from the URL just because its encrypted in transit and safe only from man in the middle attacks? Do we reach out to the SAML2.0 developers and tell them it's pointless to encrypt query strings and that their ADFS user information is safe? I don't get the point you're trying to make, he's here for a simple solution, no one has offered an informative answer for what you're preaching – zanderwar Jan 16 '23 at 14:52
  • @Topaco Hi there, I have posted my sample data ya. Thank you very much. Hopefully it is clear, if it is not clear, please do let me know what other information that I need to provide. Thank you very much – desh Jan 16 '23 at 15:37
  • You seem to confuse decryption and verification. The posted website examples verify a signature generated using RSA with SHA256 and PKCS#1 v1.5 padding. However, the posted PHP code performs decryption. These are different things. – Topaco Jan 16 '23 at 15:51
  • @Topaco What I am trying to suggest is that the data/clear text & signature matches the private key and public key . My php code verifies the signature then decrypts the data. I did not post the verification part because it verifies successfully , the part where it fails is the decryption part from the PHP. Sorry for causing the confusion. – desh Jan 16 '23 at 15:55
  • 1
    The ciphertext from Data Set 1 can be decrypted with the PHP code, see https://paiza.io/projects/OdHabdIDK9YkH3eQG0sNig. You may have the wrong key in your file system. – Topaco Jan 16 '23 at 16:15
  • @Topaco THANK YOU VERY MUCH ! really appreciate your help. It works! Than you once again. – desh Jan 16 '23 at 16:20

1 Answers1

2

Others have suggested to just lean on HTTPS, a few things to bare in mind:

  • HTTPS encrypts the communication between the client and the server using SSL/TLS protocols. This protects all data, including query strings in URLs, from being tampered with or intercepted while in transit.
  • Query strings in URLs are sent as regular text as part of the request, but when HTTPS is used, the entire request, including the query strings, are encrypted, making them secure during the transmission.

Now to your problem...

Assuming your public key is definitely married to your private key.

OpenSSL functions are typically used to decrypt payloads from OpenSSL functions, whilst both OpenSSL and JSEncrypt use the RSA algorithm, it's fair to say that their implementation may be different.

You could try using phpseclib

composer require phpseclib/phpseclib
<?php

use phpseclib3\Crypt\PublicKeyLoader;

function decrypt($encrypted)
{
    $privateKey = file_get_contents('/path/to/your/private.key');

    /** @var \phpseclib3\Crypt\RSA\PrivateKey $loader */
    $loader = PublicKeyLoader::loadPrivateKey($privateKey);
    $decrypted = $loader->decrypt(base64_decode($encrypted));

    return json_decode(base64_decode($decrypted), true);
}

Disclaimer: Code above is untested

zanderwar
  • 3,440
  • 3
  • 28
  • 46
  • 1
    Even though the OP asked specifically about OpenSSL I'd encourage them to check this out. Once you know about phpseclib, you'll find other places eventually you can use it, too. – Chris Haas Jan 16 '23 at 14:38
  • @zanderwear Hi, May I know the phpseclib u are using, is it version 2 or 3 ya. I am using version 3 , it seems that it cannot instantiate the RSA Class . It produces an error of Cannot instantiate abstract class phpseclib3\Crypt\RSA. – desh Jan 16 '23 at 15:20
  • See [this](https://phpseclib.com/docs/why#phpseclib-30-vs-phspeclib-10--20). In version 3 you should use `PublicKeyLoader` to figure things out for you. – Chris Haas Jan 16 '23 at 15:31
  • Updated the answer, for more information refer to [the documentation](https://phpseclib.com/docs/rsa#rsaencryption_pkcs1) (also thanks Chris) – zanderwar Jan 16 '23 at 15:33
  • Thank you both. Really appreciate all the help given. – desh Jan 16 '23 at 16:27