Mcrypt 函数

目录

添加笔记

用户贡献的笔记 24 笔记

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

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

包括 des、3des、rc4、aes 和 rijndael 的纯 PHP 实现。如果可用,则使用 mcrypt,否则使用纯 PHP 实现。它还具有作为其文档第 3.5.5 节“速度比较”中所述的最快现有的纯 PHP aes 实现的优点。
duerra_NOT_THIS_ at pushitlive dot net
17 年前
对于那些需要使用 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);
}
?>
triptripon at gmail dot com
18 年前
关于将结果存储在使用 Unicode 的 Postgres 数据库中(以下帖子的后续)。
您无需将数据库的编码更改为 ASCII。
只需使用 BASE64 编码结果,这完全安全。
解密之前使用 base64_decode。
-- Tomer Levinboim
herowekker at hotmail dot com
21 年前
mcrypt_ecb 与 base64_decode 出现了一些问题,我发现它必须被截断才能正常工作

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

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

为了使 php 中的 mcrypt 正常工作,您必须使用以下选项配置和编译 libmcrypt 源代码包
./configure --disable-posix-threads --enable-dynamic-loading
simms
20 年前
DEBIAN 用户:避免 mcrypt 安装头痛。
要将 mcrypt 支持添加到现有的 php 安装中,请获得 root 权限并运行

apt-get install php4-mcrypt

重新启动您的 web 服务器,瞧。
pawelNOSPAM at rsc dot pl
23 年前
如果您已成功编译 mcrypt 和 php,但 phpinfo() 显示没有支持的密码和模式,请尝试将 libdirs(/usr/local/libmcrypt、/usr/local/libcrypt)的模式更改为 755。
patrickdk at patrickdk dot com
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));
}
?>
mountie at paygate dot net
24 年前
加密后的结果数据可能是二进制数据,它会导致 SQL 查询出现错误。
因此,请在 mcrypt() 中使用 base64_encode/base64_decode 函数。
尝试以下操作

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

mcrypt_ecb(MCRYPT_BLOWFISH,$key,base64_decode($input),MCRYPT_DECRYPT);
?>
p ete postma - googlemail.com
14 年前
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 的文件,它必须在文件头部包含,而不是在函数中。
Rafael M. Salvioni
15 年前
以下函数是用纯 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);
}
?>
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 模块!!!)上测试。

P.S.
我写下这些,因为当我简单地取消注释 "extension=php_mcrypt.dll" 行时,我从 phpMyAdmin 中得到了 "无法加载 mcrypt 扩展。请检查您的 PHP 配置。" 错误。
vincent at verbrugh dot nl
18 年前
如果您计划使用 Mcrypt 加密将加密数据(例如密码)存储在(MySQL)数据库中,请确保将该列设置为 BLOB 而不是 VARCHAR。否则,数据可能会改变,这会导致您解密值时出现意外结果。
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
coz AT metamule D0T com
18 年前
如果您打算使用类似的东西加密数据并将其存储在 postgres 中。

<?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 的数据库中。
joseph-at-digiweb-dot-net-dot-nz
18 年前
对于那些在 PHP 和 Java 之间进行互操作的人来说,还有一个补充说明。

如果您在 Java 端使用的是 BouncyCastle 库,那么现在可以使用它提供的 ZeroBytePadding 模式。Mcrypt 使用 Null 而不是空格填充数据。

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

在这个环境中,当您以 ISAPI 方式运行 PHP 时,似乎在启用某些扩展(mcrypt 是其中之一)时存在一些不兼容性。

解决问题的方法(错误将是无法加载 php_mcrypt.dll - 访问被拒绝)是使用 CGI 运行。虽然从性能角度来看,这并不应该像预期的那样好,但如果您需要 mcrypt 支持(或者 Oracle 支持,我相信也是如此),那么这是我找到的唯一方法。
Jurgen Schwietering
19 年前
注意使用比实际密钥大小更长的密钥(例如,160 位而不是 128 位)。

它可以在 PHP 脚本之间工作,但可能会导致使用 openssl 或其他与 mcrypt 集成的包时出现问题。请始终将其剪切到支持的大小(mcrypt_enc_get_key_size),以避免失眠之夜。
scott at boothcreek dot com
22 年前
如果您使用 ECB 模式加密,它似乎并没有使用 iv(初始化向量)来做很多事情,给定相同的密钥,无论 iv 是什么,它总是会解密它。如果您使用 CBC 模式,则必须使用与加密时相同的 iv 解密。

如果您在解密之前使用不同的 iv,您的解密将无法正常工作。恕我直言,使用 CBC 模式比 ECB 模式更好,因为 ECB 模式始终会将相同的明文加密为相同的密文(使您容易受到已知明文攻击)。CBC 使用随机 iv,这意味着文本加密为不同的内容。您可能可以通过在 ECB 模式中使用随机密钥来获得相同的效果。

在施奈尔著作 - 应用密码学(ISBN 0-471-11709-9)中阅读到这些内容。这本书是任何认真使用任何类型加密的人必读之书。
phpknights at pookmail dot com
16 年前
Pear 类 Crypt/Blowfish.php 将在可用时使用 mcrypt 模块,但该模块不是必需的。

一些非常容易的 Pear 和示例伪代码,通过使用单向哈希和 Blowfish 对称加密来保护您的数据。
http://en.wikibooks.org/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 的主键
$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'] );
?>

感谢您阅读本文。
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);
}
?>

一些优化?
steve@itemfront dot ltd dot uk
20 年前
刚花了些时间让 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

hth, steve
To Top