PHP Conference Japan 2024

mdecrypt_generic

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

mdecrypt_generic解密数据

警告

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

描述

mdecrypt_generic(资源 $td, 字符串 $data): 字符串

此函数解密数据。请注意,由于数据的填充,返回字符串的长度实际上可能比未加密字符串的长度更长。

参数

td

mcrypt_module_open() 返回的加密描述符

data

加密数据。

返回值

返回解密后的字符串。

示例

示例 #1 mdecrypt_generic() 示例

<?php
/* 数据 */
$key = 'this is a very long key, even too long for the cipher';
$plain_text = 'very important data';

/* 打开模块并创建 IV */
$td = mcrypt_module_open('des', '', 'ecb', '');
$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, $plain_text);
mcrypt_generic_deinit($td);

/* 重新初始化缓冲区以进行解密 */
mcrypt_generic_init($td, $key, $iv);
$p_t = mdecrypt_generic($td, $c_t);

/* 清理 */
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
}

if (
strncmp($p_t, $plain_text, strlen($plain_text)) == 0) {
echo
"ok\n";
} else {
echo
"error\n";
}
?>

上面的示例展示了如何检查加密前的数据与解密后的数据是否相同。在尝试解密数据之前,使用 mcrypt_generic_init() 重新初始化加密缓冲区非常重要。

在调用此函数之前,应该始终使用 mcrypt_generic_init() 使用密钥和 IV 初始化解密句柄。在完成加密后,应该通过调用 mcrypt_generic_deinit() 来释放加密缓冲区。请参阅 mcrypt_module_open() 获取示例。

参见

添加注释

用户贡献的注释 11 个注释

nytro_rst at yahoo dot com
15 年前
<?php
// 参数:
// $text = 你想要加密的文本。
// $key = 你用于加密的密钥。
// $alg = 加密算法。
// $crypt = 1 表示加密,0 表示解密。

function cryptare($text, $key, $alg, $crypt)
{
$encrypted_data="";
switch(
$alg)
{
case
"3des":
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
break;
case
"cast-128":
$td = mcrypt_module_open('cast-128', '', 'ecb', '');
break;
case
"gost":
$td = mcrypt_module_open('gost', '', 'ecb', '');
break;
case
"rijndael-128":
$td = mcrypt_module_open('rijndael-128', '', 'ecb', '');
break;
case
"twofish":
$td = mcrypt_module_open('twofish', '', 'ecb', '');
break;
case
"arcfour":
$td = mcrypt_module_open('arcfour', '', 'ecb', '');
break;
case
"cast-256":
$td = mcrypt_module_open('cast-256', '', 'ecb', '');
break;
case
"loki97":
$td = mcrypt_module_open('loki97', '', 'ecb', '');
break;
case
"rijndael-192":
$td = mcrypt_module_open('rijndael-192', '', 'ecb', '');
break;
case
"saferplus":
$td = mcrypt_module_open('saferplus', '', 'ecb', '');
break;
case
"wake":
$td = mcrypt_module_open('wake', '', 'ecb', '');
break;
case
"blowfish-compat":
$td = mcrypt_module_open('blowfish-compat', '', 'ecb', '');
break;
case
"des":
$td = mcrypt_module_open('des', '', 'ecb', '');
break;
case
"rijndael-256":
$td = mcrypt_module_open('rijndael-256', '', 'ecb', '');
break;
case
"xtea":
$td = mcrypt_module_open('xtea', '', 'ecb', '');
break;
case
"enigma":
$td = mcrypt_module_open('enigma', '', 'ecb', '');
break;
case
"rc2":
$td = mcrypt_module_open('rc2', '', 'ecb', '');
break;
default:
$td = mcrypt_module_open('blowfish', '', 'ecb', '');
break;
}

$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = substr($key, 0, mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);

if(
$crypt)
{
$encrypted_data = mcrypt_generic($td, $text);
}
else
{
$encrypted_data = mdecrypt_generic($td, $text);
}

mcrypt_generic_deinit($td);
mcrypt_module_close($td);

return
$encrypted_data;
}
?>
[email protected]
11年前
对于所有对填充感到“惊讶”的人(即使方法描述中提到了填充),请不要仅仅“去除所有我不理解的东西”。
使用rtrim、rtrim "\0"、去除所有小于16的字符码等方法都是错误的。
PKCS #7填充的工作方式与RFC 5652中描述的完全一致。
要移除填充,只需查看消息的最后一个字节,它会告诉你需要移除多少个字节。
例如,如果最后一个字节等于\0A,则移除10个字节。
Ulysse
11年前
根据“[email protected]”提供的信息,在PKCS#7中,最后一个字节包含要移除的字节数(参见RFC 5652,第6.3部分),并且对于像我这样喜欢复制粘贴现成代码片段的人

