0
votes

I am trying to write a simple 2 way encryption class using mcrypt to learn more about encryption, and everything seems to be working fine. The issue that I am having is I am receiving a PHP error stating "IV parameter must be as long as the block size" however, the encryption and decryption both seem to be working. Is my understanding of IV size incorrect? Any push in the right direction would be greatly appreciated. Thanks.

Edit: I am actually wrong, the encryption/decryption is not working and I am unsure why.

Edit2: Alright, I figured out why the encryption wasn't working (thanks to Robert) but the original problem still exists.

<?php

ini_set("display_errors", 1);

class IDBCrypt {

    private $iv_size, $hash_type, $hash_size, $hash_key, $encryption_key;

    const SECRET_KEY = "Ep8+NFPfybsJn26ZFyPn213WTI";
    const HASH_KEY = "mU2YjBiZDVmYjBiOWUyNmE";
    const HASH_TYPE = "sha256";
    const HASH_SIZE = 64;

    /** 
      * For SHA256 hashing algorithm
      * each digit requires 4 bits of
      * memory. This means that you need
      * 64 digits to represent a 256 bit 
      * hash, thereby making the size of 
      * a hash generated with this algorithm
      * 256 bits, with a length of 64
      */

    function __construct() {

        /* Constructor */

    }

    function encrypt( $data ) {

        // Generate an IV to encrypt with
        $iv = mcrypt_create_iv( self::HASH_SIZE, MCRYPT_RAND );
        $hashed_iv = hash_hmac( self::HASH_TYPE, $iv, self::HASH_KEY );

        // echo $iv ."<br><br>";

        // Encrypt plain text
        $cipher_text = mcrypt_encrypt( MCRYPT_RIJNDAEL_128, self::SECRET_KEY, $data, MCRYPT_MODE_CBC, $hashed_iv );

        // Base64 encode and salt the data
        $cipher_text_64 = base64_encode( $hashed_iv . $cipher_text );

        return $cipher_text_64;

    }

    function decrypt( $data ) {

        // Base64 decode the cipher text
        $ciphertext_dec = base64_decode( $data );

        // retrieves the IV/salt from the cipher text
        $iv_dec = substr( $ciphertext_dec, 0, self::HASH_SIZE );

        // retrieves the cipher text (everything except the $iv_size in the front)
        $ciphertext_dec = substr( $ciphertext_dec, self::HASH_SIZE );

        $plaintext = mcrypt_decrypt( MCRYPT_RIJNDAEL_128, self::SECRET_KEY, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec );

        return $plaintext;

    }

}

$crypt = new IDBCrypt();

$string = $crypt->encrypt("Greetings from encryption and beyond");

echo $string . "<br>";

echo $crypt->decrypt($string);

?>
1
You should definitly check mcrypt_enc_get_iv_size() functionRobert
where do u set 'iv_size' i can't find it?Robert
Thanks for that catch, I was going crazy trying to figure out why the encryption broke. Now that the encryption is working, I'm still getting the original error "The IV parameter must be as long as the blocksize". I've edited the code to reflect that fix.Mike

1 Answers

1
votes

I think problem in mcrypt_function()

You pass hashed IV instead of IV created by mcrypt_create_iv() that is why size is different.

You can get proper IV size with function mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128 , 'cbc');

The proper length of IV is 16 bytes for RIJNDAEL 128(other mode than ECB, ECB doesn't use IV).

So you can change(because you passed 64)

$iv = mcrypt_create_iv( self::HASH_SIZE, MCRYPT_RAND );

to

$iv = mcrypt_create_iv( 16, MCRYPT_RAND );

And it will work.

Edit:

Check this simple example. Of course padding needs to be removed

$text ='asdf';
$key = 'Ep8+NFPfybsJn26ZFyPn213WTI';
$iv = mcrypt_create_iv( 16, MCRYPT_RAND );
$cipher_text = mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);

echo mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $key, $cipher_text , MCRYPT_MODE_CBC, $iv);