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.

+2


source to share


2 answers


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.

+5


source


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.

+2


source







All Articles