需求背景:游戏防沉迷操作中,需要先做socket后验证流程。 文档中的例子中给出了java代码。
/**
* @title aesGcmEncrypt
* @description Aes-Gcm加密
*
* @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;
}
}
/**
* @title aesGcmDecrypt
* @description Aes-Gcm解密
*
* @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));
}
随后测试网站依然提示测试失败。
经过一系列操作php加密方式php加密方式,终于发现$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及以下版本请参考:
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
发表评论