将PHP-mcrypt与Rijndael/AES一起使用

将PHP-mcrypt与Rijndael/AES一起使用,php,encryption,cryptography,aes,mcrypt,Php,Encryption,Cryptography,Aes,Mcrypt,我试图使用php中的mcrypt和密码Rijndael对一些文本消息进行加密,但我不确定mcrypt_MODE_modename(根据php的手册,可以使用“ecb”、“cbc”、“cfb”、“ofb”、“nofb”或“stream”,但我读到了更多)。我不知道每个人都做什么或如何使用它们 我读到两件事,欧洲央行模式不应该使用,麦克里普特·兰德也不应该使用。他们没有解释原因。对于ECB模式,我想这是因为它总是为相同的纯文本生成相同的加密输出(也许这可以用于攻击),不知道MCRYPT_RAND(由

我试图使用php中的mcrypt和密码Rijndael对一些文本消息进行加密,但我不确定mcrypt_MODE_modename(根据php的手册,可以使用“ecb”、“cbc”、“cfb”、“ofb”、“nofb”或“stream”,但我读到了更多)。我不知道每个人都做什么或如何使用它们

我读到两件事,欧洲央行模式不应该使用,麦克里普特·兰德也不应该使用。他们没有解释原因。对于ECB模式,我想这是因为它总是为相同的纯文本生成相同的加密输出(也许这可以用于攻击),不知道MCRYPT_RAND(由@azz提到)


我的问题是,我应该使用什么样的mcrypt模式,如果能看到一个使用它的php代码示例,那就太好了,因为我发现的所有示例都使用ECB。我试图加密的字符串将只包含ascii文本和可变长度,不超过500个字符。

ecb是最简单的,并且有缺点,因此不建议使用()。cbc被认为明显强于欧洲央行。其他一些可能比cbc更强大,但它们都与流相关,所以cbc应该适合您的需要

  • MCRYPT_MODE_ECB(电子码本)适用于随机数据,如加密其他密钥。由于那里的数据短小且随机,欧洲央行的缺点具有有利的负面影响
  • MCRYPT_MODE_CBC(密码块链接)特别适用于加密安全性大大提高的文件
  • MCRYPT_MODE_CFB(密码反馈)是加密字节流的最佳模式,其中必须对单个字节进行加密
  • MCRYPT_模式_of B(8位输出反馈)与CFB相当,但可用于不能容忍错误传播的应用中。它不安全(因为它在8位模式下运行),因此不建议使用它
  • MCRYPT_MODE_NOFB(nbit中的输出反馈)与OFB相当,但更安全,因为它根据算法的块大小进行操作
  • MCRYPT_MODE_STREAM是一种额外的模式,包括一些流算法,如“WAKE”或“RC4”
我不确定为什么建议反对MCRYPT_RAND,但这可能是因为许多系统上的系统随机数生成器被认为不是真正的随机数。只有两种选择,根据您的系统和PHP版本,它们可能不可用。从

  • IV源可以是MCRYPT_RAND(系统随机数生成器)、MCRYPT_DEV_random(从/DEV/random读取数据)和MCRYPT_DEV_Uradom(从/DEV/Uradom读取数据)。在5.3.0之前,MCRYPT_RAND是Windows上唯一受支持的
下面的代码只是一个简单的示例。它起作用了,但我不能证明它的力量

<?php // Test code $objEncManager = new DataEncryptor(); $sensitiveData = "7890"; echo "Raw Data: _" . $sensitiveData . "_<br><br>"; $encryptedData = $objEncManager->mcryptEncryptString( $sensitiveData ); echo "Enc Data: _" . $encryptedData . "_<br><br>"; echo "Enc Data length: " . strlen( $encryptedData) . "<br><br>"; $decryptedData = $objEncManager->mcryptDecryptString( $encryptedData, $objEncManager->lastIv ); echo "D-enc Data: _" . $decryptedData . "_<br><br>"; echo "IV: _" . $objEncManager->lastIv . "_<br><br>"; /* * Note: These functions do not accurately handle cases where the data * being encrypted have trailing whitespace so the data * encrypted by them must not have any. Leading whitespace is okay. * * Note: If your data needs to be passed through a non-binary safe medium you should * base64_encode it but this makes the data about 33% larger. * * Note: The decryption IV must be the same as the encryption IV so the encryption * IV must be stored or transmitted with the encrypted data. * From (http://php.net/manual/en/function.mcrypt-create-iv.php)... * "The IV is only meant to give an alternative seed to the encryption routines. * This IV does not need to be secret at all, though it can be desirable. * You even can send it along with your ciphertext without losing security." * * Note: These methods don't do any error checking on the success of the various mcrypt functions */ class DataEncryptor { const MY_MCRYPT_CIPHER = MCRYPT_RIJNDAEL_256; const MY_MCRYPT_MODE = MCRYPT_MODE_CBC; const MY_MCRYPT_KEY_STRING = "1234567890-abcDEFGHUzyxwvutsrqpo"; // This should be a random string, recommended 32 bytes public $lastIv = ''; public function __construct() { // do nothing } /** * Accepts a plaintext string and returns the encrypted version */ public function mcryptEncryptString( $stringToEncrypt, $base64encoded = true ) { // Set the initialization vector $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; // Encrypt the data $encryptedData = mcrypt_encrypt( self::MY_MCRYPT_CIPHER, self::MY_MCRYPT_KEY_STRING, $stringToEncrypt , self::MY_MCRYPT_MODE , $iv ); // Data may need to be passed through a non-binary safe medium so base64_encode it if necessary. (makes data about 33% larger) if ( $base64encoded ) { $encryptedData = base64_encode( $encryptedData ); $this->lastIv = base64_encode( $iv ); } else { $this->lastIv = $iv; } // Return the encrypted data return $encryptedData; } /** * Accepts a plaintext string and returns the encrypted version */ public function mcryptDecryptString( $stringToDecrypt, $iv, $base64encoded = true ) { // Note: the decryption IV must be the same as the encryption IV so the encryption IV must be stored during encryption // The data may have been base64_encoded so decode it if necessary (must come before the decrypt) if ( $base64encoded ) { $stringToDecrypt = base64_decode( $stringToDecrypt ); $iv = base64_decode( $iv ); } // Decrypt the data $decryptedData = mcrypt_decrypt( self::MY_MCRYPT_CIPHER, self::MY_MCRYPT_KEY_STRING, $stringToDecrypt, self::MY_MCRYPT_MODE, $iv ); // Return the decrypted data return rtrim( $decryptedData ); // the rtrim is needed to remove padding added during encryption } } ?>
ECB模式不安全,因为它不会在加密数据中引入随机性。这基本上意味着您将在输出中看到相同的输入模式(即,查看报告的图像,它是Tux的“加密”版本,Linux的徽标)

MT_RAND被认为是不安全的,因为它使用操作系统的随机数生成器(PHP的
RAND()
函数)

出于加密目的,最好使用
MCRYPT\u DEV\u RANDOM
(从/DEV/RANDOM读取数据)或
MCRYPT\u DEV\u URANDOM
(从/DEV/URANDOM读取数据)


Mcrypt提供的最常用和最安全的加密模式是CBC和CTR模式,适用于一般用例。最好使用加密+身份验证(即先加密,然后使用HMAC进行身份验证)。例如,没有身份验证的CBC模式受相关的影响:Wikipedia很好地描述了不同的模式、它们的操作方式以及它们的优缺点。请查看一个非常有效的实现警告:MCRYPT_RIJNDAEL_256是块大小为256位的RIJNDAEL密码,换句话说,它与AES不同。还要注意的是,PHP并没有使用事实上的PKCS#7填充标准,而且它也没有很好地处理键(在需要时进行扩展和剪切)。然后,随机生成器又得到了改进。