CJdriver
CJdriver

Reputation: 458

3DES PHP Encryption Not Decrypting Properly

I'm using the following code to encrypt information that will be passed to an external site on the end of the link URL. Right now it's able to do the encrypting and decrypting itself, but when I go to online Decryptors (online-domain-tools.com, tools4noobs.com) I'm seeing extra symbols added or it's not showing the right content whatsoever. Of course I'm new to this. What I have, I have pieced together from other questions (php-equivalent-for-java-triple-des-encryption-decryption, php-equivalent-encryption-decryption-tripledes, php-encrypt-decrypt-with-tripledes-pkcs7-and-ecb). Thanks for any help or direction!

I can only use 3DES with CBC.

PHP Code:

$key = "12AB12AB12AB12AB12AB12AB";
$iv = "12AB12AB";
$cipher = mcrypt_module_open(MCRYPT_3DES, '', 'cbc', '');

// MESSAGE
$message = "[email protected]&account=987654321&role=2";
echo 'Message:::  ' .$message .'<br />';

// ENCRYPTED
$encrypted = Encryptor($message);
echo 'Encrypted:::  ' .$encrypted .'<br />';

// DECRYPTED
$decrypted = Decryptor($encrypted);
echo 'Decrypted:::  ' .$decrypted .'<br />';

function Encryptor($buffer) {
  global $key, $iv, $cipher;

  // get the amount of bytes to pad
  $extra = 8 - (strlen($buffer) % 8);

  // add the zero padding
  if($extra > 0) {
    for($i = 0; $i < $extra; $i++) {
      $buffer .= "\0";
    }
  }
  mcrypt_generic_init($cipher, $key, $iv);
  $result = bin2hex(mcrypt_generic($cipher, $buffer));
  mcrypt_generic_deinit($cipher);
  return $result;
}

function Decryptor($buffer) {
  global $key, $iv, $cipher;

  mcrypt_generic_init($cipher, $key, $iv);
  $result = rtrim(mdecrypt_generic($cipher, hex2bin($buffer)), "\0");
  mcrypt_generic_deinit($cipher);
  return $result;
}

function hex2bin($data)
{
  $len = strlen($data);
  return pack("H" . $len, $data);
} 

Upvotes: 3

Views: 1331

Answers (1)

Gennadiy Litvinyuk
Gennadiy Litvinyuk

Reputation: 1597

To be short: Your code is correct. You can't test your encryption with provided tools.

Both tools do not allow to enter your IV.

The IV should be unique and can be transferred publicly.

Using wrong IV by decoding gives you wrong part at the beginning of decrypted data.

Here is OO version. It uses zero padding (built in PHP), like your code. It also makes no padding **, if the original message is already aligned.

<?php

$key = "12AB12AB12AB12AB12AB12AB";
$iv = "12AB12AB";

// MESSAGE
$message = "[email protected]&account=987654321&role=22";
echo 'Message:::   ' . $message . PHP_EOL;


$cryptor = new Crypt3Des();

$encryptedMessage = $cryptor->encrypt($message, $key, $iv);
echo 'Encrypted:::  ' . bin2hex($encryptedMessage) . PHP_EOL;

$decryptedMessage = $cryptor->decrypt($encryptedMessage, $key, $iv);
echo 'Decrypted:::  ' . $decryptedMessage . PHP_EOL;

class Crypt3Des
{
    private $cipher;

    public function __construct()
    {
        $this->cipher = mcrypt_module_open(MCRYPT_3DES, '', 'cbc', '');
    }

    public function encrypt($data, $key, $iv)
    {
        mcrypt_generic_init($this->cipher, $key, $iv);
        $result = mcrypt_generic($this->cipher, $data);
        mcrypt_generic_deinit($this->cipher);
        return $result;
    }

    public function decrypt($encryptedData, $key, $iv)
    {
        mcrypt_generic_init($this->cipher, $key, $iv);
        $result = mdecrypt_generic($this->cipher, $encryptedData);
        mcrypt_generic_deinit($this->cipher);
        $result = rtrim($result, "\0");
        return $result;
    }
}


// Before 5.4.0
if (!function_exists('hex2bin')) {
    function hex2bin($data)
    {
        $len = strlen($data);
        return pack("H" . $len, $data);
    }
}

Upvotes: 1

Related Questions