PHP: mcrypt controls start of line for garbage
I need medium to strong encryption on the server, so I decided to use mcrypt with PHP. If I use functions below the start of my original string, it becomes binary garbage after decryption. (This is not a common problem of getting added extra garbage, my string changes instead.) According to the documentation, mcrypt_encrypt () should have enough characters to match the block size of the chosen algorithm, but I suspect it doesn't work.
However, if I put it manually in a 128 bit (16 byte) Rijndael block size, it doesn't work either. The only way I can get this to work is to add some line long enough to (probably) cover the garbage block and add a known prefix like "DATA #" between that line and my data. After decryption, this block was partially garbled, but my prefix and all data after that were decrypted correctly.
$GLOBALS['encryptionmarker'] = 'DATA#';
function encrypt($plain, $key) {
/*
// workaround because beginning of decrypted string is being mangled
// so we simply prefix with some text plus marker
$prefix = str_pad('', 128, '#', STR_PAD_RIGHT).$GLOBALS['encryptionmarker'];
$plain = $prefix.$plain;
*/
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $plain, MCRYPT_MODE_CFB,
mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
MCRYPT_DEV_URANDOM));
return $encrypted;
}
function decrypt($encrypted, $key) {
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CFB,
mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
MCRYPT_DEV_URANDOM));
/*
// workaround: remove garbage
$pos = strpos($decrypted, $GLOBALS['encryptionmarker']);
$decrypted = trim(substr($decrypted, $pos + strlen($GLOBALS['encryptionmarker'])));
*/
return $decrypted;
}
What's wrong with my functions? Why should I prefix my data (I find this to be a dirty workaround, so I would like to fix it)?
Keeping encrypted data is not a problem; decrypting it immediately after encrypting it without storing it in the database results in the same errors.
source to share
Your problem is that you are generating a new, different random IV on the receiving end. It doesn't work as you saw.
The recipient needs to know the IV that the sender used; so you have to send it along with encrypted data and transfer it to mcrypt_decrypt()
.
Note that you must also use mhash()
with a key (another key to the encryption key) to generate an HMAC over the message and validate it on the receiving end. If you don't, the man-in-the-middle can trivially change parts of your message without discovering it.
source to share
Use the same IV in en- and decryption. IV is not a shared secret, but must be shared. You can refer to Wikipedia: IV
$IV = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
MCRYPT_DEV_URANDOM));
IV must be transmitted ONE. You can increase the IV for each packet. But this can be done on both sides independently.
source to share