28

I need a PHP function, AES256_encode($dataToEcrypt) to encrypt the $data into AES-256 and another one AES256_decode($encryptedData) do the opposite. Does anyone know what code should this functions have?

1

4 Answers 4

21

Look at the mcrypt module

AES-Rijndael example taken from here

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);
$key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");
# show key size use either 16, 24 or 32 byte keys for AES-128, 192
# and 256 respectively
$key_size =  strlen($key);
echo "Key size: " . $key_size . "\n";
$text = "Meet me at 11 o'clock behind the monument.";
echo strlen($text) . "\n";

$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);
echo strlen($crypttext) . "\n";

This is the decrypt function

8
  • 15
    -1, AES-256 is different from RIJNDAEL-256. The 256 in AES refers to the key size, where the 256 in RIJNDAEL refers to block size. AES-256 is RIJNDAEL-128 when used with a 256 bit key.
    – ircmaxell
    Commented Jun 22, 2013 at 11:50
  • 3
    @CodesInChaos I've edited the answer according to your observations. Now the answer should be correct.
    – Fabio
    Commented Jun 22, 2013 at 16:00
  • 3
    I just want to emphasize that MACs are really important if active attacks are possible. A well known attack is the "padding oracle" where the reaction of the recipient leaks information about the plaintext allowing byte-by-byte recovery of the plaintext by querying the recipient. Commented Jun 22, 2013 at 16:12
  • 1
    Padding is also important to note: as the mcrypt library in php only supports zero length padding. Where as most people using pkcs#5 or pkcs#7 padding. So always make sure you match the padding up if encrypting and decrypting in different platforms/places (for example: webserver vs mobile app)
    – DEzra
    Commented Mar 18, 2015 at 12:59
  • 3
    PHP has deprecated mcrypt library, it will be removed from PHP version after 7.1. As such, using suggesting mcrypt makes this answer deprecated. See php.net/manual/en/migration71.deprecated.php
    – Dennis
    Commented Jul 6, 2017 at 18:10
18

I need a PHP function, AES256_encode($dataToEcrypt) to encrypt the $data into AES-256 and another one AES256_decode($encryptedData) do the opposite. Does anyone know what code should this functions have?

There is a difference between encrypting and encoding.

Do you really need AES-256? The security of AES-256 versus AES-128 isn't that significant; you're more likely to screw up at the protocol layer than get hacked because you used a 128-bit block cipher instead of a 256-bit block cipher.

Important - Use A Library

A Quick and Dirty AES-256 Implementation

If you're interested in building your own not for the sake of deploying it in production but rather for the sake of your own education, I've included a sample AES256

/**
 * This is a quick and dirty proof of concept for StackOverflow.
 * 
 * @ref http://stackoverflow.com/q/6770370/2224584
 * 
 * Do not use this in production.
 */
abstract class ExperimentalAES256DoNotActuallyUse
{
    /**
     * Encrypt with AES-256-CTR + HMAC-SHA-512
     * 
     * @param string $plaintext Your message
     * @param string $encryptionKey Key for encryption
     * @param string $macKey Key for calculating the MAC
     * @return string
     */
    public static function encrypt($plaintext, $encryptionKey, $macKey)
    {
        $nonce = random_bytes(16);
        $ciphertext = openssl_encrypt(
            $plaintext,
            'aes-256-ctr',
            $encryptionKey,
            OPENSSL_RAW_DATA,
            $nonce
        );
        $mac = hash_hmac('sha512', $nonce.$ciphertext, $macKey, true);
        return base64_encode($mac.$nonce.$ciphertext);
    }

    /**
     * Verify HMAC-SHA-512 then decrypt AES-256-CTR
     * 
     * @param string $message Encrypted message
     * @param string $encryptionKey Key for encryption
     * @param string $macKey Key for calculating the MAC
     */
    public static function decrypt($message, $encryptionKey, $macKey)
    {
        $decoded = base64_decode($message);
        $mac = mb_substr($message, 0, 64, '8bit');
        $nonce = mb_substr($message, 64, 16, '8bit');
        $ciphertext = mb_substr($message, 80, null, '8bit');

        $calc = hash_hmac('sha512', $nonce.$ciphertext, $macKey, true);
        if (!hash_equals($calc, $mac)) {
            throw new Exception('Invalid MAC');
        }
        return openssl_decrypt(
            $ciphertext,
            'aes-256-ctr',
            $encryptionKey,
            OPENSSL_RAW_DATA,
            $nonce
        );
    }
}

