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 之前,MCRYPT_RAND 是 Windows 上唯一支持的来源。

请注意,此参数的默认值在 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);
?>

参见

添加注释

用户贡献注释 13 个注释

Graham
10 年前
关于这里看到的所有关于密码学的“建议”,我的建议是忽略其中大部分。其中一些是好的,一些是坏的,但大多数都跳过了关键问题。

我原本希望写出一篇长长的解释,但 PHP 的注释系统告诉我我的文章太长了。相反,我会说:

您应该使用 CBC,使用为每个密钥随机选择的唯一 IV,并且您应该将该 IV 与密文一起明文传输。您还应该使用类似 HMAC-SHA256 的方法对整个数据块执行完整性检查,并使用另一个独立的密钥。

以下是完整的内容: http://pastebin.com/sN6buivY

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

我还建议您阅读布鲁斯·施奈尔的《实用密码学》和尼尔斯·弗格森的《密码学工程》,这两本书都非常易于理解,并介绍了实用密码学。
Chris
17 年前
>首先,IV 应该是随机且可变的。它的目的 >是为了确保每次加密相同的明文时,生成的密文 >都不相同。如果您使用的是常量或公共 IV, >那么您肯定会失去安全性。

错误,错误!初始化向量是允许公开的!它通常与密文一起发送,且不加密。

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

再次错误!初始化向量不会在加密之前预先附加到明文。IV 用于播种反馈系统!(这就是为什么您在 ECB 模式下不需要 IV - 因为没有反馈)

>其次,IV 根本不应该是解密参数的一部分。您应该能够 >解密密文,甚至不必读取 >开头部分的初始化向量,就能获得明文

不,您需要在解密期间播种反馈机制,使其与加密期间播种的状态相同。这意味着使用相同的 IV!
nils at nm dot cx
12 年前
如果您使用 /dev/random,则需要一个填充良好的熵池,否则应用程序将阻塞,直到有足够的熵可用。
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)上,它显示了非常明显的模式。
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");
?>
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
tim at indigopixel dot com
20 年前
来自 http://www.ciphersbyritter.com/GLOSSARY.HTM#IV(链接到上面)

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

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

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

对于一个应该很敏捷的网站来说,4 秒的渲染时间是很常见的。我建议,如果速度至关重要,请使用其他方法来创建您的 IV(例如,如果您认为下面这个方法足够安全,可以使用它)。

使用其他 IV 创建方法后,我的页面渲染时间从 4 秒降至 0.01 秒。
Anonymous
18 年前

edwardzyang at thewritingpot dot com
2005 年 7 月 19 日 10:06

这是因为(正如上面手册中所描述的)此函数不像 rand() 那样重新播种随机数生成器。按照上面建议的那样使用 srand() 可以获得正确的 IV。
Mahn
9 年前
如果此函数在您的请求中随机挂起,请在第二个参数中指定 MCRYPT_RAND。
fandelem at hotmail dot com
22 年前
注意:如果您遇到一个抱怨第二个参数必须是“long”,而您给的是“string”(对我来说,它是使用 MCRYPT_URANDOM),您可能想尝试 MCRYPT_DEV_URANDOM :)
To Top