0

I have a ciphertext, encrypted in 3DES CBC mode, and I'm having some trouble decrypting it. I have the following information (not actual values):

<?php
// Three 16 character long keys
$key1 = '1234567890123456';
$key2 = '6543210987654321';
$key3 = '6549873210456123';

// The initialisation vector
$ivec = '0102030405060708';

// A token which looks something like this
$token = '2ad82e09e3b4e7c491e4bb9fb7c606e1';
?>

I based my decryption function off the PHP Class that is found in this blog post. It looks like this:

<?php
function decrypt($key,$iv,$token) {
    $td = mcrypt_module_open('tripledes', '', 'cbc', ''); 
    $iv = substr($iv, 0, mcrypt_enc_get_iv_size($td)); 
    $expected_key_size = mcrypt_enc_get_key_size($td); 

    $key = substr(md5($key), 0, $expected_key_size); 
    mcrypt_generic_init($td, $key, $iv);

    $decrypted_string = trim(mdecrypt_generic($td, base64_decode($token)));

    mcrypt_generic_deinit($td); 
    mcrypt_module_close($td); 

    return $decrypted_string;
}
?>

However, I'm not sure how to feed the three keys into the algorithm. I have tried chaining them together like so: $key1.$key2.$key3, and in reverse order, but to no avail.

Any help would be appreciated.

White Elephant
  • 1,361
  • 2
  • 13
  • 28
  • The expected key length is 24 and the expected initialisation vector length is 8, so they keys must be encoded in hex. I'm now using VolkerK's function below on the keys before decryption, but it still doesn't yield the expected plaintext. – White Elephant Jul 17 '09 at 13:48
  • Are you sure '2ad82e09e3b4e7c491e4bb9fb7c606e1' is the base64 encoded version of the token? – VolkerK Jul 17 '09 at 14:10
  • The token is something very similar to that, yes. It looks like it's in hex format too. I've tried base64 encoding the token, converting it from hex and converting it from hex, then base64 encoding it, but no joy. – White Elephant Jul 17 '09 at 14:36
  • Can you provide an encrypted/encoded token, a set of keys and the corresponding decrypted token? – VolkerK Jul 17 '09 at 21:51

2 Answers2

2

// Three 16 character long keys
$expected_key_size is 24, 3*8. The keys are most likely in hex format.
function foo($hex) {
    $rv = '';
    foreach(str_split($hex, 2) as $b) {
        $rv .= chr(hexdec($b));
    }
    return $rv;
}

// Three 16 character long keys
$key1 = '1234567890123456';
$key2 = '6543210987654321';
$key3 = '6549873210456123';

$key = foo($key1.$key2.$key3);
VolkerK
  • 95,432
  • 20
  • 163
  • 226
2

I found the problem with the function in the end. It was a combination of converting the key, IVEC and token from Hex, removing the MD5 hash of the decryption key and removing the Base64 decoding of the resulting plain text.

The padding character that resulted in the plain text was a bit odd, but that's stripped away with rtrim(). It may also be worth noting that the encryption was initially done in JSP using some standard Java libraries, so this might be useful for anyone else going from Java Encryption → PHP Decryption.

Thanks for your help VolkerK, here's the function I ended up using (including your hex function which I haven't added below):

$algorithm = 'tripledes';
$key   = 'F123ACA...'; // Some hex key
$ivec  = 'FE12FA1...'; // Some hex ivec
$token = 'F2ACE12...'; // Some hex token
$mode  = 'cbc';

$key    = foo($key);
$ivec   = foo($ivec);
$token  = foo($token);

function decrypt($key,$iv,$algorithm,$mode,$token) {
    $td = mcrypt_module_open($algorithm, '', $mode, '') ; 
    $iv = substr($iv, 0, mcrypt_enc_get_iv_size($td));

    $expected_key_size = mcrypt_enc_get_key_size($td); 
    $key = substr($key, 0, $expected_key_size); 

    mcrypt_generic_init($td, $key, $iv);

    $response = rtrim(mdecrypt_generic($td, $token), '');

    mcrypt_generic_deinit($td); 
    mcrypt_module_close($td); 

    return $response;
}

$plaintext = decrypt($key,$ivec,$algorithm,$mode,$token);
White Elephant
  • 1,361
  • 2
  • 13
  • 28