使用mcrypt获取Scrambled文本以保护php中的url数据

m using

public function encrypt($plain_str,$key)
{
     $str= mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plain_str, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND));
     $str = urlencode(base64_encode($str));
     return  $str ;
}

public function decrypt($cipher_str,$key)
{
    $str = urldecode(base64_decode($cipher_str));
    return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND));
}

on crypting :201433~58~g@fds.com~20140820142427

i get : %2BAihYMLwpwrsmL4lSGGzwFTfonvdCyOb%2BCGEUJ%2F%2BE%2F7ZnvgwFRYFtlazQeSrVjUjyaaGZADK8%2BZyynIGxyt4VQ%3D%3D

on decrypting : %2BAihYMLwpwrsmL4lSGGzwFTfonvdCyOb%2BCGEUJ%2F%2BE%2F7ZnvgwFRYFtlazQeSrVjUjyaaGZADK8%2BZyynIGxyt4VQ%3D%3D

i get :201433~58~g@fds.com~20140820142427 back but

when string is malformed like some character removed

like this : %2BAihYMLwpwrsmL4lSGGzwFTfonvdCyOb%2BCGEUJ%2F%2BE%2F7Z

on decrypting i get : 201433~58~g@fds.com~201408201424O#¿W«Gݽˋ¯ È#'oP´ŸØw\Â⦑

How can i detect this anomoly ?

First of all, I'd like to list some flaws in your code:

  • Don't use ECB mode.
  • You are encrypting using MCRYPT_RIJNDAEL_128, but you're getting the IV size for MCRYPT_RIJNDAEL_256. (btw, IV is ignored in ECB mode, which is one of the reasons why not to use it)
  • You are also using MCRYPT_RAND as your randomness source, which is not secure. You should use MCRYPT_DEV_URANDOM (that is also the new default in PHP 5.6).
  • You don't have to urlencode() the resulting ciphertext, Base64 encoding is URL-safe.

Now, to answer your question ... this is done via a HMAC. The easiest way to use a HMAC is to prepend the cipher-text with it (which you should do with the IV as well; don't worry, it's not a secret):

public function encrypt($plainText, $encKey, $hmacKey)
{
    $ivSize = mcrypt_get_iv_size('rijndael-128', 'ctr');
    $iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
    $cipherText = mcrypt_encrypt('rijndael-128', $encKey, $plainText, 'ctr', $iv);

    $cipherText = $iv.$cipherText;
    $hmac = hash_hmac('sha256', $cipherText, $hmacKey, true);
    return base64_encode($hmac.$cipherText);
}

public function decrypt($cipherText, $encKey, $hmacKey)
{
    $cipherText = base64_decode($cipherText);

    if (strlen($cipherText) <= 32)
    {
        throw new Exception('Authentication failed!');
    }

    $recvHmac = substr($cipherText, 0, 32);
    $cipherText = substr($cipherText, 32);

    $calcHmac = hash_hmac('sha256', $cipherText, $hmacKey, true);

    if ( ! hash_equals($recvHmac, $calcHmac))
    {
        throw new Exception('Authentication failed!');
    }

    $ivSize = mcrypt_get_iv_size('rijndael-128', 'ctr');
    $iv = substr($cipherText, $ivSize);
    $cipherText = substr($cipherText, $ivSize);

    return mcrypt_decrypt('rijndael-128', $encKey, $cipherText, 'ctr', $iv);
}

Please note that the encryption key and HMAC key are different - they most NOT be the same key. Also, for Rijndael-128, you should create a 128-bit (or 16-byte) random key, it is not something that you can just type in with your keyboard. Here's how to generate one:

$encKey = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);