飞道的博客

PHP aes-128-gcm加密方式

980人阅读  评论(0)

需求背景:在做游戏防沉迷操作中,需要先做前置的接口验证过程,在文档中示例中,给出的是java代码


  
  1. /**
  2. * <p>@title aesGcmEncrypt</p>
  3. * <p>@description Aes-Gcm加密</p>
  4. *
  5. * @param content 待加密文本
  6. * @param key 密钥
  7. * @return java.lang.String
  8. */
  9. private static String aesGcmEncrypt(String content, byte[] key) {
  10. try {
  11. // 根据指定算法ALGORITHM自成密码器
  12. Cipher cipher = Cipher.getInstance( "AES/GCM/PKCS5Padding");
  13. SecretKeySpec skey = new SecretKeySpec(key, "AES");
  14. cipher.init(Cipher.ENCRYPT_MODE, skey);
  15. //获取向量
  16. byte[] ivb = cipher.getIV();
  17. byte[] encodedByteArray = cipher.doFinal(content.getBytes(UTF_8));
  18. byte[] message = new byte[ivb.length + encodedByteArray.length];
  19. System.arraycopy(ivb, 0, message, 0, ivb.length);
  20. System.arraycopy(encodedByteArray, 0, message, ivb.length, encodedByteArray.length);
  21. return Base64.getEncoder().encodeToString(message);
  22. } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
  23. | BadPaddingException e) {
  24. //建议自行调整为日志输出或抛出异常
  25. return null;
  26. }
  27. }
  28. /**
  29. * <p>@title aesGcmDecrypt</p>
  30. * <p>@description Aes-Gcm解密</p>
  31. *
  32. * @param content 带解密文本
  33. * @param key 密钥
  34. * @return java.lang.String
  35. */
  36. private static String aesGcmDecrypt(String content, byte[] key) {
  37. try {
  38. // 根据指定算法ALGORITHM自成密码器
  39. Cipher decryptCipher = Cipher.getInstance( "AES/GCM/NoPadding");
  40. SecretKeySpec skey = new SecretKeySpec(key, "AES");
  41. byte[] encodedArrayWithIv = Base64.getDecoder().decode(content);
  42. GCMParameterSpec decryptSpec = new GCMParameterSpec( 128, encodedArrayWithIv, 0, 12);
  43. decryptCipher.init(Cipher.DECRYPT_MODE, skey, decryptSpec);
  44. byte[] b = decryptCipher.doFinal(encodedArrayWithIv, 12, encodedArrayWithIv.length - 12);
  45. return new String(b, UTF_8);
  46. } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
  47. | BadPaddingException | InvalidAlgorithmParameterException e) {
  48. //建议自行调整为日志输出或抛出异常
  49. return null;
  50. }
  51. }

 

本人不是很懂java所以这个代码也是看的云里雾里的,然后我就用PHP的 openssl_encrypt()方法做了相同的加密方式(本方法支持PHP7.1+)

如下


  
  1. private function aesGcm($data)
  2. {
  3. $key = self::SECRETKEY;
  4. $cipher = "aes-128-gcm";
  5. $ivlen = openssl_cipher_iv_length($cipher);
  6. $iv = openssl_random_pseudo_bytes($ivlen);
  7. $encrypt = openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA,$iv,$tag);
  8. return base64_encode(($iv.$encrypt.$tag));
  9. }

然后测试网站一直提示测试无法通过。

通过一系列操作终于发现 需要将$key转成ASC||。

最后的代码PHP代码段:


  
  1. private function aesGcm($data)
  2. {
  3. $key = self::SECRETKEY;
  4. $key = hex2bin($key);
  5. $cipher = "aes-128-gcm";
  6. $ivlen = openssl_cipher_iv_length($cipher);
  7. $iv = openssl_random_pseudo_bytes($ivlen);
  8. $encrypt = openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA,$iv,$tag);
  9. return base64_encode(($iv.$encrypt.$tag));
  10. }

 

PHP7.1以下的请参考 :https://github.com/Spomky-Labs/php-aes-gcm


  
  1. public function aesGcmEncrypt($string)
  2. {
  3. $cipher = strtolower( 'AES-128-GCM');
  4. if(is_array($string)) $string = json_encode($string);
  5. //二进制key
  6. $skey = hex2bin( $this->secretKey);
  7. //二进制iv
  8. $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));
  9. require APPPATH . 'vendor/autoload.php';
  10. list($content, $tag) = AESGCM::encrypt($skey, $iv, $string);
  11. //如果环境是php7.1+,直接使用下面的方式
  12. // $tag = NULL;
  13. // $content = openssl_encrypt($string, $cipher, $skey,OPENSSL_RAW_DATA,$iv,$tag);
  14. $str = bin2hex($iv) . bin2hex($content) . bin2hex($tag);
  15. return base64_encode(hex2bin($str));
  16. }

如有不懂 请加QQ群一起讨论 :789235512


转载:https://blog.csdn.net/qq_39370482/article/details/113727328
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场