Usage

First, generate two keys (yes, two of them) and store them somehow.

$eKey = random_bytes(32);
$aKey = random_bytes(32);

Then to encrypt/decrypt messages:

$plaintext = 'This is just a test message.';
$encrypted = ExperimentalAES256DoNotActuallyUse::encrypt($plaintext, $eKey, $aKey);
$decrypted = ExperimentalAES256DoNotActuallyUse::decrypt($encrypted, $eKey, $aKey);

If you don't have random_bytes(), get random_compat.

7
  • 5
    Can you explain why it would not be a good idea to use the quick-and-dirty implementation in production if it does what is needed?
    – Nathan F.
    Commented Sep 24, 2016 at 1:29
  • You'll find that you want defuse/php-encryption rather than rolling your own or copying and pasting from StackOverflow. The only reason to roll your own is to create toy implementations to teach yourself. Commented Sep 24, 2016 at 2:29
  • 2
    Yes, but say for example I wanted to handle something like stream ciphering from CPP over a socket to PHP. I've not personally looked into defuse's library, but is there a reason the generic AES256 written above wouldn't be suitable? Clearly not the exact code, but something similar as far as building the cipher.
    – Nathan F.
    Commented Sep 27, 2016 at 4:08
  • is this answer still up to date? (Just checking). I do not know the history of halite, but it seems to me that there is currently stable version of v3.2.0 that's available
    – Dennis
    Commented Jul 6, 2017 at 18:48
  • 1
    @ScottArciszewski, The other reason would be "not renting whole building just to store a piece of paper".
    – AaA
    Commented Dec 19, 2019 at 3:10
17

MCRYPT_RIJNDAEL_256 is not equivalent to AES_256.

The way to make RIJNDAEL be decrypted from AES is to use MCRYPT_RIJNDAEL_128 and padd the string to encrypt before encrypting

AES-256 has BlockSize=128bit and KeySize=256bit Rijndael-256 has BlockSize=256bit and KeySize=256bit

Just AES/Rijndael 128bit are identical. Rijndael-192 and Rijndael-256 are not identical to AES-192 and AES-256 (block sizes and number of rounds differ).

2
  • 3
    You're certainly correct, but this post doesn't really answer the question. Commented Jun 22, 2013 at 13:18
  • Thanks @CodesInChaos. The way to make RIJNDAEL be decrypted from AES with openssl is to use MCRYPT_RIJNDAEL_128 and padd the string to encrypt before encrypting with the follwing function: <?php function pkcs5_pad ($text, $blocksize) { $pad = $blocksize - (strlen($text) % $blocksize); return $text . str_repeat(chr($pad), $pad); } ?> Commented Jun 25, 2013 at 9:53
-2
$key = '324325923495kdfgiert734t'; / key used for decryption in jasper code
$text = 'string_to_be_encrypted';
$encrypted = fnEncrypt($text, $key);




function fnEncrypt( $plaintext, $key )
{
$plaintext = pkcs5_pad($plaintext, 16);

return bin2hex(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, hex2bin($key), $plaintext, MCRYPT_MODE_ECB));

}


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



function hex2bin($hexdata) 
{
$bindata = "";

    for ($i = 0; $i < strlen($hexdata); $i += 2) 
    {
      $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
    }

return $bindata;
}
2
  • Please explain your answer in brief to make it more useful for OP and other readers.
    – Mohit Jain
    Commented May 27, 2014 at 8:46
  • 1
    Kindly add the decrypt function also.
    – user216084
    Commented Dec 24, 2014 at 11:42

Your Answer

By clicking “Post Your Answer”, you agree to our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.