2024年PHP日本大会

mcrypt_generic

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

mcrypt_generic此函数用于加密数据

警告

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

描述

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

此函数用于加密数据。数据将用“\0”填充,以确保数据长度为 n * 块大小。此函数返回加密后的数据。请注意,由于数据的填充,返回字符串的长度实际上可能比输入长度更长。

如果要将加密数据存储在数据库中,请确保存储mcrypt_generic返回的整个字符串,否则字符串将无法完全正确解密。如果原始字符串长度为10个字符,块大小为8(使用mcrypt_enc_get_block_size()确定块大小),则数据库字段至少需要16个字符。请注意,mdecrypt_generic()返回的字符串长度也为16个字符……使用rtrim($str, "\0")删除填充。

例如,如果将数据存储在MySQL数据库中,请记住varchar字段在插入过程中会自动删除尾随空格。由于加密数据可能以空格(ASCII 32)结尾,因此此删除操作会损坏数据。请改为将数据存储在tinyblob/tinytext(或更大)字段中。

参数

td

加密描述符。

加密句柄应始终使用mcrypt_generic_init()和密钥以及IV初始化,然后再调用此函数。完成加密后,应通过调用mcrypt_generic_deinit()释放加密缓冲区。请参阅mcrypt_module_open()了解示例。

data

要加密的数据。

返回值

返回加密后的数据。

参见

添加注释

用户贡献注释 7 条注释

tmacedo at linux dot ime dot usp dot br
18年前
补充Ryan Thomas, ryanrst at gmail dot com的帖子,如果使用HTTP方法发布cookie,则可能会进行编码;
由于base64中的一些字符会被编码成其他内容,您可以在编码前替换它们,并在解码后替换回来;
这是对dawgeatschikin at hotmail dot com对massimo dot scamarcia at gmail dot com最初想法的改进
(参见@ https://php.net/manual/en/function.base64-encode.php)
<?php
function urlsafe_b64encode($string)
{
$data = base64_encode($string);
$data = str_replace(array('+','/','='),array('-','_','.'),$data);
return
$data;
}
function
urlsafe_b64decode($string)
{
$data = str_replace(array('-','_','.'),array('+','/','='),$string);
$mod4 = strlen($data) % 4;
if (
$mod4) {
$data .= substr('====', $mod4);
}
return
base64_decode($data);
}
?>
Ryan Thomas, ryanrst at gmail dot com
18年前
如果希望将加密数据存储在浏览器的cookie变量中,在解密数据时会遇到问题。这是因为cookie只存储US-ASCII字符,而加密数据可能包含非US-ASCII字符。

解决方案

在将加密字符串存储到cookie之前,使用base64_encode对其进行编码,并在解密之前对存储在cookie中的字符串使用base64_decode进行解码。

示例

function setEncryptedCookie($cookieName, $data)
{
setcookie($cookieName, base64_encode($this->encrypt($data)), time()+$this->expire);
}

function getEncryptedCookie($cookieName)
{
return $this->decrypt(base64_decode($_COOKIE[$cookieName]));
}
chad 0x40 herballure 0x2e com
18年前
如果数据已经是n*块大小的长度,PHP会用另一个完整的"\0"块进行填充,因此填充字节数将在1到mcrypt_enc_get_block_size($td)之间。

您可以通过无条件地向字符串添加0x80来创建二进制安全的填充,然后去除PHP添加的尾随"\0",以及一个0x80字节。

<?php
function pad($text) {
// 添加单个0x80字节,并让PHP用0x00字节填充。
return pack("a*H2", $text, "80");
}
function
unpad($text) {
// 返回除了尾随0x80之外的所有内容,这些内容已删除0x00字节
return substr(rtrim($text, "\0"), 0, -1);
}
?>
chad 0x40 herballure 0x2e com
18年前
对我的上一条注释的补充:显然存在某种字符编码中断;如果不需要填充,PHP不会填充,而我看到的额外填充是chr(X)返回多个字节或其他什么的结果。

但是,我提供的pad/unpad函数仍然是二进制安全的,并且据我所知,与NIST 800-38a完全兼容。
maxximus007 at gmail dot com
17年前
行为更改:从5.2.x开始,当datastring为空时,mcrypt_generic将发出警告。
eric at ez-llc dot com
18年前
我能够使用Blowfish和密码分组链接模式(CBC)让PHP和Perl协同工作。Blowfish密钥至少需要8个字符(即使Blowfish的最小长度是8位,Perl也不接受小于8个字符的密钥),最大56个字符。IV必须正好是8个字符,填充必须为null,因为PHP使用null填充。此外,PHP需要libmcrypt >= 2.4.9才能与Perl兼容。

PERL
----

use Crypt::CBC;
$cipher = Crypt::CBC->new( {'key' => 'my secret key',
'cipher'=> 'Blowfish',
'iv' => '12345678',
'regenerate_key' => 0,
'padding' => 'null',
'prepend_iv' => 0
});
$cc = 'my secret text';
$encrypted = $cipher->encrypt($cc);
$decrypted = $cipher->decrypt($encrypted);

print "encrypted : ".$encrypted;
print "<br>";
print "decrypted : ".$decrypted;

PHP
---

$cc = 'my secret text';
$key = 'my secret key';
$iv = '12345678';

$cipher = mcrypt_module_open(MCRYPT_BLOWFISH,'','cbc','');

mcrypt_generic_init($cipher, $key, $iv);
$encrypted = mcrypt_generic($cipher,$cc);
mcrypt_generic_deinit($cipher);

mcrypt_generic_init($cipher, $key, $iv);
$decrypted = mdecrypt_generic($cipher,$encrypted);
mcrypt_generic_deinit($cipher);

echo "encrypted : ".$encrypted;
echo "<br>";
echo "decrypted : ".$decrypted;
pauls at sellingsource dot com
21年前
如果您正在加密二进制数据,并且在加密过程中中途出现空终止符,您将丢失字符串的其余部分。解决方法是先对二进制字符串进行base64_encode编码。

我们在尝试加密信用卡信息时发现了这个问题。将信用卡值转换为二进制字符串后,某些信用卡值无法解密。

我们当时使用MCRYPT_RIJNDAEL_256模块进行加密。

希望这对某些人有所帮助。
To Top