Exemple de partage de méthodes d'implémentation de chiffrement et de déchiffrement dans Laravel

小云云
Libérer: 2023-03-19 12:34:01
original
1812 Les gens l'ont consulté

Cet article vous présente principalement les méthodes d'implémentation de cryptage et de déchiffrement dans Laravel. L'article le présente en détail à travers un exemple de code. Il a une certaine valeur d'apprentissage de référence pour les études ou le travail de tous les amis qui en ont besoin, suivez l'éditeur ci-dessous. Venez apprendre ensemble.

Avant-propos

Le mécanisme de cryptage de Laravel utilise OpenSSL pour fournir le cryptage AES-256 et AES-128 Cet article présentera en détail l'implémentation du cryptage et du décryptage dans Laravel et le partagera pour votre référence et. apprentissage. Pas grand chose à dire ci-dessous, jetons un œil à l’introduction détaillée.

1. Comment utiliser

Tout d'abord, générez la clé secrète. Vous devez fournir APP_KEY dans le répertoire .env si celui-ci n'est pas disponible, vous pouvez le générer via la commande php artisan key:generate, ou vous pouvez le définir vous-même. L'exemple généré devrait ressembler à ceci

APP_KEY=base64:5BM1BXGOBrGeeqJMAWJZSzyzh5yPcCGOcOGPtUij65g=
Copier après la connexion

Configurez la clé de chiffrement et l'algorithme de chiffrement dans le fichier, et configurez-le dans le répertoire config/app.php

$ 'key' => env('APP_KEY'),
 
  'cipher' => 'AES-256-CBC',
Copier après la connexion

Méthodes d'utilisation, il existe déjà des méthodes d'utilisation dans Laravel, donc je n'entrerai pas trop dans les détails ici. Les deux principales méthodes utilisées sont le cryptage du cryptage et le déchiffrement du décryptage

2 Trouver les fichiers de cryptage et de décryptage

L'emplacement de la méthode d'implémentation est dans supplier/illuminate/ Deux fichiers. ont été trouvés dans le répertoire chiffrement/, l'un est EncryptionServiceProvider et l'autre est Encrypter

3 Analysez le fichier EncryptionServiceProvider

 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类,注入到框架里
  });
 }
Copier après la connexion

Ce fichier n'a pas grand chose, mais grâce à cela nous pouvons. voir Oui, en fait, dans le fichier de configuration, on peut écrire la clé directement, et elle peut aussi être analysée sans base64 devant. Cela équivaut à enregistrer quelques étapes

De plus, lors de l'instanciation de la classe, vous devez transmettre la clé et la méthode de cryptage

Analyser le fichier Encrypter

.

1. Analysez __construct et exécutez

 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.');
  }
 }
Copier après la connexion

avant l'instanciation. La méthode ci-dessus est principalement utilisée pour déterminer si la méthode de cryptage et la longueur de la clé transmise sont les mêmes, car différentes méthodes de cryptage nécessitent une correspondance. clés. La longueur est également requise. Plus précisément, la longueur de la clé requise pour chaque méthode de cryptage peut être trouvée dans le document correspondant

 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位
 }
Copier après la connexion

La méthode ci-dessus montre un point rigoureux, en utilisant la méthode mb_strlen, et la longueur doit être calculée selon Calculé en utilisant 8 bits. L’avantage est que quel que soit le système d’exploitation utilisé, la durée du calcul est la même.

En prenant en compte les conditions des différents systèmes d'exploitation, il n'y aura aucun problème de cryptage.

2. Analysez la méthode de chiffrement

 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位,用于传输
 }
Copier après la connexion

Une méthode personnalisée hash() est utilisée ci-dessus. Nous pouvons jeter un œil à l'implémentation de la méthode.

 protected function hash($iv, $value)
 {
  // 生成签名
  // 1、把随机值转为base64
  // 2、使用hash_hmac生成sha256的加密值,用来验证参数是否更改。第一个参数表示加密方式,目前是使用sha256,第二个是用随机值连上加密过后的内容进行,第三个参数是上步使用的key。生成签名。
  return hash_hmac('sha256', $iv.$value, $this->key); /根据随机值和内容,生成一个sha256的签名
 }
