cookie加密解密和保证数据完整性(不被篡改)
创始人
2024-03-19 11:52:31
0

cookie加密解密和保证数据完整性

AES-128-CBC`加密算法

AES-128-CBC是一种分组对称加密算法,即用同一组key进行明文和密文的转换,以128bit为一组,128bit==16Byte,意思就是明文的16字节为一组对应加密后的16字节的密文。
若最后剩余的明文不够16字节,需要进行填充,通常采用PKCS7进行填充。比如最后缺3个字节,则填充3个字节的0x03;若最后缺10个字节,则填充10个字节的0x0a;
若明文正好是16个字节的整数倍,最后要再加入一个16字节0x10的组再进行加密

CBC加密原理:
明文跟向量异或,再用KEY进行加密,结果作为下个BLOCK的初始化向量。

解密原理:
使用密钥先对密文解密,解密后再同初始向量异或得到明文。

加密时需要的参数:
1、传入要加密的明文
2、传入一个16字节的key
3、传入一个16字节的初始偏移向量IV

解密时需要的参数:

1、带解密的密文
2、加密解密的key一致
3、跟加密时传递IV参数一致

正文:

laravel初始化会加载 \App\Http\Middleware\EncryptCookies::class中间件用来加密解密cookie
代码:


use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;class EncryptCookies extends Middleware
{/*** The names of the cookies that should not be encrypted.** @var array*/protected $except = [//];
}

EncryptCookies 继承了 EncryptCookies,处理逻辑都在EncryptCookies这个类中

关键代码:

    /*** Handle an incoming request.** @param  \Illuminate\Http\Request  $request* @param  \Closure  $next* @return \Symfony\Component\HttpFoundation\Response*/public function handle($request, Closure $next){return $this->encrypt($next($this->decrypt($request))); //加密解密}

加密代码:

    /*** Encrypt the given value.** @param  mixed  $value* @param  bool  $serialize* @return string** @throws \Illuminate\Contracts\Encryption\EncryptException*/public function encrypt($value, $serialize = true){$iv = random_bytes(openssl_cipher_iv_length($this->cipher));//偏移向量IV// First we will encrypt the value using OpenSSL. After this is encrypted we// will proceed to calculating a MAC for the encrypted value so that this// value can be verified later as not having been changed by the users.$value = \openssl_encrypt($serialize ? serialize($value) : $value,$this->cipher, $this->key, 0, $iv);//key在.env中配置if ($value === false) {throw new EncryptException('Could not encrypt the data.');}// Once we get the encrypted value we'll go ahead and base64_encode the input// vector and create the MAC for the encrypted value so we can then verify// its authenticity. Then, we'll JSON the data into the "payload" array.$mac = $this->hash($iv = base64_encode($iv), $value); //签名,base64加密之后再计算,双重加密$json = json_encode(compact('iv', 'value', 'mac'));if (json_last_error() !== JSON_ERROR_NONE) {throw new EncryptException('Could not encrypt the data.');}return base64_encode($json);//再次加密}

这里的$this->encrypter对应是vendor/laravel/framework/src/Illuminate/Encryption/Encrypter.php类

  /*** Encrypt the given value.** @param  mixed  $value* @param  bool  $serialize* @return string** @throws \Illuminate\Contracts\Encryption\EncryptException*/public function encrypt($value, $serialize = true){$iv = random_bytes(openssl_cipher_iv_length($this->cipher));// First we will encrypt the value using OpenSSL. After this is encrypted we// will proceed to calculating a MAC for the encrypted value so that this// value can be verified later as not having been changed by the users.$value = \openssl_encrypt($serialize ? serialize($value) : $value,$this->cipher, $this->key, 0, $iv);if ($value === false) {throw new EncryptException('Could not encrypt the data.');}// Once we get the encrypted value we'll go ahead and base64_encode the input// vector and create the MAC for the encrypted value so we can then verify// its authenticity. Then, we'll JSON the data into the "payload" array.$mac = $this->hash($iv = base64_encode($iv), $value);$json = json_encode(compact('iv', 'value', 'mac'));if (json_last_error() !== JSON_ERROR_NONE) {throw new EncryptException('Could not encrypt the data.');}return base64_encode($json);}

Laravel 的加密机制使用的是 OpenSSL 所提供的 AES-256 和 AES-128 加密,所有 Laravel 加密之后的结果都会使用消息认证码 (MAC) 签名,使其底层值不能在加密后再次修改
采用的是AES-128-CBC加密算法

解密代码:

  /*** Decrypt the given value.** @param  string  $payload* @param  bool  $unserialize* @return mixed** @throws \Illuminate\Contracts\Encryption\DecryptException*/public function decrypt($payload, $unserialize = true){$payload = $this->getJsonPayload($payload);$iv = base64_decode($payload['iv']);// Here we will decrypt the value. If we are able to successfully decrypt it// we will then unserialize it and return it out to the caller. If we are// unable to decrypt this value we will throw out an exception message.$decrypted = \openssl_decrypt($payload['value'], $this->cipher, $this->key, 0, $iv);if ($decrypted === false) {throw new DecryptException('Could not decrypt the data.');}return $unserialize ? unserialize($decrypted) : $decrypted;}
   /*** Get the JSON array from the given payload.** @param  string  $payload* @return array** @throws \Illuminate\Contracts\Encryption\DecryptException*/protected function getJsonPayload($payload){$payload = json_decode(base64_decode($payload), true); //之前加密这里对应解密var_dump($payload);// If the payload is not valid JSON or does not have the proper keys set we will// assume it is invalid and bail out of the routine since we will not be able// to decrypt the given value. We'll also check the MAC for this encryption.if (! $this->validPayload($payload)) {throw new DecryptException('The payload is invalid.');}if (! $this->validMac($payload)) {throw new DecryptException('The MAC is invalid.');}return $payload;}
array(3) {["iv"]=>string(24) "YlBI1gpkduvfhdVbKtVI0g=="["value"]=>string(64) "kdL5N3LkUNoCtsHFcQAWmBx4+3+pCH6814uV0l4Y3A4qMhxr2/ZsT9W/VGXU21yB"["mac"]=>string(64) "4d47c1452cf3b8772e6528dae7247a51a9b95e36636b9228ab4f081522a55b8e"
}

关键代码:
this−>validMac(this->validMac(this−>validMac(payload)方法验证数据完整性

    /*** Determine if the MAC for the given payload is valid.** @param  array  $payload* @return bool*/protected function validMac(array $payload){$calculated = $this->calculateMac($payload, $bytes = random_bytes(16));同样算法算出签名return hash_equals( hash_hmac('sha256', $payload['mac'], $bytes, true), $calculated);//和之前存储的签名作比较}
    /*** Calculate the hash of the given payload.** @param  array  $payload* @param  string  $bytes* @return string*/protected function calculateMac($payload, $bytes){return hash_hmac('sha256', $this->hash($payload['iv'], $payload['value']), $bytes, true);}

扩展

数字签名:
在这里插入图片描述
验签:

在这里插入图片描述

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...