Maison  >  Article  >  développement back-end  >  Introduction à l'utilisation d'openssl pour remplacer mcrypt dans PHP7.1

Introduction à l'utilisation d'openssl pour remplacer mcrypt dans PHP7.1

不言
不言original
2018-07-03 15:23:521778parcourir

Cet article présente principalement l'exemple détaillé d'utilisation d'openssl pour remplacer mcrypt dans PHP7.1. Cet article vous présente en détail. Les amis qui en ont besoin peuvent s'y référer

Dans le développement PHP, utilisez mcrypt. fonctions Les opérations de chiffrement et de déchiffrement AES peuvent être facilement effectuées, mais l'extension mcrypt est abandonnée dans PHP7.1, il faut donc trouver une autre implémentation. Le remplacement de mcrypt par openssl est déjà souligné dans le manuel de migration, mais aucun exemple spécifique n'est donné. Il existe de nombreux exemples en ligne qui peuvent remplacer la plupart des scénarios, mais les détails ne sont pas expliqués. De même, la simple utilisation d'exemples en ligne peut entraîner des problèmes de compatibilité avant et après le remplacement du code dans certains scénarios de code. Parlons des codes spécifiques et des raisons ci-dessous.

Nous donnons d'abord directement le code de remplacement, puis analysons le problème à partir du code. (L'algorithme analysé dans cet article est AES-128-CBC)

Exemple de remplacement

L'exemple montrera deux façons d'utiliser mcrypt, principalement La différence réside dans le remplissage (le remplissage sera expliqué ci-dessous). Pendant tout le processus de cryptage et de déchiffrement, le code le plus complet implémentera automatiquement le remplissage et la suppression du remplissage, et le code le plus simple ignorera directement le remplissage, mais les deux méthodes peuvent fonctionner normalement dans le développement réel (versions antérieures à 7.1), il est recommandé ; pour ajouter du rembourrage. Veuillez consulter l'exemple spécifique suivant :

mcrypt n'utilise pas de remplissage

le cryptage mcrypt :

 $key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; 
 $iv = 'aaaaaaaaaaaaaaaa';
 $data = 'dataString';
 $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
 mcrypt_generic_init($cipher, $key, $iv);
 $cipherText256 = mcrypt_generic($cipher, $data);
 mcrypt_generic_deinit($cipher);
 return bin2hex($cipherText256);

Code de cryptage Openssl avec la même fonction :

 $key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; 
 $iv = 'aaaaaaaaaaaaaaaa';
 $data = 'dataString';

 $data = $data . str_repeat("\x00", 16 - (strlen($data) % 16)); // 双引号可以解析asc-ii码\x00
 return bin2hex(openssl_encrypt($data, "AES-256-CBC", $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));

mcrypt utilise le remplissage

le cryptage mcrypt :

$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; 
 $iv = 'aaaaaaaaaaaaaaaa';
 $data = 'dataString';
 // 填充(移除填充反着移除即可)
 $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
 $pad = $block - (strlen($data) % $block);
 if ($pad <= $block) {
 $char = chr($pad);
 $data .= str_repeat($char, $pad);
 }
 $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, &#39;&#39;, MCRYPT_MODE_CBC, &#39;&#39;);
 mcrypt_generic_init($cipher, $key, $iv);
 $cipherText256 = mcrypt_generic($cipher, $data);
 mcrypt_generic_deinit($cipher);
 return bin2hex($cipherText256);

le code de cryptage openssl avec la même fonction :

 $key = &#39;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#39;; 
 $iv = &#39;aaaaaaaaaaaaaaaa&#39;;
 $data = &#39;dataString&#39;;  
return bin2hex(openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));

Les deux exemples ci-dessus s'exécutent avec succès, avec le premier exemple (sans remplissage, mais remplissage dans openssl) et le deuxième exemple (avec remplissage, sans remplissage dans openssl Utilisation de padding ) le résultat est le même avant et après le remplacement, et il n'y a aucun problème de compatibilité. Vous pouvez choisir différentes solutions de remplacement en fonction des différentes méthodes de remplissage du code, mais il y a trois détails qui doivent être expliqués

Pourquoi y a-t-il un remplissage ?

Pourquoi les noms des algorithmes sont-ils différents après les avoir remplacés par openssl ?
Le prochain chapitre analysera le remplissage et l'algorithme en détail.

Remplissage

La raison pour laquelle il y a un remplissage commence par l'algorithme de cryptage. Parce que dans l'algorithme AES-128-CBC, la chaîne à chiffrer sera segmentée en segments tous les 16 octets de longueur et calculée étape par étape, ce qui entraînera le remplissage de segments de moins de 16 octets. Il existe donc deux types d'exemples donnés : l'un consiste à utiliser le remplissage par défaut et l'autre à utiliser un remplissage indépendant. Lors du remplacement d'openssl, comment choisir le schéma de remplissage nécessite une compréhension du remplissage par défaut et autonome de mcrypt et openssl.

remplissage par défaut de mcrypt

Dans le code source de php, on peut voir que le remplissage par défaut est x00. En fait, il n'est pas complété par x00. le code source On peut constater qu'une chaîne vide de 16 bits est d'abord demandée, donc chaque octet est x00 lors de l'initialisation. En fait, on peut dire qu'il n'y a pas de remplissage, mais c'est x00 La chaîne cryptée obtenue par. l'utilisation du remplissage par défaut sera sous la forme suivante :

mcrypt est complété par défaut avec

donc l'extra x00 doit être supprimé lors du décryptage. Bien sûr, vous pouvez aussi être paresseux et ne pas supprimer x00. Parce que la chaîne "stringx00" et la chaîne "string" en PHP ont les mêmes performances sauf pour la longueur, il ne semble donc y avoir aucune différence. Le code suivant :

 // 尾部包含若干个`\x00` 均可功输出true
 if ("string\x00" == "string") { // 用双引号可解析\x00
 echo true;
 }

.

Exemple après un remplissage x00 : (veuillez faire attention à la longueur de la chaîne, on peut voir que un remplissage avec x00 affectera la longueur)

Remplissage autonome mcrypt

L'algorithme de remplissage doit être effectué selon l'algorithme suivant :

Remplissage ajouté

/**
 * 填充算法
 * @param string $source
 * @return string
 */
 function addPKCS7Padding($source)
 {
 $source = trim($source);
 $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);

 $pad = $block - (strlen($source) % $block);
 if ($pad <= $block) {
  $char = chr($pad);
  $source .= str_repeat($char, $pad);
 }
 return $source;
 }

Après avoir ajouté du rembourrage, la chaîne ressemble en fait à ceci :

Suppression du rembourrage

 /**
 * 移去填充算法
 * @param string $source
 * @return string
 */
 function stripPKSC7Padding($source)
 {
 $source = trim($source);
 $char = substr($source, -1);
 $num = ord($char);
 if ($num == 62) return $source;
 $source = substr($source, 0, -$num);
 return $source;
 }

openssl default padding

La méthode par défaut est cohérente avec la méthode de remplissage autonome du mcrypt standard, donc dans le deuxième exemple, après avoir utilisé le ci-dessus l'algorithme de remplissage, vous pouvez directement utiliser le remplacement openssl_encrypt sans problèmes de compatibilité. La chaîne cryptée complétée se présente sous la forme suivante :

Il convient de noter que le remplissage et la suppression du remplissage sont intégrés dans openssl_encrypt et openssl_decrypt, vous pouvez donc l'utiliser directement à moins que vous devez le faire vous-même. Implémentez le remplissage, sinon il n'est pas nécessaire d'envisager le remplissage

remplissage autonome openssl

openssl_encrypt fournit le paramètre d'option pour prendre en charge l'autonomie. padding, mais après avoir consulté le code source php, openssl L'utilisation correcte a été trouvée grâce au code du scénario de test :

 // if we want to manage our own padding
 $padded_data = $data . str_repeat(&#39; &#39;, 16 - (strlen($data) % 16));
 $encrypted = openssl_encrypt($padded_data, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
 $output = openssl_decrypt($encrypted, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
 var_dump(rtrim($output));
(备注:如上,OPENSSL_ZERO_PADDING 并非是为0填充的意思)

À partir de là, nous pouvons expliquer pourquoi dans le premier exemple, le code pour le point de recharge indépendant x00 a été ajouté avant openssl_encrypt

Depuis le cryptage et le déchiffrement ci-dessus, la logique de remplissage est différente, et les exemples ci-dessus peuvent expliquez-le bien :

Exemple 1 :

mcrypt n'utilise pas de remplissage lors du cryptage, il est donc complété par x00, donc lorsque vous le remplacez par openssl, vous devez implémenter le remplissage x00 indépendamment.

Exemple 2 :

mcrypt utilise un remplissage standard lors du cryptage, et la méthode de remplissage d'openssl est également un remplissage standard, vous pouvez donc l'utiliser directement.

Après avoir analysé cela, nous pouvons constater que quelle que soit la stratégie de remplissage, nous devons faire attention à l'ajout de remplissage pendant le cryptage et à la suppression du remplissage pendant le décryptage. À ce stade, l'analyse liée au remplissage dans l'exemple ci-dessus est terminée. Voyons ensuite comment choisir l'algorithme remplacé.

Sélectionner l'algorithme

Dans l'exemple ci-dessus, il y a un problème avec l'algorithme AES-128-CBC dans mcrypt, dans openssl Comment faire le remplacer par AES_256 ?
Concernant ce point, je n'ai pas trouvé d'explication raisonnable. J'ai vérifié le code source depuis un moment et je n'ai pas trouvé la raison (la capacité est limitée~), mais à travers les informations suivantes, le la fonction est toujours terminée

Openssl déchiffre le problème d'incompatibilité des données mcrypt AES

Convertir mcrypt_generic en openssl_encrypt Poser une question

Si des étudiants trouvent la raison, veuillez partir moi un message, merci.

Résumé

Pour la partie chiffrement utilisant mcrypt AES, s'il y a un problème lors du processus de remplacement, vous pouvez les remplacer ou les remplir deux de l'algorithme Commençons à y réfléchir. Dans le même temps, l'une des conditions à remplir est de choisir selon différentes méthodes de remplissage. La chose la plus importante à considérer lors du remplacement est de s'assurer qu'aucun changement ne se produira après le remplacement. Bien qu'il n'y ait qu'une légère différence - la différence dans les dernières chaînes, il est difficile de la modifier sur plusieurs plates-formes en même temps, mais moins il y a de changements, plus le risque est faible.

Cet article n'explique que brièvement l'algorithme AES. Reste à savoir si d'autres algorithmes sont applicables.

Ce qui précède représente l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'étude de chacun. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois !

Recommandations associées :

Implémentation PHP de l'enregistrement des images Canvas en HTML5 sur le serveur

Interface PHP héritage et tarits multiples Méthodes d'implémentation pour plusieurs effets d'héritage_php compétences

Framework Laravel + Implémentation Blob de l'analyse d'exemple de fonction de téléchargement multi-images

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