2024年PHP开发者大会日本站

mcrypt_create_iv

(PHP 4, PHP 5, PHP 7 < 7.2.0, PECL mcrypt >= 1.0.0)

mcrypt_create_iv从随机源创建初始化向量 (IV)

警告

此函数在 PHP 7.1.0 中已弃用,并在 PHP 7.2.0 中移除

此函数的替代方案包括

描述

mcrypt_create_iv(int $size, int $source = MCRYPT_DEV_URANDOM): string

从随机源创建初始化向量 (IV)。

IV 仅用于为加密例程提供替代种子。此 IV 完全不需要保密,尽管这样做可能更好。你甚至可以将其与密文一起发送而不会丢失安全性。

参数

size

IV 的大小。

source

IV 的来源。来源可以是 MCRYPT_RAND(系统随机数生成器)、MCRYPT_DEV_RANDOM(从 /dev/random 读取数据)和 MCRYPT_DEV_URANDOM(从 /dev/urandom 读取数据)。在 5.3.0 之前,在 Windows 上仅支持 MCRYPT_RAND

请注意,在 PHP 5.6.0 之前,此参数的默认值为 MCRYPT_DEV_RANDOM

注意: 请注意,MCRYPT_DEV_RANDOM 可能会阻塞,直到有足够的熵可用。

返回值

返回初始化向量,或在发生错误时返回 false

范例

示例 #1 mcrypt_create_iv() 示例

<?php
$size
= mcrypt_get_iv_size(MCRYPT_CAST_256, MCRYPT_MODE_CFB);
$iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
?>

参见

添加注释

用户贡献的注释 12 条注释

44
Graham
10年前
关于此处看到的加密“建议”,我的建议是忽略大部分内容。有些是好的,有些是坏的,但大多数都忽略了关键问题。

我希望写出一个很好的长篇解释,但PHP的评论系统告诉我我的文章太长了。所以我只说这些:

你应该使用CBC模式,使用对每个密钥唯一的随机选择的IV,并且你应该将该IV与你的密文一起明文传输。你还应该使用诸如HMAC-SHA256之类的算法对整个数据块进行真实性检查,并使用另一个独立的密钥。

这是我将要写的全文:http://pastebin.com/sN6buivY

如果你对这些东西感兴趣,或者只是想了解更多信息,请查看有关分组密码模式、分组密码、HMAC等的维基百科文章。

我还建议阅读布鲁斯·施奈尔的《实用密码学》和尼尔斯·弗格森的《密码工程》,这两本书都是关于实用密码学的非常容易理解的书籍。
16
Chris
18年前
>首先,IV应该是随机且变化的。它的全部 >意义在于确保相同的明文不会每次都 >加密成相同的密文。如果IV是常量或公开的, >你肯定会失去安全性。

错误,错误,大错特错!初始化向量可以是公开的!它通常与密文一起未加密地发送。

>密文应该是E(IV | 明文,密钥)

再次错误!初始化向量在加密前不会附加到明文。IV用于启动反馈系统!(这就是为什么你在ECB模式下不需要它——没有反馈)

>其次,IV根本不应该成为解密 >参数的一部分。你应该能够解密密文, >丢弃前面的初始化向量,甚至 >不用读取它,就能得到你的明文

不。你需要在解密期间将反馈机制的种子设置到与加密期间相同的状态。这意味着使用相同的IV!
5
nils at nm dot cx
12年前
如果你使用/dev/random,你需要一个填充良好的熵池,否则应用程序将阻塞,直到有足够的良好熵可用。
6
hans at llis dot nl
12年前
这并不能在所有系统上生成随机分布的IV,因此存在很大的安全风险。使用一个脚本(基于Alex Khimch's在rand()页面上发布的脚本),可以很容易地检查这一点。

<?php

$td
= mcrypt_module_open (MCRYPT_RIJNDAEL_256, "", MCRYPT_MODE_CBC, "");
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($td), MCRYPT_DEV_RANDOM);

// header("Content-type: image/png");
$img = imagecreatetruecolor(255,255);

$ink = imagecolorallocate($img,255,255,255);
for(
$i=0;$i<255;$i++) {
for(
$j=0;$j<255;$j++) {
$twobytes = substr ($iv, 0, 2);
$iv = substr ($iv, 2);
if (!
strlen ($iv)) $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($td), MCRYPT_RAND);

imagesetpixel($img, ord($twobytes[0]), ord($twobytes[1]), $ink);
}
}

imagepng($img);
imagedestroy($img);

?>

生成的图像应该显示随机噪点,但在我的 Windows 系统 (运行 PHP 5.3.x) 上测试时,却显示出非常明显的图案。
5
robert at peakepro dot com
20 年前
需要注意的是,除了 ECB 模式外,所有密码模式都需要在解密时使用与加密时相同的 IV。

您需要将密钥 *和* IV 传递给解密函数。在解密例程中初始化一个新的 IV 是行不通的。

由于“您可以将 [IV] 与密文一起发送而不会损失安全性”,一种很好的处理方法是将您的 IV 预先添加到密文中。由于 IV 是固定宽度的,您可以使用 `mcrypt_get_iv_size()` 和 `substr()`轻松恢复 IV 和原始密文。

这是一个例子

