使用PHP mcrypt与Rijndael / AES [英] Using PHP mcrypt with Rijndael/AES
问题描述
我读了两件事,ECB模式不应该被使用,MCRYPT_RAND也没有。他们没有解释为什么。对于ECB模式,我猜是因为它总是为相同的纯文本生成相同的加密输出(也许这可以用于攻击),不了解MCRYPT_RAND(由@azz 使用,并且很高兴看到使用的php代码的例子,因为我发现所有的例子都使用ECB。我试图加密的字符串将只包含ascii文本,可变长度不超过500个字符。 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_RAND,但可能是因为许多系统上的系统随机数生成器不被认为是随机的。只有两个选择,根据您的系统和PHP版本,它们可能不可用。从... http://php.net/manual/en/function .mcrypt-create-iv.php ... 下面的代码只是一个简单的例子。它的作品,但我不能证明它的力量。 I am trying to encrypt some text messages using mcrypt from php and the cipher Rijndael, but I am not sure about the MCRYPT_MODE_modename (according to PHP's manual these are available "ecb", "cbc", "cfb", "ofb", "nofb" or "stream" but I read there are actually a few more). I have no idea what each one do or how to use them. I read two things, that ECB mode should not be used and MCRYPT_RAND neither. They didn't explain why. For the ECB mode I guess it's because it always generate the same encrypted output for the same plain text (maybe this could be used for an attack), no idea about MCRYPT_RAND (mentioned by @azz here). My question is, what mcrypt mode should I use, and it would be great to see an example of php code using it because all the examples I found use ECB. The strings I am trying to encrypt will contain only ascii text, and variable length, not bigger than 500 chars. ecb is the simplest and has weaknesses so it is not recommended (http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation). cbc is considered significantly stronger than ecb. Some of the others may be even stronger than cbc but they are all stream related so cbc should suit your needs. From... http://us.php.net/manual/en/mcrypt.constants.php... I'm not sure why MCRYPT_RAND is recommended against but it may be because the system random number generator on many systems is not considered to be truely random. There are only two alternatives and they may not be available depending on your system and PHP version. From... http://php.net/manual/en/function.mcrypt-create-iv.php... The code below is just a quick sample. It works but I can't attest to it's strength.
这篇关于使用PHP mcrypt与Rijndael / AES的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
<?php
//测试代码
$ objEncManager = new DataEncryptor();
$ sensitiveData =7890;
echo原始数据:_。 $ sensitiveData。 _<峰; br><峰; br> 中;
$ encryptedData = $ objEncManager-> mcryptEncryptString($ sensitiveData);
echoEnc Data:_。 $ encryptedData。 _<峰; br><峰; br> 中;
echoEnc Data length:。 strlen($ encryptedData)。 <峰; br><峰; br> 中;
$ decryptptedData = $ objEncManager-> mcryptDecryptString($ encryptedData,$ objEncManager-> lastIv);
echoD-enc Data:_。 $ decryptptedData。 _<峰; br><峰; br> 中;
echoIV:_。 $ objEncManager-> lastIv。 _<峰; br><峰; br> 中;
/ *
*注意:这些函数不能准确处理数据
*加密的情况,具有尾随空格,因此数据
*加密由他们不能有任何的。领先的空白是可以的
*
*注意:如果您的数据需要通过非二进制安全介质传递,您应该
* base64_encode,但这会使数据大约33%。
*
*注意:解密IV必须与加密IV相同,因此加密
* IV必须与加密数据一起存储或传输。
*从(http://php.net/manual/en/function.mcrypt-create-iv.php)...
*IV只是为了给一个替代种子加密例程
*这个IV不需要秘密,虽然可以是可取的。
*你甚至可以发送它与你的密文,而不会失去安全性。
*
*注意:这些方法不会对各种mcrypt函数的成功进行任何错误检查
* /
class 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()
{
// do nothing
}
/ **
*接受一个明文字符串并返回加密版本
* /
public function mcryptEncryptString($ stringToEncrypt,$ base64encoded = true)
{
//设置初始化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;
//加密数据
$ encryptedData = mcrypt_encrypt(self :: MY_MCRYPT_CIPHER,self :: MY_MCRYPT_KEY_STRING,$ stringToEncrypt,self :: MY_MCRYPT_MODE,$ iv);
//数据可能需要通过非二进制安全介质传递,因此如果需要,可以将base64_encode进行编码。 (使数据大约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_encoded,因此如果需要解码(必须在解密之前)
if($ base64encoded){
$ stringToDecrypt = base64_decode($ stringToDecrypt);
$ iv = base64_decode($ iv);
}
//解密数据
$ decryptptedData = mcrypt_decrypt(self :: MY_MCRYPT_CIPHER,self :: MY_MCRYPT_KEY_STRING,$ stringToDecrypt,self :: MY_MCRYPT_MODE,$ iv);
//返回解密的数据
return rtrim($ decryptptedData); //需要rtrim来删除在加密过程中添加的填充
}
}
?>
<?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
}
}
?>