<?php
function unpadPKCS7($data, $blocksize)
{
$last = substr($data, -1);
return
substr($data, 0, strlen($data) - ord($last));
}
?>

现在你没有理由再使用rtrim()来移除结果末尾的填充了。
匿名用户
15 年前
这是一个快速移除PKCS7填充的代码片段

<?php
function unpadPKCS7($data, $blockSize) {
$length = strlen ( $data );
if (
$length > 0) {
$first = substr ( $data, - 1 );

if (
ord ( $first ) <= $blockSize) {
for(
$i = $length - 2; $i > 0; $i --)
if (
ord ( $data [$i] != $first ))
break;

return
substr ( $data, 0, $i );
}
}
return
$data;
}
?>
Peter Bailey
12年前
我们发现有时生成的填充不是空字符“\0”,而是几个控制字符之一。

如果您知道您的数据不应该有任何尾随的控制字符(就像我们一样),您可以像这样去除它们。

<?php

$data
= mdecrypt_generic( $cipher, $data );

// 去除尾随的控制字符填充
$data = preg_replace( "/\p{Cc}*$/u", "", $data );

?>
trashmail dot hashishin at gmail dot com
14年前
无论何时需要解密使用.net(和其他?)加密的文件,都可以使用以下设置

加密:'rijndael-256'
模式:'cbc'
填充模式:Zeros
iv:“yes”

使用base64编码数据并将它们发送到您的php脚本
robbie [at] averill [dot] co [dot] nz
19年前
我注意到,有时当二进制密文长于明文时,解密的明文旁边可能会有一些小方块作为“填充”。我还注意到,您无法剪切和粘贴它们来编辑它们,但我确实找到了一个解决方案。

只需在字符串周围调用rtrim(),它就会删除它们。
Silvan
17年前
通常不建议只使用rtrim来移除填充。

对于末尾不是“\0”的字符串,使用rtrim($str, "\0"),或者在加密过程中存储数据长度。
(尽管包含“\0”的数据有时会在加密过程中损坏,因此这些类型的数据实际上应该被打包。)

例如

<?php

function encrypt($original_data)
{
$length = strlen($original_data);
$data_to_encrypt = $length.'|'.$original_data;
// 加密包含其长度的数据。
// 不要保存未加密的长度,因为这可能是一个(轻微的)安全风险
}

function
decrypt($cypher)
{
// 首先解密密码数据
// 接下来检索原始数据
list($length, $padded_data) = explode('|', $decrypted_data, 2);
$original_data = substr($padded_data, 0, $length);
}

?>
php at pcwize dot com
18年前
只是确认.DLL问题。对于4.3.4,您需要旧的.DLL。我猜任何版本的PHP4都需要旧的.DLL。对于PHP5,您需要新的。
drew at expressdynamics dot com
19年前
在使用PHP 5的Win32系统上,必须使用较新的libmcrypt.dll文件,否则mdecrypt_generic将无法工作。
jon@jonroig dot com
20年前
这是一段加密/解密代码。

如果您在win32平台上使用它,请注意!最新的DLL(2004年1月19日)包含一个错误,它阻止mdecrypt_generic发挥作用。几乎让我崩溃……2002年12月30日的版本似乎运行良好。
<?

$key = "this is a secret key";
$input = "Let us meet at 9 o'clock at the secret place.";

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

echo "Encrypt: ".$encrypted_data;

echo "<br><br>";

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = substr($key, 0, mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$decrypted_data = mdecrypt_generic($td, $encrypted_data);
echo "Decrypt: ".$decrypted_data;
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

?>
To Top