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

时间:2014-08-20 09:01:50

标签: php url mcrypt

m使用

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));
}

关于加密:201433~58~g@fds.com~20140820142427

我得到:%2BAihYMLwpwrsmL4lSGGzwFTfonvdCyOb%2BCGEUJ%2F%2BE%2F7ZnvgwFRYFtlazQeSrVjUjyaaGZADK8%2BZyynIGxyt4VQ%3D%3D

解密:%2BAihYMLwpwrsmL4lSGGzwFTfonvdCyOb%2BCGEUJ%2F%2BE%2F7ZnvgwFRYFtlazQeSrVjUjyaaGZADK8%2BZyynIGxyt4VQ%3D%3D

我得到:201433~58~g@fds.com~20140820142427但是

当字符串格式错误时,删除某些字符

像这样:%2BAihYMLwpwrsmL4lSGGzwFTfonvdCyOb%2BCGEUJ%2F%2BE%2F7Z

解密我得到:201433~58~g@fds.com~201408201424O#¿W«Gݽˋ¯ È#'oP´ŸØw\Â⦑

我怎样才能发现这种异常?

1 个答案:

答案 0 :(得分:0)

首先,我想在您的代码中列出一些缺陷:

  • Don't use ECB mode
  • 您正在使用MCRYPT_RIJNDAEL_128进行加密,但是您获得MCRYPT_RIJNDAEL_256的IV大小。 (顺便说一句,在ECB模式下忽略IV,这是不使用它的原因之一)
  • 您还使用MCRYPT_RAND作为随机源,这是不安全的。您应该使用MCRYPT_DEV_URANDOM(也就是new default in PHP 5.6)。
  • 您不必urlencode()生成的密文,Base64编码是网址安全的。

现在,回答你的问题......这是通过HMAC完成的。使用HMAC的最简单方法是在其前面加上密文(你也应该用IV做;不要担心,这不是秘密):

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);
}

请注意,加密密钥和HMAC密钥不同 - 它们大多数是相同的密钥。另外,对于Rijndael-128,你应该创建一个128位(或16字节)的随机密钥,这不是你可以用键盘输入的东西。以下是如何生成一个:

$encKey = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);