Copier après la connexion

Le cryptage ci-dessus est divisé en trois étapes principales

1. Générer un code aléatoire

2. Générer du contenu crypté

3. Générer une signature

Le framework utilise une méthode élégante, utilisant Serialize pour générer une valeur. L'élégance de cette méthode est qu'elle peut être convertie en chaîne, que votre contenu soit un tableau ou un. chaîne. Quelle est la différence entre utiliser sérialiser et utiliser json_encode ? Je pense que le plus grand avantage est que lorsque le contenu que vous souhaitez chiffrer est relativement volumineux, la sérialisation est relativement plus rapide.

Une autre chose est que le framework utilise une chaîne aléatoire lors du cryptage. Pourquoi utiliser une chaîne aléatoire ? Puisqu'une chaîne aléatoire est utilisée, le contenu crypté sera différent à chaque fois pour empêcher les autres de le deviner.

3. Analyse de la méthode de décryptage

Le décryptage des données peut être considéré comme la partie la plus compliquée. Non seulement les données doivent être décryptées, mais leur intégrité doit également être garantie, et les données doivent être infalsifiables

public 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; //把数据转换为原始数据
 }
Copier après la connexion

Méthode getJsonPayload

 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;
 }
Copier après la connexion

Je ne parlerai pas de la méthode validPayload, qui est relativement simple et basique. L'accent est mis sur la vérification validMac. pour s'assurer que les données ne sont pas falsifiées. C'est la chose la plus importante

 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 //根据原始数据里的签名在新生成一个签名
  );
 }
Copier après la connexion

La méthode calculateMac consiste à générer une signature basée sur les données d'origine et les valeurs aléatoires, puis à utiliser cette signature pour générer. une signature à nouveau

 protected function calculateMac($payload, $bytes)
 {
  return hash_hmac(
   'sha256', $this->hash($payload['iv'], $payload['value']), $bytes, true
  );
 }
Copier après la connexion

Le décryptage ci-dessus est divisé en trois étapes principales

1. Déterminer l'intégrité des données

2. Déterminer la cohérence de les données

3. Décrypter le contenu des données.

Il y a quelque chose d'étrange dans cette signature de vérification. Ce n'est pas comme notre vérification habituelle des signatures. Nous vérifions généralement les signatures en utilisant des données originales et des valeurs aléatoires pour générer une signature, puis comparons la signature générée avec la signature des données originales pour déterminer si elle a été falsifiée.

Mais il existe un autre cadre. Ce qu'il utilise est de générer une signature à travers les données d'origine et les valeurs aléatoires, puis d'utiliser cette signature pour générer une signature, et la comparaison est également basée sur le données originales. La signature génère une signature puis la compare. Je n'arrive pas à comprendre pourquoi il faut quelques étapes supplémentaires.

Pendant le cryptage, nous avons converti les données d'origine à l'aide de la sérialisation, nous devons donc également utiliser la désérialisation pour reconvertir les données en conséquence.

Remarque

  • La valeur de l'élément aléatoire dans openssl_encrypt utilisée pour le cryptage est la valeur binaire des données brutes d'origine utilisées, et la valeur déchiffrée à l'aide d'openssl_decrypt est utilisée. Une chaîne aléatoire après les bits en base64.

  • Lors de la génération d'une signature pour comparaison lors du décryptage, au lieu d'utiliser la signature originale puis de régénérer une signature pour comparaison basée sur le contenu des données originales, une signature est générée sur la base de la signature originale, puis prenez la signature générée sur la base des données d'origine et utilisez cette signature nouvellement générée pour régénérer une signature. Alors comparez.

  • AES256 est une donnée cryptée, qui peut être décryptée ultérieurement à l'envers. SHA256 génère une signature. Ce processus est irréversible et permet de vérifier l'intégrité des données.

Recommandations associées :

Comment utiliser correctement AES_ENCRYPT() et AES_DECRYPT() pour le cryptage et le déchiffrement MySQL

Solution à l'erreur Aucun chiffreur pris en charge trouvé lors de l'utilisation de Laravel 5.1

javascript - décryptage de encryptData dans l'applet wx.getUserInfo

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal