Laravel Crypt值在每次重新加载时都会发生变化

时间:2014-07-15 21:31:32

标签: php laravel mcrypt

我正在尝试使用Laravel的Crypt功能,只需将值存储在数据库中,稍后再使用即可。但是我注意到我无法解密这个值。

我的应用程序密钥是一个随机的32个字符的字符串。我的密码是MCRYPT_RIJNDAEL_128。 从PHP信息中,安装了MCRYPT,并支持RIJNDAEL_128。

为了测试,我在GET rou上执行以下操作:

$t = "123456789";

var_dump(Crypt::encrypt($t));

请参阅:http://laravel.io/bin/2e9Xr#

在每次页面刷新时,输出是一个不同的值,这显然是不正确的 - 但我不知道为什么。

我正在使用EasyPHP作为我的开发服务器。但是我注意到的一件事是,与生产的Apache Web服务器相比,此环境中的应用程序请求显着缓慢。

这让我想知道每次是否有某种环境刷新,可能会重置MCRYPT用于加密的“资源”,因此每次都不同。

任何线索?

2 个答案:

答案 0 :(得分:4)

这是正常行为。出于安全原因,每个Crypt :: encrypt调用都应该产生不同的输出。

Crypt对于小字符串来说效率非常低。例如,Crypt::encrypt("Hello World")输出如下内容:eyJpdiI6Imhnb2hRazVabUNZUnVRVzFBSEExVkE9PSIsInZhbHVlIjoiTHJ4c05zcjdJZkZwWU1vRVVRMEcwZE5nTUdjQnhyM2RKWTMzSW04b1cxYz0iLCJtYWMiOiIyZjRmNDc3NGEyNGQyOGJjZGQ4MWQxYWViYzI1MjNjZTU0MmY4YTIxYTEyNWVjNDVlZDc4ZWEzNzRmN2QwM2ZiIn0=

立即可识别为基本64字符串。解码后,它变为{"iv":"hgohQk5ZmCYRuQW1AHA1VA==","value":"LrxsNsr7IfFpYMoEUQ0G0dNgMGcBxr3dJY33Im8oW1c=","mac":"2f4f4774a24d28bcdd81d1aebc2523ce542f8a21a125ec45ed78ea374f7d03fb"}

使用Crypt,您可以轻松加密和解密大型明文,而无需担心细节。但是,如果您想存储或传输大量单独加密的实体,那么您可能需要考虑不同的方法。

那为什么会这样?

(注意:目录结构对Laravel 4.2有效。)

首先,大多数安全块密码操作模式需要IV (initialization vector),这是一组长度与块大小匹配的随机字节。对每个密文使用不同的IV对于阻止密码分析和重放攻击非常重要。但是,让我们看看实际的Crypt代码。

config/app.php别名数组开始,我们看到'Crypt' => 'Illuminate\Support\Facades\Crypt'

所以我们检查vendor/laravel/framework/src/Support/Facades目录,我们发现Crypt.php表示模块访问者名称实际上是" encrypter"。检查config/app.php提供程序数组会显示'Illuminate\Encryption\EncryptionServiceProvider'

vendor/laravel/framework/src/Illuminate/Encryption有几个感兴趣的文件:Encrypter.phpEncryptionServiceProvider.php。服务提供者使用创建,配置和返回Encrypter实例的函数绑定访问者。

Encrypter课程中,我们找到了加密方法:

public function encrypt($value)
{
    $iv = mcrypt_create_iv($this->getIvSize(), $this->getRandomizer());
    $value = base64_encode($this->padAndMcrypt($value, $iv));
    // Once we have the encrypted value we will go ahead base64_encode the input
    // vector and create the MAC for the encrypted value so we can verify its
    // authenticity. Then, we'll JSON encode the data in a "payload" array.
    $mac = $this->hash($iv = base64_encode($iv), $value);
    return base64_encode(json_encode(compact('iv', 'value', 'mac')));
}

你有它。每次调用Crypt::encrypt时,它都会生成一个新的IV,加密该值,创建一个MAC的IV和密文,然后返回一个基本的64位编码的JSON字符串,该字符串是IV的关联数组, MAC和密文。每个IV都是不同的,这意味着每个密文和MAC也会不同 - 即使是相同的值。如果所有明文都很大,那么真的很聪明,但对于许多较小的明文来说非常不切实际,因为MAC是不必要的开销。

tl; dr version:

为每个加密调用生成16字节的随机性,并将其级联到密文和MAC中,所有这些都在基本64位编码的JSON关联数组中返回。因此,每个Crypt :: encrypt调用都会产生不同的输出。

答案 1 :(得分:0)

mcrypt的工作方式 - http://mnshankar.wordpress.com/2014/03/29/laravel-hash-make-explained/

$test = 'test';
$crypted = Crypt::encrypt($test);

echo $crypted.'<br />'; // encrypted string
echo Crypt::decrypt($crypted); // "test"