在 PHP 中使用 mcrypt 函数时检测到错误的解密密钥
Detect wrong decryption key while working with mcrypt functions in PHP
我写了下面的代码来做一个加解密机制。一切正常,但如果有人在解密时输入错误的密钥,我想防止显示不可读的字符。相反,我想向他显示一条特定的错误消息。我该怎么做?
我的 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
?>
如果您已经了解有关纯文本的,则只能检测密钥是否正确。
(坏)方法一:在纯文本中添加静态字符串
您可以修改 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;
}
}
我写了下面的代码来做一个加解密机制。一切正常,但如果有人在解密时输入错误的密钥,我想防止显示不可读的字符。相反,我想向他显示一条特定的错误消息。我该怎么做?
我的 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
?>
如果您已经了解有关纯文本的,则只能检测密钥是否正确。
(坏)方法一:在纯文本中添加静态字符串
您可以修改 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;
}
}