Maison  >  Article  >  développement back-end  >  Introduction au chiffrement et au déchiffrement dans Laravel

Introduction au chiffrement et au déchiffrement dans Laravel

巴扎黑
巴扎黑original
2017-09-26 09:45:481727parcourir

Cet article vous présente principalement les méthodes d'implémentation de cryptage et de décryptage 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. 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 le cryptage dans. Laravel Et l'implémentation de decrypt est partagée pour la référence et l'étude de chacun. Je ne dirai pas grand-chose ci-dessous, jetons un coup d'œ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=

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',

La méthode d'utilisation est déjà disponible dans Laravel, je n'entrerai donc pas trop dans les détails ici. Les deux principales méthodes utilisées sont le cryptage par cryptage et le déchiffrement par déchiffrement

2 Trouver les fichiers cryptés et décryptés

L'emplacement de. la méthode d'implémentation est que deux fichiers se trouvent dans le répertoire de supplier/illuminate/encryption/, l'un est EncryptionServiceProvider et l'autre est Encrypter

3. Analysez le fichier EncryptionServiceProvider<.>


 public function register()
 {
  $this->app->singleton(&#39;encrypter&#39;, function ($app) {
   $config = $app->make(&#39;config&#39;)->get(&#39;app&#39;); //从config/app.php里拿到配置文件

   if (Str::startsWith($key = $config[&#39;key&#39;], &#39;base64:&#39;)) { //分析配置文件里的key里面有没有带&#39;base64&#39;
    $key = base64_decode(substr($key, 7)); //如果有的话,把key前面的base64:给取消,并且解析出原来的字符串
   }

   return new Encrypter($key, $config[&#39;cipher&#39;]); //实例化Encrypte类,注入到框架里
  });
 }
Ce fichier n'a pas grand chose, mais à partir de là on peut voir qu'en fait, dans le fichier de configuration, on peut écrire directement la clé, et il n'y a pas de précédent. Il peut également être analysé avec base64. 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 la méthode ci-dessus de


 public function __construct($key, $cipher = &#39;AES-128-CBC&#39;)
 {
  $key = (string) $key; //把key转换为字符串

  if (static::supported($key, $cipher)) { //调用一个自定义的方法,用来判断加密方式和要求的key长度是否一样
   $this->key = $key;
   $this->cipher = $cipher;
  } else {
   throw new RuntimeException(&#39;The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.&#39;);
  }
 }
avant instanciation, principalement Il est utilisé 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 également la longueur de la clé correspondante. Plus précisément, la longueur de la clé requise par chaque méthode de cryptage peut être. trouvé dans le document correspondant


 public static function supported($key, $cipher)
 {
  $length = mb_strlen($key, &#39;8bit&#39;); //判断key的字符的长度,按照8bit位的方式计算字符长度

  return ($cipher === &#39;AES-128-CBC&#39; && $length === 16) ||
    ($cipher === &#39;AES-256-CBC&#39; && $length === 32); //编码格式为AES128的要求字符长度为16。编码格式为AES256的要求字符长度为32位
 }
La méthode ci-dessus montre un point rigoureux, utilisant la méthode mb_strlen, et nécessitant que la longueur de calcul soit calculée sur la base de 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 cryptage


 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(&#39;Could not encrypt the data.&#39;);
  }

  $mac = $this->hash($iv = base64_encode($iv), $value); //生成一个签名,用来保证内容参数没有被更改

  $json = json_encode(compact(&#39;iv&#39;, &#39;value&#39;, &#39;mac&#39;)); //把随机码,加密内容,已经签名,组成数组,并转成json格式

  if (! is_string($json)) {
   throw new EncryptException(&#39;Could not encrypt the data.&#39;);
  }

  return base64_encode($json); //把json格式转换为base64位,用于传输
 }
Une méthode personnalisée hash() est utilisée ci-dessus, nous pouvons voir la mise en œuvre de la méthode suivante.


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

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 la sérialisation pour générer une valeur. L'élégance de cette méthode est que peu importe. ce que vous avez Que le contenu soit un tableau ou une chaîne, il peut être converti en 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. Il est non seulement nécessaire de décrypter les données, mais aussi de les décrypter. assurer l'intégrité des données. Et les données infalsifiables


public function decrypt($payload, $unserialize = true)
 {
  $payload = $this->getJsonPayload($payload); //把加密后的字符串转换出成数组。

  $iv = base64_decode($payload[&#39;iv&#39;]); //把随机字符串进行base64解密出来

  $decrypted = \openssl_decrypt( //解密数据
   $payload[&#39;value&#39;], $this->cipher, $this->key, 0, $iv
  );

  if ($decrypted === false) {
   throw new DecryptException(&#39;Could not decrypt the data.&#39;);
  }

  return $unserialize ? unserialize($decrypted) : $decrypted; //把数据转换为原始数据
 }
méthode getJsonPayload


 protected function getJsonPayload($payload)
 {
  $payload = json_decode(base64_decode($payload), true); //把数据转换为原来的数组形式

  if (! $this->validPayload($payload)) { //验证是不是数组以及数组里有没有随机字符串,加密后的内容,签名
   throw new DecryptException(&#39;The payload is invalid.&#39;);
  }

  if (! $this->validMac($payload)) { //验证数据是否被篡改
   throw new DecryptException(&#39;The MAC is invalid.&#39;);
  }

  return $payload;
 }
La méthode validPayload ne sera pas mentionnée, comparez Simple et basique, l'accent est mis sur la vérification validMac pour garantir que les données ne sont pas falsifiées


La méthode calculerMac consiste à se baser sur les données d'origine et à générer une signature avec une valeur aléatoire, puis à utiliser cette signature pour générer à nouveau une signature
 protected function validMac(array $payload)
 {
  $calculated = $this->calculateMac($payload, $bytes = random_bytes(16)); //拿数据和随机值生成一个签名

  return hash_equals( //比对上一步生成的签名和下面生成的签名的hash是否一样。
   hash_hmac(&#39;sha256&#39;, $payload[&#39;mac&#39;], $bytes, true), $calculated //根据原始数据里的签名在新生成一个签名
  );
 }


 protected function calculateMac($payload, $bytes)
 {
  return hash_hmac(
   &#39;sha256&#39;, $this->hash($payload[&#39;iv&#39;], $payload[&#39;value&#39;]), $bytes, true
  );
 }
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 des données


3. Décryptez 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 originales et des valeurs aléatoires, puis d'utiliser cette signature pour générer une signature, et la comparaison consiste également à utiliser la signature dans les données originales pour générer une signature, puis comparer. Je n'arrive pas à comprendre pour le moment 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 d'origine, la valeur binaire originale. la valeur déchiffrée à l'aide d'openssl_decrypt est une chaîne aléatoire après l'utilisation de bits en base64.

  • Lors de la génération de signatures 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, nous utilisons la signature originale comme base pour générer une signature, 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.

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!

Déclaration:
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