Search code examples
phpencryptionblowfish

php openssl_decrypt() parameters (encrypted previously by perl Crypt::CBC)


My encryption/decryption environment works fine in Perl. Reading that information from php is my problem I am seeking an answer for. Below is my test case, I'd like the php to print $decryption correctly. Currently I get a blank.

#(perl 5)  the encryption method
use Crypt::Blowfish;
use Crypt::CBC;
$cipher = Crypt::CBC->new( -key    => "example",
                           -cipher => 'Blowfish',
                           -iv     =>  '12345678',
                           -header      => 'none'
                          );

$pj="Testing encryption";
$pje = $cipher->encrypt("$pj");##
$pjf = unpack("H*", $pje), "\n";

open (FILE2,">data.txt");
print FILE2 "$pjf";
close (FILE2);

#(php 7.3)
<?php 

$data = file_get_contents("data.txt");
$encryption = pack("H*", $data);
$ciphering = "blowfish";
$options = 0; 

// Display the encrypted string 
echo "Encrypted String: " . $encryption . "\n"; 

// Non-NULL Initialization Vector for decryption 
$decryption_iv = '12345678'; 

// Store the decryption key 
$decryption_key = "example"; 

// Use openssl_decrypt() function to decrypt the data 
$decryption=openssl_decrypt ($encryption, $ciphering,  
        $decryption_key, $options, $decryption_iv); 

// Display the decrypted string 
echo "Decrypted String: " . $decryption; 
echo""
?> 

(thank You)


Solution

  • When the Crypt::CBC object is created in the Perl code, the following is defined with regard to the key, see here:

    • Because the -keysize argument isn't specified, the key has the maximum size of 56 bytes.
    • Since the -literal_key argument isn't specified, the value is interpreted as a passphrase and the actual key is derived from it (usually in combination with a salt).
    • Since the -salt argument isn't specified, no salt is used, so the key is derived only from the passphrase.

    For the example in the posted Perl code the ciphertext as hexadecimal string ($pjf) is:

    ecc9d0b2449ef433285ade2d02ac19184866f5f9b814bde2 
    

    To successfully decrypt this ciphertext with the posted PHP code, the following changes are necessary:

    • The key must be derived from the passphrase. This is done in the expandKey function. The key is generated by creating the MD5 hash of the passphrase. If the key doesn't have the required length, it's hashed again and appended to the previous hash. This happens until a key with the required length has been generated.

    • The OPENSSL_RAW_DATA flag must be set, because the encrypted data are passed to openssl_decrypt as raw data and not Base64 encoded. Alternatively, the encrypted data must be passed Base64 encoded to openssl_decrypt.

    PHP code including changes:

    $encryptedDataHex = 'ecc9d0b2449ef433285ade2d02ac19184866f5f9b814bde2';
    $encryptedData = hex2bin($encryptedDataHex);
    
    $key = expandKey('example'); 
    $iv = '12345678'; 
    $cipher = 'bf-cbc'; // 'blowfish' also works
    $options = OPENSSL_RAW_DATA; 
    
    $decryptedData = openssl_decrypt($encryptedData, $cipher, $key, $options, $iv); 
    
    echo 'Decrypted data: ' . $decryptedData; 
    
    function expandKey($key){
        $key = md5($key, true);
        while(strlen($key) < 56){
            $key .= md5($key, true);
        }
        return substr($key, 0, 56);
    }