在PHP中使用mcrypt函数时检测错误的解密密钥

时间:2015-03-08 12:49:39

标签: php encryption key mcrypt

我已经编写了下面的代码来制作加密和解密机制。一切正常,但如果有人在解密时输入错误的密钥,我想阻止显示不可读的字符。相反,我想向他显示一些错误消息。我该怎么办? 我的PHP代码:

<?php

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

function encrypt($plaintext,$key) {
    global $iv, $iv_size;
    $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
    $ciphertext = $iv . $ciphertext;
    return base64_encode($ciphertext);
}

function decrypt($ciphertext_base64,$key) {
    global $iv, $iv_size;
    $ciphertext_dec = base64_decode($ciphertext_base64);
    $iv_dec = substr($ciphertext_dec, 0, $iv_size);
    $ciphertext_dec = substr($ciphertext_dec, $iv_size);
    return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
}

echo decrypt(encrypt('Hello World','123'),'123');
// Correct key used for decryption and result will be `Hello world`

echo decrypt(encrypt('Hello World','123'),'321');
// Wrong key used for decryption and result will be something like :ŘI¨ĄěđŘcSNŔ¶¸˘ÚE‘Z‰ŃZŃ9

?>

1 个答案:

答案 0 :(得分:2)

如果您已经知道关于纯文本的某些内容,则只能检测密钥是否正确。

(错误)方法1:向纯文本

添加静态字符串

您可以修改encrypt()功能,以便它始终向纯文本添加内容,例如$plaintext = 'correct key' . $plaintext;

decrypt()函数中,您现在可以检查此字符串是否存在并在返回之前将其删除。

您必须将decrypt()的最后一行替换为:

$decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
if (strpos($decrypted_text, 'correct key') === 0) {
    return substr($decrypted_text, strlen('correct key'));
} else {
    // key was wrong
    return false;
}

这里的问题是知道部分加密消息可能会削弱加密的安全性。所以不要这样做。

(更好)方法2:使用散列

验证纯文本

您可以只保存指纹(例如SHA1哈希),而不是修改纯文本。

像这样修改encrypt()函数:

return sha1($plaintext) . base64_encode($ciphertext);

decrypt()函数如下:

function decrypt($ciphertext, $key) {
    global $iv, $iv_size;

    $fingerprint = substr($ciphertext, 0, 32);
    $ciphertext_base64 = substr($ciphertext, 32);

    $ciphertext_dec = base64_decode($ciphertext_base64);
    $iv_dec = substr($ciphertext_dec, 0, $iv_size);
    $ciphertext_dec = substr($ciphertext_dec, $iv_size);

    $decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
    if (sha1($decrypted_text) == $fingerprint) {
        return $decrypted_text;
    } else {
        // key was wrong
        return false;
    }
}