Decryption of encrypted text in PHP

2019-09-18 16:24发布

I am trying to decode encrypted data in PHP, however the return value keeps coming back as null.

The data to be decrypted comes into the PHP file as a data argument.

$dataArg1 = $_REQUEST["data"];

// Retrieve $encryptedData from storage ...
//
// Load the private key and decrypt the encrypted data
$encryptedData = $dataArg1;
$privateKey = array ( array(123456,654321,123456), array(123456,1234),
                      array(1234567,4321)
                    );
    openssl_private_decrypt($encryptedData, $sensitiveData, $privateKey);

The function above comes from the second response of another posting here on Stack Overflow: How to encrypt data in javascript and decrypt in php?

I assume that the decrypted value is in the PHP variable, $sensitiveData.

When I echo that to the screen, I get nothing.

echo("sensitiveData=[$sensitiveData]<br />");

Thoughts?

UPDATE: The return value from openssl_private_decrypt() is FALSE, and the return value is NULL.

UPDATE 2: I created the public/private key from the following URL. http://shop-js.sourceforge.net/crypto2.htm

At the bottom, there is the line: And put the following in your private script (probably on your local hard disk -- not on the internet -- if your private key is found this whole thing is useless.)

<script>
function decrypt() {
 // key = [ [d], [p], [q] ];
 var key=[[123456789,123456789,123456789],[123456789,1234],[123456789,4321]];
 document.form.text.value=rsaDecode(key, document.form.text.value);
}
</script>
(actual values changed)

I copied translated the "var key=" line to PHP (per my other posting). Translation above using embedded arrays. I then past that key to the decrypt function.

My thought is that the PHP documentation calls the private key "mixed". I am wondering if maybe I need a different format for the private key.

Here is the output:

dataArg1=[jmOdss9ktFc\"WO5eltUZXt0rpqS1NluNKa]

bResult=[]

sensitiveData=[]

var_dump=[NULL ]

1条回答
我欲成王,谁敢阻挡
2楼-- · 2019-09-18 16:27

$privateKey has to be in a certain format. You can't just throw in random data to it and magically expect it to know what to do with it.

Also, looking at the js you're using, it's not just doing RSA. It has a function named base64ToText. It's decoding the ciphertext with that, taking the first byte as the length of the "encrypted session key", getting the "encrypted session key", decrypting that with RSA and then using that as the key to RC4 to decrypt it. But there are a number of problems with that too. Among other things, base64ToText isn't the same thing as PHP's base64_encode as the name might imply.

Anyway I wasn't able to get it to working. Personally, I'd recommend something more like this (which is interoperable with PHP / phpseclib's Crypt_RSA):

http://area51.phpbb.com/phpBB/viewtopic.php?p=208860

That said, I did manage to figure a few things out. Your js lib uses base-28. To convert numbers from that format to one phpseclib uses you'll need to use this function:

function conv_base($num)
{
    $result = pack('N', $num[count($num) - 1]);

    for ($i = count($num) - 2; $i >= 0; --$i) {
        _base256_lshift($result, 28);
        $result = $result | str_pad(pack('N', $num[$i]), strlen($result), chr(0), STR_PAD_LEFT);
    }

    return $result;
}

function _base256_lshift(&$x, $shift)
{
    if ($shift == 0) {
        return;
    }

    $num_bytes = $shift >> 3; // eg. floor($shift/8)
    $shift &= 7; // eg. $shift % 8

    $carry = 0;
    for ($i = strlen($x) - 1; $i >= 0; --$i) {
        $temp = ord($x[$i]) << $shift | $carry;
        $x[$i] = chr($temp);
        $carry = $temp >> 8;
    }
    $carry = ($carry != 0) ? chr($carry) : '';
    $x = $carry . $x . str_repeat(chr(0), $num_bytes);
}

Here's the script I used to confirm the correctness of that:

<?php
include('Math/BigInteger.php'); 

$p = array(242843315,241756122,189); 
$q = array(177094647,33319298,129); 
$n = array(45173685,178043534,243390137,201366668,24520); 

$p = new Math_BigInteger(conv_base($p), 256); 
$q = new Math_BigInteger(conv_base($q), 256); 
$n = new Math_BigInteger(conv_base($n), 256); 

$test = $p->multiply($q); 
echo $test . "\r\n" . $n; 

ie. they match.

I also ported your js's base64ToText to PHP:

function decode($t)
{
    static $b64s = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"';
    $r = '';
    $m = $a = 0;
    for ($n = 0; $n < strlen($t); $n++) {
        $c = strpos($b64s, $t[$n]);
        if ($c >= 0) {
            if ($m) {
                $r.= chr(($c << (8-$m))&255 | $a);
            }
            $a = $c >> $m;
            $m+=2;
            if ($m == 8) {
                $m = 0;
            }
        }
    }

    return $r;
}

Among other potential problems I may have encountered... who knows if their RC4 implementation is correct? Their base64 implementation isn't so it wouldn't be without precedent for the RC4 implementation to be broken too.

查看更多
登录 后发表回答