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(
    string $algorithm,
    string $algorithm_directory,
    string $mode,
    string $mode_directory
): resource

此函数打开要使用的算法和模式的模块。算法的名称在 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 notes

2
匿名
21 年前
执行 trim($decrypted) 将删除可能由于解密而发生的空填充。

问题是,如果您加密的是像 MSWord 文档这样的东西,它通常以空字符结尾。结果 $decrypted 将小于原始明文 - 然后将无法在 MSOffice 中打开。

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

$decrypted = substr(mdecrypt_generic($td, $encrypted), 0, $originalLength);
2
Mark
11 年前
对于像这样的错误
' 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
蛇形 XTEA Blowfish Enigma RC2 三重 DES
支持的模式 => CBC CFB CTR ECB NCFB NOFB OFB 流
1
dinamic at gmail dot com
16 年前
还要指出,在为 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";
?>
0
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
= 'something very secret';
$human_key2 = 'something else very secret';

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

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

... 或者您可以自动将一个大型“人类密钥”拆分为两个或多个部分,使用 sha1(原始输出!)对这些部分进行哈希处理,并将它们再次合并(按原始顺序或重新排列,加盐,按照您喜欢的任何方式转换它们)以获得 40、60、80 或更多字符的二进制密钥,具体取决于秘密密钥已拆分的次数 =)
-1
匿名
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”,它也只能与某些组合一起使用。

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

有关如何添加 pkcs 5 填充的示例,请参见 ref.mcrypt.php
-2
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