<?PHP
function my_encrypt($string,$key) {
srand((double) microtime() * 1000000); //为了 MCRYPT_RAND
$key = md5($key); //为了提高方差
/* 打开模块,并创建 IV */
$td = mcrypt_module_open('des', '','cfb', '');
$key = substr($key, 0, mcrypt_enc_get_key_size($td));
$iv_size = mcrypt_enc_get_iv_size($td);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
/* 初始化加密句柄 */
if (mcrypt_generic_init($td, $key, $iv) != -1) {

/* 加密数据 */
$c_t = mcrypt_generic($td, $string);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$c_t = $iv.$c_t;
return
$c_t;
}
//end if
}

function
my_decrypt($string,$key) {
$key = md5($key); //为了提高方差
/* 打开模块,并创建 IV */
$td = mcrypt_module_open('des', '','cfb', '');
$key = substr($key, 0, mcrypt_enc_get_key_size($td));
$iv_size = mcrypt_enc_get_iv_size($td);
$iv = substr($string,0,$iv_size);
$string = substr($string,$iv_size);
/* 初始化加密句柄 */
if (mcrypt_generic_init($td, $key, $iv) != -1) {

/* 解密数据 */
$c_t = mdecrypt_generic($td, $string);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return
$c_t;
}
//end if
}
// 测试:
//print my_decrypt(my_encrypt("Hello, world.","foo"),"foo");
?>
2
kkaiser at dataresolutions dot com
18年前
在我对维护的一个相当大的动态网站进行性能分析以确定间歇性冻结执行的原因后,我发现使用 `MCRYPT_DEV_RANDOM` 作为源的 `mcrypt_create_iv()` 调用始终会使执行暂停 0.2 到约 12 秒不等,具有讽刺意味的是,暂停时间是随机的。我假设暂停是由 `/dev/random` 中当前可用随机输入不足引起的,因为它的预期功能是在提供足够的随机输入回设备之前阻塞。我发现使用下面找到的 `alt_mcrypt_create_iv()` 函数的修改版本足以满足我的需求。

虽然未经测试,但我假设使用 `MCRYPT_DEV_URANDOM` 或 `MCRYPT_DEV_RAND` 与 `srand()` 的组合也能解决这个问题;我后来发现 `/dev/urandom` 的预期功能是在 `/dev/urandom` 缓冲区为空时无缝地从随机数生成器提供加密安全的输出,而 `MCRYPT_DEV_RAND` 只会使用与 `alt_mcrypt_create_iv()` 相同的 `rand()` 函数。

-Kevin Kaiser
2
tim at indigopixel dot com
20 年前
来自 http://www.ciphersbyritter.com/GLOSSARY.HTM#IV (上面链接)

“虽然经常有人说 IV 值只需要类似随机或不可预测,并且不需要保密,但在 CBC 模式的情况下,此建议可能会导致针对第一个明文块的中间人攻击。如果 MITM 对手知道第一个块的常用内容,他们可以更改 IV 来操纵该块(且仅操纵该块)以传递不同的地址、不同的金额、不同的命令或任何其他内容。虽然传统建议是在更高层使用 MAC 来检测更改的明文,但这并不总是理想的或正确执行的。但是,CBC 首块问题可以通过简单地加密 IV 并将其保密来轻松解决,即使稍后将使用 MAC,这也是合理的。”
1
joseph dot t dot fallon at gmail dot com
9 年前
分组密码的核心是一对变换算法,称为变换。一个加密,一个解密——在某些情况下,算法是相同的,但这并不重要。分组变换采用固定长度的明文块,使用某种选定大小的密钥对其进行变换,并产生相同长度的密文块。或者,当然,反之亦然(解密)。

分组密码的安全模型,至少从简化的角度来看,被定义为“如果使用随机选择的密钥加密一个明文块,那么对于仅知道密文(即不知道密钥)的攻击者来说,发现关于明文内容的信息在计算上是不可行的”。现实情况略有不同——还有一些关于知道部分明文而无法发现更多明文的条款——但那是另一个故事了。

一旦你开始使用相同的块变换和相同的密钥加密多个明文块,所有赌注都无效。在电子密码本 (ECB) 密码模式下,每个明文块都使用相同的密钥独立变换。这导致一个问题:当使用相同的密钥时,相同的明文块会产生相同的密文块。这意味着数据中的“模式”是可见的,尤其是在具有重复模式或长序列相同数据的 数据格式中。这最好用可视化方式描述,例如 ECB 加密的位图。请参阅维基百科上关于 ECB 的文章以了解此演示。
1
Matthew
16年前
我在一个正在进行的项目中加密页面上的几个项目,我发现IV创建函数也会导致页面渲染速度大幅降低(我注意到这里其他人也有这个问题)。

对于一个本应非常快速的站点,4秒的渲染时间相当常见。我建议如果速度至关重要,则应使用替代方法来创建IV(例如,如果您认为它足够安全,则可以使用下面的方法)。

使用替代的IV创建方法后,我的页面渲染时间从4秒缩短到0.01秒。
0
wschalle at gmail dot com
9 年前
hans at illis dot nl 的演示代码是错误的。在循环中,他使用

$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($td), MCRYPT_RAND);

而实际上应该使用

$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($td), MCRYPT_DEV_URANDOM);

这在 Windows 上产生一致的结果。
-1
匿名
19年前
来自
edwardzyang at thewritingpot dot com
2005年7月19日 10:06

这是因为(如上文手册中所述),此函数与 rand() 不同,它不会重新播种随机数生成器。如上所述,使用 srand() 可以获得正确的 IV。
-4
Mahn
10年前
如果此函数在您的请求中随机挂起,请在第二个参数中指定 MCRYPT_RAND。
To Top