This article mainly introduces you to the implementation methods of encrypt and decrypt in Laravel. The article introduces it in great detail through sample code. It has certain reference learning value for everyone's study or work. Friends who need it follow below Let’s learn together.
Preface
Laravel’s encryption mechanism uses OpenSSL to provide AES-256 and AES-128 encryption. This article will introduce in detail about encrypt in Laravel And the implementation of decrypt is shared for everyone's reference and study. I won't say much below, let's take a look at the detailed introduction.
1. Usage method
First, generate the secret key. You need to provide APP_KEY in the .env directory. If it does not exist, you can generate it through the command php artisan key:generate
, or you can set it yourself. The generated example should look like this
APP_KEY=base64:5BM1BXGOBrGeeqJMAWJZSzyzh5yPcCGOcOGPtUij65g=
Configure the encryption key and encryption algorithm in the file, and configure it in the config/app.php directory
$ 'key' => env('APP_KEY'), 'cipher' => 'AES-256-CBC',
The usage method is already available in laravel, so I won’t go into too much detail here. The two main methods used are encryption by encrypt and decryption by decrypt
2. Find encrypted and decrypted files
The location of the implementation method is to find two files in the directory of vendor/illuminate/encryption/, one is EncryptionServiceProvider and the other is Encrypter
3. Analyze the EncryptionServiceProvider file
public function register() { $this->app->singleton('encrypter', function ($app) { $config = $app->make('config')->get('app'); //从config/app.php里拿到配置文件 if (Str::startsWith($key = $config['key'], 'base64:')) { //分析配置文件里的key里面有没有带'base64' $key = base64_decode(substr($key, 7)); //如果有的话,把key前面的base64:给取消,并且解析出原来的字符串 } return new Encrypter($key, $config['cipher']); //实例化Encrypte类,注入到框架里 }); }
There is not much in this file, but we can see from this that in fact, in the configuration file, we can write the key directly without base64 in front of it. It can also be parsed. It is equivalent to saving a few steps
In addition, when instantiating the class, you need to pass in the key and encryption method
4. Analyze the Encrypter file
1. Analyze __construct and execute the above method
##
public function __construct($key, $cipher = 'AES-128-CBC') { $key = (string) $key; //把key转换为字符串 if (static::supported($key, $cipher)) { //调用一个自定义的方法,用来判断加密方式和要求的key长度是否一样 $this->key = $key; $this->cipher = $cipher; } else { throw new RuntimeException('The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.'); } }
public static function supported($key, $cipher) { $length = mb_strlen($key, '8bit'); //判断key的字符的长度,按照8bit位的方式计算字符长度 return ($cipher === 'AES-128-CBC' && $length === 16) || ($cipher === 'AES-256-CBC' && $length === 32); //编码格式为AES128的要求字符长度为16。编码格式为AES256的要求字符长度为32位 }
2. Analyze the encrypt method
public function encrypt($value, $serialize = true) { $iv = random_bytes(16); //生成一个16位的随机字符串 // 使用openssl_encrypt把数据生成一个加密的数据 // 1、判断需要不需要生成一个可存储表示的值,这样做是为了不管你的数据是数组还是字符串都能给你转成一个字符串,不至于在判断你传过来的数据是数组还是字符串了。 // 2、使用openssl_encrypt。第一个参数是传入数据,第二个参数是传入加密方式,目前使用AES-256-CBC的加密方式,第三个参数是,返回加密后的原始数据,还是把加密的数据在经过一次base64的编码,0的话表示base64位数据。第四个参数是项量,这个参数传入随机数,是为了在加密数据的时候每次的加密数据都不一样。 $value = \openssl_encrypt( $serialize ? serialize($value) : $value, $this->cipher, $this->key, 0, $iv ); //使用AES256加密内容 if ($value === false) { throw new EncryptException('Could not encrypt the data.'); } $mac = $this->hash($iv = base64_encode($iv), $value); //生成一个签名,用来保证内容参数没有被更改 $json = json_encode(compact('iv', 'value', 'mac')); //把随机码,加密内容,已经签名,组成数组,并转成json格式 if (! is_string($json)) { throw new EncryptException('Could not encrypt the data.'); } return base64_encode($json); //把json格式转换为base64位,用于传输 }
protected function hash($iv, $value) { // 生成签名 // 1、把随机值转为base64 // 2、使用hash_hmac生成sha256的加密值,用来验证参数是否更改。第一个参数表示加密方式,目前是使用sha256,第二个是用随机值连上加密过后的内容进行,第三个参数是上步使用的key。生成签名。 return hash_hmac('sha256', $iv.$value, $this->key); /根据随机值和内容,生成一个sha256的签名 }
The above encryption is divided into three major steps
1. Generate random code3. Analysis of decrypt method
Decrypting data can be said to be the most complicated part. Not only must the data be decrypted, but the integrity of the data must also be ensured. As well as data tamper-proofpublic function decrypt($payload, $unserialize = true) { $payload = $this->getJsonPayload($payload); //把加密后的字符串转换出成数组。 $iv = base64_decode($payload['iv']); //把随机字符串进行base64解密出来 $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; //把数据转换为原始数据 }
protected function getJsonPayload($payload) { $payload = json_decode(base64_decode($payload), true); //把数据转换为原来的数组形式 if (! $this->validPayload($payload)) { //验证是不是数组以及数组里有没有随机字符串,加密后的内容,签名 throw new DecryptException('The payload is invalid.'); } if (! $this->validMac($payload)) { //验证数据是否被篡改 throw new DecryptException('The MAC is invalid.'); } return $payload; }
protected function validMac(array $payload) { $calculated = $this->calculateMac($payload, $bytes = random_bytes(16)); //拿数据和随机值生成一个签名 return hash_equals( //比对上一步生成的签名和下面生成的签名的hash是否一样。 hash_hmac('sha256', $payload['mac'], $bytes, true), $calculated //根据原始数据里的签名在新生成一个签名 ); }
protected function calculateMac($payload, $bytes) { return hash_hmac( 'sha256', $this->hash($payload['iv'], $payload['value']), $bytes, true ); }
The above decryption is divided into three major steps
1. Determine the integrity of the data PropertyBut there is one more framework. What he uses is to generate a signature through the original data and random values, and then use this signature to generate a signature, and the comparison is also to use the signature in the original data to generate a signature. , and then compare. I can't figure out why it takes a few more steps.
During encryption, we converted the original data using serialize, so we also need to use unserialize to convert the data back accordingly.
Note
#The random item value in openssl_encrypt used during encryption is the original data raw used Binary value, the value decrypted using openssl_decrypt is a random string after base64 bits are used.
When generating signatures for comparison during decryption, instead of using the original signature and then regenerating a signature for comparison based on the content of the original data, we use the original signature as the basis to generate a signature. Sign, then take the signature generated based on the original data, and use this newly generated signature to regenerate a signature. Then compare.
AES256 is encrypted data, which can be decrypted later in reverse. SHA256 generates a signature. This process is irreversible and is used to verify the integrity of the data.
The above is the detailed content of Introduction to encrypt and decrypt in Laravel. For more information, please follow other related articles on the PHP Chinese website!