Skip to content
Advertisement

AES/CBC/PKCS5 Padding | Alternate to mcrypt_get_block_size() in Php OpenSSL

Problem Statement:

I’m trying to integrate API which AES/CBC/PKCS5 Padding. After some research I found the implementation on following article.

However, In this article there were using mcrypt which is deprecated and removed from PHP 7.2. Hence, I’m looking to modify above implementation in openssl.

There is function pkcs5_pad for PKCS5 padding the data which require parameter as data and blocksize. And there are no alternative to mcrypt_get_block_size in openssl.


Code Snippet

pkcs5_pad & pkcs5_unpad

function pkcs5_pad ($text, $blocksize)
{
    $pad = $blocksize - (strlen($text) % $blocksize);
    return $text . str_repeat(chr($pad), $pad);
}


function pkcs5_unpad($text)
{
    $pad = ord($text{strlen($text)-1});
    if ($pad > strlen($text)) return false;
    if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
    return substr($text, 0, -1 * $pad);
}

Trying to convert following

$paddedData = pkcs5_pad(
                            $data, 
                            mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)
                        );


$encrypteddata = mcrypt_encrypt(
                                    MCRYPT_RIJNDAEL_128,
                                    hex2bin(md5($key)),
                                    $paddedData,
                                    MCRYPT_MODE_CBC,
                                    $iv
                                );

TO

$paddedData = pkcs5_pad($data);  // How do I getBlock size in OpenSSL. i.e. Alternate to mcrypt_get_block_size

$encrypteddata = openssl_encrypt(
                                    $paddedData, 
                                    $cipher, 
                                    $key, 
                                    $options=OPENSSL_RAW_DATA, 
                                    $iv
                                );

Trial & Error:

I found some file after some research in Github. But didn’t know how to use this file to convert data into pkcs5 padded data.


Advertisement

Answer

The good news is – OpenSSL has a “built in” padding so you don’t have to worry about it.

The full running code below shows you how to encrypt or decrypt a string using a 32 bytes long, randomly generated key for AES-256. The AES mode is CBC, and it is using the PKCS5/7 padding. The output of the encryption is Base64 encoded (usefull for transport via Email), of course you can leave the Base64 en-/decoding out when saving the ciphertext to a file and later read the file for decryption.

Please be aware that there are is no exception handling and the code is for educational purpose:

<?php
function generateRandomAesKey()
{
    return openssl_random_pseudo_bytes(32, $crypto_strong);
}

function generateRandomInitvector()
{
    return openssl_random_pseudo_bytes(16, $crypto_strong);
}

function base64Encoding($input)
{
    return base64_encode($input);
}

function base64Decoding($input)
{
    return base64_decode($input);
}

function aesCbcEncryptToBase64($key, $data)
{
    $iv = generateRandomInitvector();
    $ciphertext = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
    return base64_encode($iv) . ':' . base64_encode($ciphertext);
}

function aesCbcDecryptFromBase64($key, $data)
{
    list($iv, $encryptedData) = explode(':', $data, 2);
    return openssl_decrypt(base64_decode($encryptedData), 'aes-256-cbc', $key, OPENSSL_RAW_DATA, base64_decode($iv));
}

echo 'AES CBC 256 String encryption with random key full' . PHP_EOL;

$plaintext = 'The quick brown fox jumps over the lazy dog';
echo 'plaintext: ' . $plaintext . PHP_EOL;

// generate random key
$encryptionKey = generateRandomAesKey();
$encryptionKeyBase64 = base64Encoding($encryptionKey);
echo 'encryptionKey (Base64): ' . $encryptionKeyBase64 . PHP_EOL;

// encryption
echo PHP_EOL . '* * * Encryption * * *' . PHP_EOL;
$ciphertextBase64 = aesCbcEncryptToBase64($encryptionKey, $plaintext);
echo 'ciphertext: ' . $ciphertextBase64 . PHP_EOL;
echo 'output is (Base64) iv : (Base64) ciphertext' .PHP_EOL;

echo PHP_EOL;
echo 'Cross platform cryptography: AES CBC 256 String encryption with random key (PHP)' . PHP_EOL;
// decryption
echo PHP_EOL . '* * * Decryption * * *' . PHP_EOL;
$decryptionKeyBase64 = $encryptionKeyBase64;
$ciphertextDecryptionBase64 = $ciphertextBase64;
echo 'decryptionKey (Base64): ' . $decryptionKeyBase64 . PHP_EOL;

echo 'ciphertextDecryption (Base64): ' . $ciphertextDecryptionBase64 . PHP_EOL;
echo 'input is (Base64) iv : (Base64) ciphertext' .PHP_EOL;
$decryptionKey = base64Decoding($decryptionKeyBase64);
$decryptedtext = aesCbcDecryptFromBase64($decryptionKey, $ciphertextDecryptionBase64);
echo 'plaintext: ' . $decryptedtext . PHP_EOL;
?>

The output looks like:

AES CBC 256 String encryption with random key full
plaintext:  The quick brown fox jumps over the lazy dog
encryptionKey (Base64): DuLNOxN3BUc+htgigTcQOeJsPuMkF/aBcyVSaXhMcEw=

* * * Encryption * * *
ciphertext: XvXGCOyMrj2ohknIr8k1+A==:nPrEGko/7OFRjiRCgX0Hryz0a+Qc6A9RmRlipWl+R6vslqLBf/8EZtGsf+zwwGAV
output is (Base64) iv : (Base64) ciphertext

* * * Decryption * * *
decryptionKey (Base64): DuLNOxN3BUc+htgigTcQOeJsPuMkF/aBcyVSaXhMcEw=
ciphertext (Base64): XvXGCOyMrj2ohknIr8k1+A==:nPrEGko/7OFRjiRCgX0Hryz0a+Qc6A9RmRlipWl+R6vslqLBf/8EZtGsf+zwwGAV
input is (Base64) iv : (Base64) ciphertext
plaintext:  The quick brown fox jumps over the lazy dog
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement