2024 年 PHP 日本大会

Mcrypt 函数

目录

添加注释

用户贡献注释 24 条注释

3
rolf at winmutt dot com
18 年前
PHP 的 mysql AES_ENCRYPT() 兼容函数

<?php
function mysql_aes_encrypt($val,$ky) {
$mode=MCRYPT_MODE_ECB;
$enc=MCRYPT_RIJNDAEL_128;
$val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16)));
return
mcrypt_encrypt($enc, $ky, $val, $mode, mcrypt_create_iv( mcrypt_get_iv_size($enc, $mode), MCRYPT_DEV_URANDOM));
}
?>

请注意,如果 strlen($ky)>16,则此函数将不兼容。
3
groundzero at zuavra dot net
20 年前
如果您曾经从源代码编译过 PHP(任何版本),您可能熟悉在尝试使用 --with-mcrypt 编译时出现的臭名昭著的 [in]famous MCRYPT_BLOWFISH_128 编译错误。它经常出现在 Debian 上,但不仅仅在那里。问题:在编译过程中,PHP 配置脚本总是假设 libmcrypt 已与 libltdl 一起构建。每当情况并非如此时,PHP 编译稍后会失败,并提示说 mcrypt.h 中缺少某些头文件(例如上面的 blowfish 示例)(这是误导性的,如果 libltdl 正确参与,它们不应该在那里也不应该被查找)。解决方案:确保您的 libmcrypt 在您开始配置 PHP 之前已与 libltdl 链接。您可以通过运行“ldd lybmcrypt.so”并验证 libltdl 是否出现在输出中来进行检查。在 Debian 上可以找到 libltdl,位于 libltld[3][-dev] 中,或者在 Red Hat 上位于 libtool-libs 中。
4
manyagain
15 年前
如果您没有安装 mcrypt,请尝试使用 phpseclib - http://phpseclib.sourceforge.net

包含 des、3des、rc4、aes 和 rijndael 的纯 PHP 实现。如果可用,则使用 mcrypt;否则使用纯 PHP 实现。根据文档第 3.5.5 节“速度比较”,它还具有最快存在的纯 PHP aes 实现的优点。
5
duerra_NOT_THIS_ at pushitlive dot net
18 年前
对于那些需要使用 PKCS#5 填充的用户,PHP 的 mcrypt API 不支持它。但是,您可以使用以下方法自己动手

<?php

function encrypt_something($input)
{
$size = mcrypt_get_block_size('des', 'ecb');
$input = pkcs5_pad($input, $size);

$key = 'YOUR SECRET KEY HERE';
$td = mcrypt_module_open('des', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$data = base64_encode($data);
return
$data;
}

function
pkcs5_pad ($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return
$text . str_repeat(chr($pad), $pad);
}

function
pkcs5_unpad($text)
{
$pad = ord($text{strlen($text)-1});
if (
$pad > strlen($text)) return false;
if (
strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
return
substr($text, 0, -1 * $pad);
}
?>
2
[email protected]
18 年前
关于将结果存储在使用 Unicode 的 Postgres 数据库中(对下面帖子的后续)。
您不需要将数据库的编码更改为 ASCII。
只需使用 BASE64 编码结果即可,这完全安全。
解密前使用 base64_decode。
-- Tomer Levinboim
2
[email protected]
21 年前
mcrypt_ecb 与 base64_decode 出现了一些问题,我发现必须将其分割才能工作

<?php
chop
(mcrypt_ecb(MCRYPT_BLOWFISH,$key,base64_decode($input),MCRYPT_DECRYPT));
?>
1
Kevin
16 年前
已解决问题

编译 php --with-mcrypt 时,phpinfo() 显示 mcrypt 已启用,但是
"支持的密码:无" 和
"支持的模式:无"

为了使 mcrypt 在 php 中工作,您必须使用以下选项配置和编译 libmcrypt 源代码包
./configure --disable-posix-threads --enable-dynamic-loading
1
simms
21 年前
Debian 用户:避免 mcrypt 安装的麻烦。
要向现有的 php 安装添加 mcrypt 支持,请获取 root 权限并运行

apt-get install php4-mcrypt

重新启动您的 Web 服务器,瞧。
1
[email protected]
23 年前
如果您编译了 mcrypt 和 php 但没有问题,但 phpinfo() 显示没有受支持的密码和模式,请尝试将 libdirs(/usr/local/libmcrypt、/usr/local/libcrypt)的模式更改为 755。
1
[email protected]
14 年前
这与 mysql aes 完全配合使用,即使是长密钥。

<?php
function mysql_aes_decrypt($val,$ky)
{
$key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
for(
$a=0;$a<strlen($ky);$a++)
$key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a]));
$mode = MCRYPT_MODE_ECB;
$enc = MCRYPT_RIJNDAEL_128;
$dec = @mcrypt_decrypt($enc, $key, $val, $mode, @mcrypt_create_iv( @mcrypt_get_iv_size($enc, $mode), MCRYPT_DEV_URANDOM ) );
return
rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null));
}

function
mysql_aes_encrypt($val,$ky)
{
$key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
for(
$a=0;$a<strlen($ky);$a++)
$key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a]));
$mode=MCRYPT_MODE_ECB;
$enc=MCRYPT_RIJNDAEL_128;
$val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16)));
return
mcrypt_encrypt($enc, $key, $val, $mode, mcrypt_create_iv( mcrypt_get_iv_size($enc, $mode), MCRYPT_DEV_URANDOM));
}
?>
1
[email protected]
24 年前
加密后的结果数据可能是二进制数据,这会在 SQL 查询中产生错误。
因此,请将 base64_encode/base64_decode 函数与 mcrypt() 一起使用
请尝试以下方法

<?php
base64_encode
(mcrypt_ecb(MCRYPT_BLOWFISH,$key,$input,MCRYPT_ENCRYPT));

mcrypt_ecb(MCRYPT_BLOWFISH,$key,base64_decode($input),MCRYPT_DECRYPT);
?>
0
p ete postma - googlemail.com
15 年前
mcrypt 模块初始化失败

我发现了这种情况

usemcrypt.php
<?php
function protect() {
//一些 mcrypt/decrypt 命令
}
?>

filea.php
<?php
include_once('usemcrypt.php');

function
a() {
protect();
}
?>

fileb.php
<?php
function b() {
include_once(
'usemcrypt.php');
protect();
}
?>

filea.php 和 a() 运行正常
fileb.php 和 b() 会报错 mcrypt 模块初始化失败

我假设你无法动态加载该模块。如果使用了调用 mcrypt 的文件,则必须在文件开头包含它,而不是在函数中。
0
Rafael M. Salvioni
16 年前
以下函数是用纯PHP代码实现的RC4密码算法。

该函数用于加密和解密数据。

<?php
/**
* 使用RC4流密码算法加密/解密字符串。
*
* @param string $key 密钥
* @param string $data 已加密/纯数据
* @see http://pt.wikipedia.org/wiki/RC4
* @return string
*/
function rc4($key, $data)
{
// 存储已计算的向量“S”
static $SC;
// 用于交换向量“S”值的函数
$swap = create_function('&$v1, &$v2', '
$v1 = $v1 ^ $v2;
$v2 = $v1 ^ $v2;
$v1 = $v1 ^ $v2;
'
);
$ikey = crc32($key);
if (!isset(
$SC[$ikey])) {
// 基于密钥创建向量“S”
$S = range(0, 255);
$j = 0;
$n = strlen($key);
for (
$i = 0; $i < 255; $i++) {
$char = ord($key{$i % $n});
$j = ($j + $S[$i] + $char) % 256;
$swap($S[$i], $S[$j]);
}
$SC[$ikey] = $S;
} else {
$S = $SC[$ikey];
}
// 加密/解密数据
$n = strlen($data);
$data = str_split($data, 1);
$i = $j = 0;
for (
$m = 0; $m < $n; $m++) {
$i = ($i + 1) % 256;
$j = ($j + $S[$i]) % 256;
$swap($S[$i], $S[$j]);
$char = ord($data[$m]);
$char = $S[($S[$i] + $S[$j]) % 256] ^ $char;
$data[$m] = chr($char);
}
return
implode('', $data);
}
?>
0
Ivan Frederiks
17年前
要在Windows下启用mcrypt扩展,你需要
1) 在php.ini文件中取消注释“extension=php_mcrypt.dll”行
2) 从 http://files.edin.dk/php/win32/mcrypt/ 下载libmcrypt.dll 并将其放入System32目录(例如C:\Windows\System32)。
已在Windows XP + Apache 1.3.37 + PHP 4.4.6(作为SAPI模块!!!)上测试。

附注:
我写下这段是因为当我仅仅取消注释“extension=php_mcrypt.dll”行时,phpMyAdmin提示“无法加载mcrypt扩展。请检查你的PHP配置”。
0
vincent at verbrugh dot nl
18 年前
如果你计划使用Mcrypt加密来存储加密数据(例如密码)到(MySQL)数据库中,请确保将列设置为BLOB而不是VARCHAR。否则数据可能会改变,这可能会在你解密值时产生意想不到的结果。
0
Jerry Hathaway
18 年前
在对256位操作的AES进行基准测试后,我得出结论:CBC比OFB快得多。使用一个14.9 MiB的文件,平均而言……

CBC加密:1.9秒
OFB加密:45.7秒(与CFB相同)
仅读取文件:〜0.53秒

经过一些研究,我得出结论:OFB和CFB比CBC略微安全一些,但是我相信性能差异是由于实现问题造成的。

关于ECB的补充说明:正如下面链接的维基百科中所述,ECB完全不足。它不使用IV(无论它是否提供给Mcrypt),这意味着相同的密钥和明文总是产生相同的密文,并且它不会隐藏模式。该网站显示了一个很好的例子。

非常有用的信息
http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
0
coz AT metamule D0T com
19年前
如果你打算用类似这样的方法加密数据并将其存储在PostgreSQL中。

<?php
function encrypt($string, $key){
$result = '';
for(
$i=1; $i<=strlen($string); $i++){
$char = substr($string, $i-1, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char)+ord($keychar));
$result.=$char;
}
return
$result;
}
?>

确保在创建数据库时将其编码设置为SQL_ASCII,因为你无法将此数据存储在使用UNICODE的数据库中。
0
joseph-at-digiweb-dot-net-dot-nz
19年前
对于在PHP和Java之间进行互操作的进一步说明

如果你在Java端使用BouncyCastle库,那么你现在可以使用其中可用的ZeroBytePadding模式。Mcrypt用空字符而不是空格填充数据……

我已经通过这种方式成功地使用Blowfish/CBC/ZeroBytePadding在PHP和Java之间进行了互操作。
0
paul dot lewis at absolutegenius dot co dot uk
19年前
我花了大部分时间试图在IIS6和Windows Server 2003(Web版)以及PHP 5.0.4下运行mcrypt。

在运行PHP作为ISAPI的环境中,启用某些扩展(mcrypt是其中之一)似乎存在一些不兼容性。

解决问题的方法(错误提示为无法加载 php_mcrypt.dll - 拒绝访问)是使用 CGI 模式运行。虽然这种方式性能可能不如其他方式,但如果你需要 mcrypt 支持(或者我认为的 Oracle 支持),这是我找到的唯一方法。
0
Jurgen Schwietering
20 年前
使用比实际密钥长度更长的密钥时需要注意(例如,使用 160 位密钥而不是 128 位密钥)。

它可以在 PHP 脚本之间工作,但在使用 OpenSSL 或其他与 mcrypt 集成的软件包时可能会出现问题。为了避免不眠之夜,请始终将密钥长度裁剪到支持的长度 (mcrypt_enc_get_key_size)。
0
scott at boothcreek dot com
22 年前
如果你使用 ECB 模式加密,它似乎并没有充分利用 iv(初始化向量),因为使用相同的密钥,无论 iv 是什么,它总是可以解密。

如果你在解密前使用不同的 iv,则解密将失败。我认为使用 CBC 模式比 ECB 模式更好,因为 ECB 模式对于相同的明文总是加密成相同的密文(使你容易受到已知明文攻击)。CBC 模式使用随机 iv,这意味着文本加密结果不同。你可能可以通过在 ECB 模式中使用随机密钥来获得相同的效果。

这来自施耐尔(Schneier)的书 - 应用密码学(ISBN 0-471-11709-9)。对于任何认真使用任何类型加密的人来说,这本书都是必读之作。
-1
phpknights at pookmail dot com
16 年前
Pear 类 Crypt/Blowfish.php 会在可用时使用 mcrypt 模块,但 mcrypt 模块不是必需的。

一些非常简单的 Pear 和示例伪代码,用于通过单向散列和 Blowfish 对称加密来保护你的数据。
https://wikibooks.cn/wiki/Cryptography/Database_protection

使用单向散列和 Blowfish 对称加密。
1. 在加密的数据库中插入 John Doe 的记录。
2. 获取用户 John Doe 的加密记录并解密数据。

1. 在加密的数据库中插入 John Doe 的记录。
<?php

require_once("Crypt/Blowfish.php"); // 一个 Pear 类

$aRecord['email'] = "[email protected]"; // 主键
$aRecord['name'] = "John Doe";
$aRecord['creditnr'] = "0192733652342" ;

// crypt - 单向加密
$cipher_key = crypt( $aRecord['email'] , "AN_SECRET_COMPANY_SALT");

$bf = new Crypt_Blowfish('ecb');
$bf->setKey( $cipher_key );

// crypt_blowfish 对称加密来加密数据
$aRecord['email'] = $bf->encrypt( $aRecord['email'] );
$aRecord['name'] = $bf->encrypt( $aRecord['name'] );
$aRecord['creditnr'] = $bf->encrypt( $aRecord['creditnr'] );

$result = sqlInsert( $aRecord ) ;
?>

2. 获取用户 John Doe 的加密记录并解密数据。
<?php

require_once("Crypt/Blowfish.php"); // 一个 Pear 类

$primary_key = "[email protected]";

// crypt - 单向加密
$cipher_key = crypt( $primary_key , "AN_SECRET_COMPANY_SALT");

$bf = new Crypt_Blowfish('ecb');
$bf->setKey( $cipher_key );

// crypt_blowfish 对称加密来加密主键用于 sql 查询
$select_key = $bf->encrypt( $primary_key ) ;

$aRecord = sqlSelectWithPKEY( $select_key );

// crypt_blowfish 对称加密来解密数据
$aRecord['email'] = $bf->decrypt( $aRecord['email'] );
$aRecord['name'] = $bf->decrypt( $aRecord['name'] );
$aRecord['creditnr'] = $bf->decrypt( $aRecord['creditnr'] );
?>

感谢阅读。
-1
artem at it-nt dot ru
16 年前
一些 LM 散列代码

<?php
function LMhash($string)
{
$string = strtoupper(substr($string,0,14));

$p1 = LMhash_DESencrypt(substr($string, 0, 7));
$p2 = LMhash_DESencrypt(substr($string, 7, 7));

return
strtoupper($p1.$p2);
}

function
LMhash_DESencrypt($string)
{
$key = array();
$tmp = array();
$len = strlen($string);

for (
$i=0; $i<7; ++$i)
$tmp[] = $i < $len ? ord($string[$i]) : 0;

$key[] = $tmp[0] & 254;
$key[] = ($tmp[0] << 7) | ($tmp[1] >> 1);
$key[] = ($tmp[1] << 6) | ($tmp[2] >> 2);
$key[] = ($tmp[2] << 5) | ($tmp[3] >> 3);
$key[] = ($tmp[3] << 4) | ($tmp[4] >> 4);
$key[] = ($tmp[4] << 3) | ($tmp[5] >> 5);
$key[] = ($tmp[5] << 2) | ($tmp[6] >> 6);
$key[] = $tmp[6] << 1;

$is = mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($is, MCRYPT_RAND);
$key0 = "";

foreach (
$key as $k)
$key0 .= chr($k);
$crypt = mcrypt_encrypt(MCRYPT_DES, $key0, "KGS!@#$%", MCRYPT_MODE_ECB, $iv);

return
bin2hex($crypt);
}
?>

一些优化建议?
-2
steve@itemfront dot ltd dot uk
21 年前
刚刚花了一些时间让 mcrypt 支持在 php 中工作。使用了 libmcrypt 2.5.7 版本和 php 4.3.3 版本。开箱即用它无法工作。配置如下:

libmcrypt

./configure --disable-posix-threads --enable-dynamic-loading

php:(正如你所看到的,它是为 SunONE 服务器构建的,但这部分配置很容易!)

./configure --with-nsapi=/usr/iplanet/servers --enable-sigchld --with-ldap --with-zlib-dir=/usr/lib --with-mcrypt=<srcdir>/libmcrypt-2.5.7

此致,Steve
To Top