【问题标题】:Issue with PHP mcrypt functionPHP mcrypt 函数的问题
【发布时间】:2011-05-08 04:03:03
【问题描述】:

我使用以下函数解密服务器上的数据:

function decrypt($key, $text) {
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)));
}

我已经阅读了很多关于不使用 ECB 的信息(并且知道它已被弃用,所以想切换到 CBC。只需将模式切换为:

function decrypt($key, $text) {
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($text), MCRYPT_MODE_CBC, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND)));
}

但是不起作用。不会产生错误,但返回的数据仍然是加密的。

我错过了什么?

更新的代码 - 仍然有错误:

$key = "hello"; 

$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_DEV_RANDOM);

function encrypt($key, $text) {
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv)));
}


function decrypt($key, $text) { 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($text), MCRYPT_MODE_CBC, $iv));
}


$text = 12345;

echo "Plain Number : " . $text . "<br><br>";

$encrypted = encrypt($key, $text);
echo "AES Number : " . $encrypted . "<br><br>";

echo "Plain Number : ". decrypt($key, $encrypted) . "<br><br>";

这应该可以工作 - 但它会返回错误:

块大小在

blocksize in> 警告:mcrypt_encrypt()

[function.mcrypt-encrypt]:IV 参数必须与 blocksize inblocksize in

块大小在

【问题讨论】:

  • 返回的数据和你传入的一样吗?如果是,那么解密功能有问题。否则它可以正常工作,而您只是使用了错误的密钥/IV,并且将垃圾回收了。
  • @Marc B - 是的,事实上我在同一页面上运行加密和解密,即使是为了确保信息是好的,但我得到了错误。我将尝试看看下面的一些建议会有所作为。

标签: php mcrypt


【解决方案1】:

解密时需要使用与加密时相同的 IV。看起来您在解密期间生成了一个新的随机 IV。

可以将 IV 附加或预先添加到密文中。 IV 不是秘密,但它们对于每条加密消息应该是唯一的,并且只能使用一次。

【讨论】:

  • @cameron - 感谢您的帮助 - 我将不得不回顾 IV,但实际上 - 如果您已经在使用密钥加密文件开始,IV 的总体目的是什么与(可能您的 IV 存储在与数据本身相同的位置,如果您的服务器受到威胁,这不是很安全。
  • IV 只是为了防止统计密码分析技术。这不是一个秘密,所以如果它被披露也没关系。对每条消息使用随机 IV 意味着如果您使用相同的密钥对同一消息进行两次加密,您将获得不同的密文。这意味着窃听者无法在一系列消息中寻找模式,即使他们知道每条消息的 IV。即使您没有重复加密同一条消息,这一点也很重要。
  • @cameron - 上面有一个新的编辑,即使在同一页面上仍然会出错。
  • 嗯。不确定。尝试检查 mcrypt_get_iv_size 是否返回正确的数字,以及 mcrypt_create_iv 是否实际生成了正确长度的 IV。可能一个以比特为单位,另一个以字节为单位。
  • $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);返回 16
【解决方案2】:

您更新的代码有一个问题,$iv 是一个在相应的编码/解码函数中不可用的全局变量:

$key = "hello"; 

$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_DEV_RANDOM);

function encrypt($key, $text, $iv) {
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv)));
}

function decrypt($key, $text, $iv) { 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($text), MCRYPT_MODE_CBC, $iv));
}

$text = 12345;

echo "Plain Number : " . $text . "<br><br>";

$encrypted = encrypt($key, $text, $iv);
echo "AES Number : " . $encrypted . "<br><br>";

echo "Plain Number : ". decrypt($key, $encrypted, $iv) . "<br><br>";

或者您仍然可以通过将全局$iv 导入到本地函数范围来依赖它:

function encrypt($key, $text) {
    global $iv; // or use $GLOBALS['iv] instead of $iv in the call below
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv)));
}

function decrypt($key, $text) { 
    global $iv; // or use $GLOBALS['iv] instead of $iv in the call below
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($text), MCRYPT_MODE_CBC, $iv));
}

但这肯定不是推荐的做法,因为它会将您的代码与全局变量耦合。

【讨论】:

  • mcrypt_create_iv 消除了警告,但由于某种原因它似乎非常慢。
  • 不知道为什么,但在我的 Linux 系统上使用MCRYPT_DEV_RANDOM 调用mcrypt_create_iv 花了很长时间。使用MCRYPT_DEV_URANDOM 就像人们所期望的那样几乎是即时的。
  • 毫无疑问,您会在虚拟机上特别注意到这一点。这是因为虚拟机没有足够的 /dev/random 熵源。
【解决方案3】:

您在加密此文本时是否也更改了模式?

另外,使用MCRYPT_MODE_CBC时,需要在加解密时使用相同的key和IV。随机 IV 不适用于 CBC。

【讨论】:

  • 我也改变了加密模式;但是,到最后一点,“随机 IV”不起作用 - php.net 上的示例代码似乎另有说明(尽管它确实使用三元组作为密码):php.net/manual/en/function.mcrypt-cbc.php
  • 我认为@Dan 是说你不能用任何旧的随机 IV 解密,它必须与用于加密的相同。欧洲央行不使用静脉注射。
  • 请注意,ECB 模式的 IV 为零,因此为 ECB 创建的 IV 是一个空字符串。对于任何其他模式,IV 长度大于零。
猜你喜欢
  • 2016-09-21
  • 2011-11-18
  • 2010-10-27
  • 2011-08-31
  • 2011-06-16
  • 1970-01-01
  • 2012-01-22
  • 2016-03-09
  • 2018-06-24
相关资源
最近更新 更多