PHP 大会日本 2024

mcrypt_module_open

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

mcrypt_module_open打开要使用的算法和模式的模块

警告

此函数自 PHP 7.1.0 起已弃用,自 PHP 7.2.0 起移除。强烈建议不要依赖此函数。

描述

mcrypt_module_open(
    字符串 $algorithm,
    字符串 $algorithm_directory,
    字符串 $mode,
    字符串 $mode_directory
): 资源

此函数打开要使用的算法和模式的模块。算法的名称在 algorithm 中指定,例如 "twofish" 或为 MCRYPT_ciphername 常量之一。通过调用 mcrypt_module_close() 关闭模块。

参数

algorithm

MCRYPT_ciphername 常量之一,或算法的名称作为字符串。

algorithm_directory

algorithm_directory 参数用于查找加密模块。提供目录名称时,将使用该目录。将其设置为空字符串 ("") 时,将使用 mcrypt.algorithms_dir php.ini 指令设置的值。如果未设置,则使用编译到 libmcrypt 中的默认目录(通常为 /usr/local/lib/libmcrypt)。

mode

MCRYPT_MODE_modename 常量之一,或以下字符串之一:"ecb"、"cbc"、"cfb"、"ofb"、"nofb" 或 "stream"。

mode_directory

mode_directory 参数用于查找加密模块。提供目录名称时,将使用该目录。将其设置为空字符串 ("") 时,将使用 mcrypt.modes_dir php.ini 指令设置的值。如果未设置,则使用编译到 libmcrypt 中的默认目录(通常为 /usr/local/lib/libmcrypt)。

返回值

通常返回加密描述符,或在出错时返回 false

示例

示例 #1 mcrypt_module_open() 示例

<?php
$td
= mcrypt_module_open(MCRYPT_DES, '',
MCRYPT_MODE_ECB, '/usr/lib/mcrypt-modes');

$td = mcrypt_module_open('rijndael-256', '', 'ofb', '');
?>

上面示例中的第一行将尝试从默认目录打开 DES 密码,并从 /usr/lib/mcrypt-modes 目录打开 ECB 模式。第二个示例使用字符串作为密码和模式的名称,这仅在扩展与 libmcrypt 2.4.x 或 2.5.x 链接时才有效。

示例 #2 在加密中使用 mcrypt_module_open()

<?php
/* 打开密码 */
$td = mcrypt_module_open('rijndael-256', '', 'ofb', '');

/* 创建 IV 并确定密钥长度,在 Windows 上使用 MCRYPT_RAND
* 代替 */
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);
$ks = mcrypt_enc_get_key_size($td);

/* 创建密钥(仅示例:MD5 不是此哈希算法的良好选择) */
$key = substr(hash('md5', 'very secret key'), 0, $ks);

/* 初始化加密 */
mcrypt_generic_init($td, $key, $iv);

/* 加密数据 */
$encrypted = mcrypt_generic($td, 'This is very important data');

/* 终止加密处理程序 */
mcrypt_generic_deinit($td);

/* 初始化加密模块以进行解密 */
mcrypt_generic_init($td, $key, $iv);

/* 解密加密字符串 */
$decrypted = mdecrypt_generic($td, $encrypted);

/* 终止解密句柄并关闭模块 */
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

/* 显示字符串 */
echo trim($decrypted) . "\n";
?>

参见

添加注释

用户贡献的注释 7 条注释

匿名
21 年前
执行 trim($decrypted) 将删除解密后可能出现的空填充。

问题是,如果您正在加密诸如 MSWord 文档之类的内容,这些文档通常以空字符结尾。结果 $decrypted 将小于原始明文 - 然后将无法在 MSOffice 中打开。

要解决此问题,请确保存储原始明文的长度,并在解密时执行

$decrypted = substr(mdecrypt_generic($td, $encrypted), 0, $originalLength);
Mark
12 年前
对于类似以下的错误
' mcrypt_module_open(): Could not open encryption module in '



