我使用Laravel 5.7,并且有两个运行在不同服务器上的应用程序。我想与加密通信。因此,两端都需要具有特定的密钥。默认的laravel加密设置为AES-256-CBC。
所以我想,我需要这样的32字节密钥:
$ key = bin2hex(openssl_random_pseudo_bytes(32,$ cstrong));
我得到了一个64位长的十六进制字符串,我想在两端保存,因此它们都可以在一侧进行加密,而在另一侧进行解密。
但是不知何故,此密钥不被接受。 Laravel抛出: 唯一受支持的密码是具有正确密钥长度的AES-128-CBC和AES-256-CBC
我还尝试使用32个字符的密钥将其设置为16字节。也行不通。
但是,它确实可以通过使用16个字符的密钥将其设置为8位来工作。但这对我来说没有任何意义?
Laravel本身使用类似如下的键: base64:X,其中X = 44字符串。
我在某处读到AES-256-CBC需要64个字符的密钥,其中44个字符应为base64。我不确定这是否正确,但我很难做到这一点。如何读取以base64:为前缀的密钥?如何将其恢复为常规字符串。
目前,我已经使用了这16个字符串,但是看起来不太正确。那么,如何生成有效的AES-256-CBC密钥,以及如何存储它呢?如果需要base64,该如何工作?编码64个生成的十六进制密钥可以使我返回88个字符串。
感谢您的帮助。
答案 0 :(得分:1)
我无法亲自尝试,但请查看源代码here:
/**
* Create a new encryption key for the given cipher.
*
* @param string $cipher
* @return string
*/
public static function generateKey($cipher)
{
return random_bytes($cipher === 'AES-128-CBC' ? 16 : 32);
}
因此,您只需要调用random_bytes()
(或其等效的openssl),要么要求16个字节(对于AES-128-CBC),要么要求32个字节(对于AES-256-CBC)。 )。这是有道理的,因为最后,AES密钥只不过是一堆随机字节。
可能会使您感到困惑的是术语string
的使用。与类型string
的常见用法不同,在这种情况下,它不是 printable 字符串,而是一个字节的集合(16个或32个字节)。
这就是加入Base64
translation的原因。它允许您仅通过ASCII字符来表示字节的集合。我怀疑在某些配置文件中找到了您所引用的“ base64:X,其中X = 44字符串”值,该文件通常只应包含可读字符。实际上,将32个字节转换为Base64格式将产生44个字符。在这种情况下,base64:
前缀仅用于指示该值以Base64格式存储。
说明所有这些的示例:
$key = random_bytes(32);
var_dump($key);
var_dump(base64_encode($key));
给予
string(32) "?9???֔e?N??Y?&[??b?4@O|?\?"
string(44) "45U5nvetGyfWlGWOF06N+VnIJlvwx2L3fzRAT3z5XPY="
后者是一种用于存储密钥的便捷格式。
PS:Encryption - Configuration section of the docuemntation提到
在使用Laravel的加密器之前,您必须在 config / app.php配置文件。您应该使用php artisan key:生成命令以生成此密钥
也许该命令可以完成您尝试做的所有事情?
答案 1 :(得分:1)
Laravel使用Illuminate\Support\Facades\Crypt,它专为端到端加密而设计。因此,这意味着您可以安全地对数据库中的数据进行加密和解密,但它不是为进行大规模通信加密而设计的。
PHP 7.2+与LibSodium紧密集成:使用您自己的宅基地加密方法并不受欢迎。您可以在php.ini
配置中启用扩展名,也可以通过使用该配置编译PHP。您可以read more on the docs。
让我们说Bob想要向Alice发送消息。 Bob和Alice都需要密钥对来加密和解密消息或数据。
sodium_crypto_box_keypair();
这些应该存储在数据库中,并且可以使用互译器或后者(例如base64*
)来实现。每个用户都应拥有一个唯一的密钥对,该密钥对可以在注册帐户后发出。
您可以通过添加Laravel \App\User.php
文件并添加新的可填充keypair
来实现。在表用户上创建一个新的迁移,像这样追加列密钥对:
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('key_pair')->unique()->nullable();
});
}
然后转到您的App\Http\Controllers\Auth\RegisterController.php
文件,并附加create
方法。
现在要加密时,可以引用用户密钥对。让Bob来:Bob的ID为1。让Alice:Alice的ID为2。
$bob = User::find(1);
$alice = User::find(2);
我们现在可以通过创建钠密码盒来加密来自Bob的消息并将其发送给Alice:
$kp = sodium_crypto_box_keypair_from_secretkey_and_publickey(
sodium_crypto_box_secretkey($bob->keypair),
sodium_crypto_box_publickey($alice->keypair) # Encrypt with Alices Public Key
);
$cbox = sodium_crypto_box(base64_encode('Hello, Alice. This is Bob.'), ($nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES)), $kp);
我们现在可以将IV(或更好地称为现时)和cyprto盒发送给Alice。如果爱丽丝现在想阅读消息,则可以使用她的私钥和鲍勃斯公钥进行阅读。
$kp = sodium_crypto_box_keypair_from_secretkey_and_publickey(
sodium_crypto_box_secretkey($alice->keypair),
sodium_crypto_box_publickey($bob->keypair) # Decrypt with Bobs public key
);
echo base64_decode(sodium_crypto_box_open($cbox, $nonce, $kp));
我built a container使用LibSodium进行加密并更轻松地对消息签名。我希望这可以帮助您理解概念以及如何使用加密并与base64*
一起存储。