Search code examples
phpencryptionplsqlmcryptdbms-crypto

Encrypt string with PLSQL then decrypt with PHP


I have an application where I'm trying to encrypt a string using PLSQL (dbms_crypto.encrypt), save it to a cookie, then read the cookie using PHP (mcrypt_decrypt) and decrypt the string. I'm having a heck of a time getting the string to decrypt. Hopefully someone has done this before and can help me out?

Here's the PLSQL code: (Running in Oracle 11)

set serveroutput on

set linesize 121

DECLARE
 cookieInfo VARCHAR2(500) := 'Cookie@Data@Goes@Here';
 cookieInfo_raw RAW(500) := utl_raw.cast_to_raw(cookieInfo);
 l_key     RAW(128) := utl_raw.cast_to_raw('abcdefgh');

 l_encrypted_raw RAW(2048);
BEGIN
  dbms_output.put_line('Original : ' || cookieInfo);

  l_encrypted_raw := dbms_crypto.encrypt(cookieInfo_raw,
  dbms_crypto.des_cbc_pkcs5, l_key);

  dbms_output.put_line('Encrypted : ' ||
  l_encrypted_raw);

END;
/

If I'm reading it correctly, the data is being encrypted using DES with CBC and PKCS5. Here's the output from the code:

Original : Cookie@Data@Goes@Here
Encrypted : 3CB6F761112AE388DDA1AE973042D08472B06C2170587D5E

PHP obviously uses MCRYPT_decode, but I can't seem to get the output right. I have pieced together a script that does part of the job, but the output always looks encoded. My problem is that I'm not really up to speed on what all the options really mean. CBC and PKCS5 are a bit Greek to me. It also seems like part of the problem may be text encoding (HEX vs RAW / BIN). I think I'm just confused.

Here's my PHP code: (Running on PHP 5.3.10)

<?php
    $input = "Matt@Danskine@L00579796";
    $key = "abcdefgh";
    $data = "DC979D2F301CA90A548B2F749237B5AF783F13A8CBECE03C";
    $iv = "";

    $decrypt = mcrypt_decrypt(MCRYPT_DES, $key, $data, MCRYPT_MODE_CBC);
    $decrypt = bin2hex($decrypt);

    $block = mcrypt_get_block_size('des', 'cbc');
    echo "BLOCK: ". $block ."<br>";
    $pad = ord($decrypt[($len = strlen($decrypt)) - 1]);
    echo "PAD: ". $pad ."<br>";
    $output = substr($decrypt, 0, strlen($decrypt) - $pad);

    echo "OUTPUT: ". $output;
?>

And the output:

OUTPUT: 793fe26d587e144f140d70e6013374acb082ff9e411

Any help would be greatly appreciated. This little issue is holding up a much larger project.

Thanks in advance.


Solution

  • Your data is in hex and you need to convert it back to bin for decryption. It is not necessary to convert bin2hex after decryption.

    $input = "Matt@Danskine@L00579796";
    $key = "abcdefgh";
    $data = "DC979D2F301CA90A548B2F749237B5AF783F13A8CBECE03C";
    $iv = "";
    
    /*
     * Convert hex to bin data
     * 
     * This code is courtesy of "Johnson"
     * http://php.net/manual/en/function.hex2bin.php#110973
     * Not needed if you have PHP > 5.4
     * Then you can just use hex2bin() builtin
     */
    $data = hextobin($data); 
    
    $decrypt = mcrypt_decrypt(MCRYPT_DES, $key, $data, MCRYPT_MODE_CBC);
    
    $block = mcrypt_get_block_size('des', 'cbc');
    echo "BLOCK: ". $block ."<br>";
    $pad = ord($decrypt[($len = strlen($decrypt)) - 1]);
    echo "PAD: ". $pad ."<br>";
    $output = substr($decrypt, 0, strlen($decrypt) - $pad);
    
    echo "OUTPUT: ". $output;
    
    function hextobin($hexstr)
    {
        $n = strlen($hexstr);
        $sbin="";  
        $i=0;
        while($i<$n)
        {      
            $a =substr($hexstr,$i,2);          
            $c = pack("H*",$a);
            if ($i==0){$sbin=$c;}
            else {$sbin.=$c;}
            $i+=2;
        }
        return $sbin;
    }