需求背景:在做游戏防沉迷操作中,需要先做前置的接口验证过程,在文档中示例中,给出的是java代码
/**
* <p>@title aesGcmEncrypt</p>
* <p>@description Aes-Gcm加密</p>
*
* @param content 待加密文本
* @param key 密钥
* @return java.lang.String
*/
private static String aesGcmEncrypt(String content, byte[] key) {
try {
// 根据指定算法ALGORITHM自成密码器
Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding");
SecretKeySpec skey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, skey);
//获取向量
byte[] ivb = cipher.getIV();
byte[] encodedByteArray = cipher.doFinal(content.getBytes(UTF_8));
byte[] message = new byte[ivb.length + encodedByteArray.length];
System.arraycopy(ivb, 0, message, 0, ivb.length);
System.arraycopy(encodedByteArray, 0, message, ivb.length, encodedByteArray.length);
return Base64.getEncoder().encodeToString(message);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
| BadPaddingException e) {
//建议自行调整为日志输出或抛出异常
return null;
}
}
/**
* <p>@title aesGcmDecrypt</p>
* <p>@description Aes-Gcm解密</p>
*
* @param content 带解密文本
* @param key 密钥
* @return java.lang.String
*/
private static String aesGcmDecrypt(String content, byte[] key) {
try {
// 根据指定算法ALGORITHM自成密码器
Cipher decryptCipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec skey = new SecretKeySpec(key, "AES");
byte[] encodedArrayWithIv = Base64.getDecoder().decode(content);
GCMParameterSpec decryptSpec = new GCMParameterSpec(128, encodedArrayWithIv, 0, 12);
decryptCipher.init(Cipher.DECRYPT_MODE, skey, decryptSpec);
byte[] b = decryptCipher.doFinal(encodedArrayWithIv, 12, encodedArrayWithIv.length - 12);
return new String(b, UTF_8);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
| BadPaddingException | InvalidAlgorithmParameterException e) {
//建议自行调整为日志输出或抛出异常
return null;
}
}
本人不是很懂java所以这个代码也是看的云里雾里的,然后我就用PHP的 openssl_encrypt()方法做了相同的加密方式(本方法支持PHP7.1+)
如下
private function aesGcm($data)
{
$key = self::SECRETKEY;
$cipher = "aes-128-gcm";
$ivlen = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$encrypt = openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA,$iv,$tag);
return base64_encode(($iv.$encrypt.$tag));
}
然后测试网站一直提示测试无法通过。
通过一系列操作终于发现 需要将$key转成ASC||。
最后的代码PHP代码段:
private function aesGcm($data)
{
$key = self::SECRETKEY;
$key = hex2bin($key);
$cipher = "aes-128-gcm";
$ivlen = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$encrypt = openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA,$iv,$tag);
return base64_encode(($iv.$encrypt.$tag));
}
PHP7.1以下的请参考 :https://github.com/Spomky-Labs/php-aes-gcm
public function aesGcmEncrypt($string)
{
$cipher = strtolower('AES-128-GCM');
if(is_array($string)) $string = json_encode($string);
//二进制key
$skey = hex2bin($this->secretKey);
//二进制iv
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));
require APPPATH . 'vendor/autoload.php';
list($content, $tag) = AESGCM::encrypt($skey, $iv, $string);
//如果环境是php7.1+,直接使用下面的方式
// $tag = NULL;
// $content = openssl_encrypt($string, $cipher, $skey,OPENSSL_RAW_DATA,$iv,$tag);
$str = bin2hex($iv) . bin2hex($content) . bin2hex($tag);
return base64_encode(hex2bin($str));
}
如有不懂 请加QQ群一起讨论 :789235512