使用PHP mcrypt与Rijndael/AES

8
我正在尝试使用php中的mcrypt和Rijndael算法对一些文本消息进行加密,但我不确定MCRYPT_MODE_modename(根据PHP手册,这些可用的模式有“ecb”,“cbc”,“cfb”,“ofb”,“nofb”或“stream”,但我读到实际上有更多)。我不知道每个模式都是做什么或如何使用它们。
我读到两件事,ECB模式不应该使用,MCRYPT_RAND也不应该使用。他们没有解释为什么。对于ECB模式,我想这是因为它总是为相同的明文生成相同的加密输出(可能会被攻击者利用),关于MCRYPT_RAND(由@azz在这里提到),我不知道。
我的问题是,我应该使用哪种mcrypt模式,如果能看到使用它的php代码示例将会很棒,因为我找到的所有示例都使用ECB。我正在尝试加密的字符串将只包含ascii文本,长度可变,不超过500个字符。

维基百科对不同的密码块模式有很好的描述,包括它们的运作方式以及优缺点。 - Tails
请查看Cryptography For The Average Developer,其中包含一个出色的工作实现。 - Mark Fox
2个回答

16

ECB是最简单的加密模式之一,但其具有弱点,因此不建议使用(http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation)。CBC被认为比ECB强大得多。其他一些模式可能比CBC更强大,但它们都与流相关,所以CBC应该适合您的需求。

来自...http://us.php.net/manual/en/mcrypt.constants.php...

  • MCRYPT_MODE_ECB(电子密码本)适用于随机数据,例如加密其他密钥。由于数据短且随机,因此ECB的缺点具有有利的负面效果。
  • MCRYPT_MODE_CBC(密码块链接)特别适用于加密文件,在这种情况下,相对于ECB,安全性显著提高。
  • MCRYPT_MODE_CFB(密码反馈)是加密字节流的最佳模式,其中必须加密单个字节。
  • MCRYPT_MODE_OFB(输出反馈,8位)类似于CFB,但可用于无法容忍错误传播的应用程序。由于它以8位模式运行,因此不安全,因此不建议使用它。
  • MCRYPT_MODE_NOFB(输出反馈,n位)类似于OFB,但更安全,因为它在算法的块大小上运行。
  • MCRYPT_MODE_STREAM是一种额外的模式,可包括一些流算法,例如“WAKE”或“RC4”。

我不确定为什么建议不使用MCRYPT_RAND,但可能是因为许多系统上的系统随机数发生器被认为不是真正的随机数发生器。只有两个替代方案,根据您的系统和PHP版本,可能无法使用。来自...http://php.net/manual/en/function.mcrypt-create-iv.php...

  • IV来源可以是MCRYPT_RAND(系统随机数生成器)、MCRYPT_DEV_RANDOM(从/dev/random读取数据)和MCRYPT_DEV_URANDOM(从/dev/urandom读取数据)。在5.3.0之前,Windows仅支持MCRYPT_RAND。

以下代码只是一个快速示例。它可以工作,但我不能保证其强度。

<?php

// 测试代码

$objEncManager = new DataEncryptor();

$sensitiveData = "7890";
echo "原始数据:_" . $sensitiveData . "_<br><br>";

$encryptedData = $objEncManager->mcryptEncryptString( $sensitiveData );
echo "加密数据:_" . $encryptedData . "_<br><br>";
echo "加密数据长度:" . strlen( $encryptedData) . "<br><br>";

$decryptedData = $objEncManager->mcryptDecryptString( $encryptedData, $objEncManager->lastIv );
echo "解密数据:_" . $decryptedData . "_<br><br>";
echo "IV:_" . $objEncManager->lastIv . "_<br><br>";
/* * 注意:这些函数不精确地处理需要加密的数据有尾随空格的情况,所以被它们加密的数据必须没有任何尾随空格。前导空格是可以的。 * * 注意:如果您的数据需要通过非二进制安全的介质传递,您应该base64_encode它,但这会使数据增大约33%。 * * 注意:解密IV必须与加密IV相同,因此加密IV必须存储或与加密数据一起传输。 * 来自(http://php.net/manual/en/function.mcrypt-create-iv.php)... * “IV只是为加密例程提供替代种子。此IV根本不需要保密,尽管这是可取的。你甚至可以将它与你的密文一起发送而不会失去安全性。” *
注意:这些方法不会对各种mcrypt函数的成功性做任何错误检查。
类DataEncryptor { const MY_MCRYPT_CIPHER = MCRYPT_RIJNDAEL_256; const MY_MCRYPT_MODE = MCRYPT_MODE_CBC; const MY_MCRYPT_KEY_STRING = "1234567890-abcDEFGHUzyxwvutsrqpo"; // 这应该是一个随机字符串,推荐32个字节
public $lastIv = '';
public function __construct() { // 什么也不干 }
/** * 接受明文字符串并返回加密版本 */ public function mcryptEncryptString($stringToEncrypt, $base64encoded = true) { // 设置初始化向量 $iv_size = mcrypt_get_iv_size(self::MY_MCRYPT_CIPHER, self::MY_MCRYPT_MODE); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $this->lastIv = $iv;
// 加密数据 $encryptedData = mcrypt_encrypt(self::MY_MCRYPT_CIPHER, self::MY_MCRYPT_KEY_STRING, $stringToEncrypt, self::MY_MCRYPT_MODE, $iv);
// 数据可能需要通过非二进制安全媒介传递,因此如果需要,则进行base64编码。 (使数据大约增加33%) if ($base64encoded) { $encryptedData = base64_encode($encryptedData); $this->lastIv = base64_encode($iv); } else { $this->lastIv = $iv; }
// 返回加密数据 return $encryptedData; }
/** * 接受明文字符串并返回加密版本 */ public function mcryptDecryptString($stringToDecrypt, $iv, $base64encoded = true) { // 注意:解密IV必须与加密IV相同,因此在加密期间必须存储加密IV
// 如果需要,数据可能已经过base64编码,因此请在解密之前进行解码(必须在解密之前进行) if ($base64encoded) { $stringToDecrypt = base64_decode($stringToDecrypt); $iv = base64_decode($iv); }// 解密数据 $decryptedData = mcrypt_decrypt( self::MY_MCRYPT_CIPHER, self::MY_MCRYPT_KEY_STRING, $stringToDecrypt, self::MY_MCRYPT_MODE, $iv );
// 返回解密后的数据 return rtrim( $decryptedData ); // 需要使用rtrim函数移除加密时添加的填充内容 }
} ?>

警告:MCRYPT_RIJNDAEL_256是具有256位块大小的Rijndael密码,换句话说,它与AES不同。还要注意PHP不使用PKCS#7填充的事实标准,并且它不太优雅地处理密钥(在需要时扩展和削减)。再次,随机生成器已经改进。 - Maarten Bodewes

2
ECB模式不安全,因为它在加密数据中没有引入随机性。这基本上意味着你会在输出中看到与输入相同的模式(即查看此处报告的图像,它是Linux标志Tux的“加密”版本)。
MT_RAND被认为不安全,因为它使用操作系统的随机数生成器(PHP的rand()函数)。
为了加密目的,最好使用MCRYPT_DEV_RANDOM(从/dev/random读取数据)或MCRYPT_DEV_URANDOM(从/dev/urandom读取数据)。
最常用和安全的加密模式是CBC和CTR模式,可用于一般用例。始终最好使用加密+身份验证(即使用HMAC进行加密-然后-身份验证)。例如,没有身份验证的CBC模式受Padding Oracle攻击的影响。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接