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

Ali*_*ias 1 php mcrypt laravel

我正在尝试使用 Laravel 的Crypt功能,简单地将一个值存储在数据库中并稍后获取以使用。但是我注意到我无法解密这个值。

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

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

$t = "123456789";

var_dump(Crypt::encrypt($t));
Run Code Online (Sandbox Code Playgroud)

见:http : //laravel.io/bin/2e9Xr#

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

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

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

有什么线索吗?

Jon*_*oss 5

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

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

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

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

那么为什么会这样呢?

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

首先,最安全的块密码操作模式需要一个IV(初始化向量),它是一组长度与块大小匹配的随机字节。对每个密文使用不同的 IV 对于阻止密码分析和重放攻击很重要。但让我们看一下实际的 Crypt 代码。

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

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

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

Encrypter类中,我们找到了 encrypt 方法:

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')));
}
Run Code Online (Sandbox Code Playgroud)

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

tl;博士版本:

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