确保您使用的是正确的名称。提供密码列表的页面**不是**说明每个密码的正确方式(此处显示https://php.net/manual/en/mcrypt.ciphers.php)。

为了查看哪些密码受支持,请尝试使用phpinfo(); 并查看mcrypt下的内容,例如:

mcrypt support => enabled
mcrypt_filter support => enabled
Version => 2.5.8
Api No => 20021217
Supported ciphers => cast-128 gost rijndael-128 twofish arcfour cast-256 loki97 rijndael-192 saferplus wake blowfish-compat des rijndael-256
serpent xtea blowfish enigma rc2 tripledes
Supported modes => cbc cfb ctr ecb ncfb nofb ofb stream
dinamic at gmail dot com
17年前
还需要指出的是,在为mcrypt形成密钥时,不应使用md5()和/或sha1()。这是因为十六进制编码仅使用一组16个字符[0-9a-f],相当于4位,因此将加密强度降低了一半:4 x 32 = 128位。

我重写了显示的示例,因此以下是我获得真正256位加密的建议

<?php
$key1
= "这是一个秘密密钥";
$key2 = "这是第二个秘密密钥";
$input = "让我们在9点钟在秘密地点见面。";
$length = strlen($input);

/* 打开密码 */
$td = mcrypt_module_open('rijndael-256', '', 'cbc', '');

/* 创建IV并确定密钥长度,在Windows上使用MCRYPT_RAND
* 代替 */
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$ks = mcrypt_enc_get_key_size($td);

/* 创建密钥 */
$key1 = md5($key1);
$key2 = md5($key2);

$key = substr($key1, 0, $ks/2) . substr(strtoupper($key2), (round(strlen($key2) / 2)), $ks/2);

$key = substr($key.$key1.$key2.strtoupper($key1),0,$ks);

/* 初始化加密 */
mcrypt_generic_init($td, $key, $iv);

/* 加密数据 */
$encrypted = mcrypt_generic($td, $input);

/* 终止加密处理程序 */
mcrypt_generic_deinit($td);

/* 初始化解密模块 */
mcrypt_generic_init($td, $key, $iv);

/* 解密加密字符串 */
$decrypted = mdecrypt_generic($td, $encrypted);

/* 终止解密句柄并关闭模块 */
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

/* 显示字符串 */
echo "文本: ".substr($decrypted,0,$length) . "<br>";
echo
"编码: ".$encrypted ."<br>";
echo
"<br>key1: $key1 <br>key2: $key2<br>生成的密钥: $key";
?>
royconejo
15年前
关于之前关于十六进制格式和大小写作为提高密钥的方法的评论

这似乎很明显,但选择仅限于十六进制字符([0-9a-z]);您可以从md5()或sha1()获取原始的RAW输出,而不是默认的可读十六进制格式。

原始输出的结果将是16或20(取决于使用的哈希函数)个范围为0-255的字符序列。比[0-9a-z]甚至[0-9a-zA-Z]都要好得多。

16或20通常小于最大密钥长度(示例中的$ks),但您可以将两个或多个密钥连接在一起

<?php
$human_key1
= '一些非常秘密的东西';
$human_key2 = '一些其他非常秘密的东西';

// 使用两个“人类可读”密钥和sha1生成40字节二进制密钥。
$bigger_binary_key = sha1($human_key1, true) . sha1($human_key2, true);

// 然后像平时一样使用它(从示例中提取)
$key = substr($bigger_binary_key, 0, $ks);
?>

...或者您可以自动将一个大型“人类密钥”拆分为两个或多个部分,使用sha1(原始输出!)对这些部分进行哈希,并将其重新组合(按原始顺序或重新排列、加盐、根据需要转换它们)以获得40、60、80或更多字符的二进制密钥,具体取决于秘密密钥已拆分的部件数量=)
匿名
8年前
针对Windows的mcrypt_module_open()错误的匿名用户的后续操作

<?php
$M
= mcrypt_list_modes();
$A = mcrypt_list_algorithms();
foreach (
$M as $m)
foreach (
$A as $a) {
$t = @mcrypt_module_open($a,'',$m,'');
print
"$m, $a = ";
print (
$t)?"ok":"nope";
print
"<br>";
}
?>

这将显示并非所有模式都适用于所有算法。Cygwin也没有'libmcrypt.dll',它也只适用于某些组合。

(第一次尝试碰巧是其中一个不起作用的!)
lehmann*at*arcor-so.net
15年前
请记住,mcrypt函数没有实现填充,例如pkcs#5。这会导致末尾出现零字节的问题,并且字符串无法在其他环境中正确解码。

有关如何添加pkcs 5填充的示例,请参阅ref.mcrypt.php
ash
16年前
对dinamic的创建密钥函数的轻微改进

我认为弱点在于大写字母始终用于字符串的同一部分。以下代码将字符串的随机字符大写,使密钥更难以预测



<?php
$key
= substr($key1, 0, $ks/2) . substr($key2, (round(strlen($key2) / 2)), $ks/2);
$key = substr($key.$key1.$key2.$key1,0,$ks);

$buffer = str_split($key);

$limit = count($buffer)-1;
srand((float)microtime() * 1000000);

$end = rand(0, $limit);
$a = 0;

// 将随机字符替换为大写字母
while ($a < $end) {
list(
$usec, $sec) = explode(' ', microtime());
$seed = ((float)$sec) + ((float) $usec * 100000);
mt_srand($seed);

$index = mt_rand(0,$limit);

$buffer[$index] = strtoupper($buffer[$index]);
$a++;
}

$key = join('', $buffer);
?>
To Top