I am in need of symmetric encryption and decryption in a pair of PHP scripts. I am using mcrypt_encrypt and crypt_decrypt. To test this, I have the following code:
$encrypted_token = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $ENCRYPTION_SECRET, $refresh_token, MCRYPT_MODE_ECB);
$encrypted_encoded_token=base64_encode($encrypted_token);
echo "\nEncrypted Token: " . $encrypted_encoded_token . "\n";
To test this, in the same PHP script I do the following:
$decoded_refresh_token = base64_decode($encrypted_encoded_token);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $ENCRYPTION_SECRET, $decoded_refresh_token, MCRYPT_MODE_ECB);
echo "\nDecrypted Token After decrypt: " . $decrypted . "\n";
My input $refresh_token is a long string of characters that looks something like this (only longer):
AQCNKTZhaWTmUl3WvHOtlkv2Vc-Ybkl24D5Zp1lZPLBraTxrr-YQhErXrI2IWWEIWk5lnBc1k
The Decrypted Token After decrypt looks something like this:
AQCNKTZhaWTmUl3WvHOtlkv2Vc-Ybkl24D5Zp1lZPLBraTxrr-YQhErXrI2IWWEIWk5lnBc1k�������������������
My $ENCRYPTION_SECRET is 32 characters long. The base64_encode and decode are because I am json_encoding and decoding the token in a Post.
What am I doing wrong?
Those extra characters are indeed bytes valued zero. PHP's mcrypt uses 0..n - 1
bytes of zero padding, where n
is the blocksize. In other words, if the plaintext is already a multiple of the blocksize then it doesn't pad. Otherwise it pads up to the block size.
Now you are using MCRYPT_RIJNDAEL_256
which is not AES, but Rijndael with a block size of 256 bits. So the number of bytes added are 0..31 bytes. If you view those as a string they get converted to question marks or removed, depending on what you view the string with. In the C-library of mcrypt that probably made more sense as zero terminates a null-terminated string.
Nowadays the ad-hoc standard is PKCS#7 padding, which adds 1..blocksize
of padding bytes. If x
is the number of padding bytes then x
is also the value of the bytes added. PKCS#7 padding is deterministic, i.e. you can always unpad, no matter the value of the plaintext. Zero padding behaves largely the same way, unless the plaintext contains zero characters at the end. This is however never the case for printable strings (in ASCII, latin or UTF-8).
Finally, to remove the padding, simply perform rtrim(plaintext, "\0")
and you'll get the original string.