Maison >développement back-end >tutoriel php >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-04 14:10:382223parcourir

Cet article présente principalement l'introduction de l'utilisation d'openssl pour remplacer mcrypt dans PHP7.1. Il a une certaine valeur de référence. Maintenant, je le partage avec vous. Les amis dans le besoin peuvent s'y référer

<.>Utilisez openssl pour remplacer mcrypt dans PHP7.1

Dans le développement PHP, l'utilisation des fonctions liées à mcrypt peut facilement effectuer des opérations de cryptage et de décryptage AES, mais l'extension mcrypt est abandonnée dans PHP7.1, vous devez donc en trouver une autre sorte de réalisation. 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 en

padding Différent (Rembourrage 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 :

  1. mcrypt n'utilise pas de remplissage

  • le cryptage mcrypt :

      $key = &#39;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#39;; 
      $iv = &#39;aaaaaaaaaaaaaaaa&#39;;
      $data = &#39;dataString&#39;;
    
      $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);
  • Code de cryptage Openssl avec la même fonction :

      $key = &#39;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#39;; 
      $iv = &#39;aaaaaaaaaaaaaaaa&#39;;
      $data = &#39;dataString&#39;;
    
      $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

    • Cryptage mcrypt :

        $key = &#39;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#39;; 
        $iv = &#39;aaaaaaaaaaaaaaaa&#39;;
        $data = &#39;dataString&#39;;
      
        // 填充(移除填充反着移除即可)
        $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);
    • 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, &#39;AES-256-CBC&#39;, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
    Les exemples ci-dessus peuvent être s'exécute avec succès, parmi lesquels le premier exemple (sans remplissage, mais avec remplissage dans openssl) et le deuxième exemple (avec remplissage, sans remplissage dans openssl) ont la même sortie 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

    1. Pourquoi y a-t-il un remplissage ?

    2. Pourquoi les noms des algorithmes sont-ils différents après les avoir remplacés par openssl ?

    Ce qui suit sera une analyse détaillée du

    remplissage et de l'algorithme.

    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.

    • rembourrage par défaut mcrypt

      Dans le code source de php, on peut voir que le remplissage par défaut est avec

      En fait, il n'est pas complété avec. x00 , on peut trouver à partir du code source 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. il s'agit à l'origine de x00. Utilisez la valeur par défaut. La chaîne cryptée complétée sera sous la forme suivante : x00
      Introduction à lutilisation dopenssl pour remplacer mcrypt dans PHP7.1

      , le

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

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

      Après remplissage. Exemple de : (Veuillez faire attention à la longueur de la chaîne, on peut voir que le remplissage avec x00 affectera la longueur) L'algorithme de remplissage doit être effectué comme suit : x00
      Introduction à l'utilisation d'openssl pour remplacer mcrypt dans PHP7.1

    • Ajouter un remplissage
    • Après avoir ajouté un remplissage, la chaîne a en fait la forme suivante :

      • Supprimer le remplissage

          /**
           * 填充算法
           * @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;
          }


        Introduction à lutilisation dopenssl pour remplacer mcrypt dans PHP7.1

        remplissage par défaut d'openssl
      • La méthode par défaut est la même que celle du mcrypt standard. La méthode de remplissage autonome est la même, donc dans le deuxième exemple, après avoir utilisé le au-dessus de l'algorithme de remplissage, il peut être directement remplacé par openssl_encrypt sans causer de problèmes de compatibilité. La chaîne cryptée rembourrée se présente sous la forme suivante :

          /**
           * 移去填充算法
           * @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;
          }
    • Il est à noter que le remplissage et la suppression du remplissage sont intégrés dans

      et

      , donc directement, utilisez-le simplement. À moins que vous n'ayez besoin d'implémenter le remplissage indépendamment, il n'est pas nécessaire d'envisager le remplissage

      Introduction à lutilisation dopenssl pour remplacer mcrypt dans PHP7.1

      remplissage indépendant openssl

      openssl_encrypt提供了option参数以支持自主填充,但在查阅php源码中openssl的测试用例代码才找到正确用法:

         // 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填充的意思)
      由此,我们就可以解释,在第一个示例中openssl_encrypt之前加入了自主点充\x00的代码原因了

    从以上的加、解密针对填充逻辑不同,针对上文中的示例可以很好地解释:

    • 示例1:
      mcrypt加密时未使用填充,故以\x00进行了填充,所以在替换成openssl,需要自主实现\x00填充。

    • 示例2:
      mcrypt加密时使用了标准的填充,同时openssl的填充方式也为Introduction à lutilisation dopenssl pour remplacer mcrypt dans PHP7.1,故直接使用即可。

    分析到这,可以发现,无论是何种填充策略都需注意在加密时加入填充,在解密时则必须要移除填充。至此,上文中示例中的填充相关则分析完成了,接下来我们再看看如何选择替换后的算法。

    选择算法

    在以上的示例中,有一个问题在于,mcrypt中的AES-128-CBC算法,在openssl中怎么替换成了AES_256?
    关于这一点, 我也未找到合理的解释,查看源码一时半会也没找到原因(能力有限~),但通过以下资料,还是完成了功能

    • openssl 解密 mcrypt AES 数据不兼容问题

    • Convert mcrypt_generic to openssl_encrypt Ask Question

    若是有同学找到原因,欢迎给我留言,谢谢。

    总结

    对于使用mcrypt AES 进行加密密的部分,若是在替换过程中问题, 可以从算法替换或填充这两方面着手考虑下。同时还是一必须满足的条件是根据不同的填充方式选择, 替换最重要的就要考虑兼容问题,保证替换后不发生任何改变。 虽然只是只是有细微的差别----尾部几个字符串的不同,但若是在多平台中同时进行修改也是一件麻烦事,但变动越少风险越小。

    本文只是针对AES算法进行了简单说明,对于其他算法是否适用还有待研究。

    以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

    相关推荐:

    PHP Excel导入数据到MySQL数据库的方法

    wordpress添加文章固定字段的介绍

    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