下面的代码以及置顶文件使用并修改了作者:jspp@qq.com的开源代码,只作学习使用,侵删
背景:
在接入Taptap的防沉迷实名认证前,需要先通过国家防沉迷实名认证系统的接口测试,要求全部示例通过才能允许使用接口:
核心代码:
接口加密需要使用密钥对请求报文体数据进行AES-128/GCM + BASE64算法加密
java
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
public class AESUtil {
// 这个算法在我这边跑不起来,所以换成了下面的那个方法
// public static String encrypt(String content, String key) {
// try {
// byte[] hexStr = hexToByteArray(key);
// //加密算法:AES/GCM/PKCS5Padding
// // 初始化加密算法
// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// SecretKeySpec skeySpec = new SecretKeySpec(hexStr, "AES");
// //随机生成iv 12位
// byte[] iv = RandomStringUtils.random(12).getBytes();
// //数据加密, AES-GCM-128
// cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new GCMParameterSpec(128, iv));
// byte[] encrypted = cipher.doFinal(content.getBytes()); //数据加密
// //iv+加密数据 拼接 iv在前,加密数据在后
// ByteBuffer byteBuffer = ByteBuffer.allocate(iv.length + encrypted.length);
// byteBuffer.put(iv);
// byteBuffer.put(encrypted);
// byte[] cipherMessage = byteBuffer.array();
// //java.util.Base64
// return java.util.Base64.getEncoder().encodeToString(cipherMessage);
//
// } catch (Exception e) {
// e.printStackTrace();
// throw new RuntimeException(e);
// }
// }
public static String encrypt(String cleartext,String key) {
try
{
byte[] hexStr = hexToByteArray(key);
SecretKeySpec skeySpec = new SecretKeySpec(hexStr, "AES");
// encoding format needs thought
byte[] clearTextbytes = cleartext.getBytes("UTF-8");
final SecureRandom secureKeyRandomness = SecureRandom.getInstanceStrong();
final KeyGenerator AES_keyInstance = KeyGenerator.getInstance("AES");
AES_keyInstance.init(128, secureKeyRandomness);
final Cipher AES_cipherInstance = Cipher.getInstance("AES/GCM/NoPadding");
AES_cipherInstance.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encryptedText = AES_cipherInstance.doFinal(clearTextbytes);
byte[] iv = AES_cipherInstance.getIV();
byte[] message = new byte[12 + clearTextbytes.length + 16];
System.arraycopy(iv, 0, message, 0, 12);
System.arraycopy(encryptedText, 0, message, 12, encryptedText.length);
return java.util.Base64.getEncoder().encodeToString(message);
}
catch (Exception e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static byte[] hexToByteArray(String hex) {
int l = hex.length();
byte[] data = new byte[l / 2];
for (int i = 0; i < l; i += 2)
{
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ Character.digit(hex.charAt(i + 1), 16));
}
return data;
}
}
使用SHA256算法对待加密字符串进行计算
java
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Sha256Utils {
/**
* 利用java原生的类实现SHA256加密
* @param str 加密后的报文
* @return
*/
public static String getSHA256(String str){
MessageDigest messageDigest;
String encodestr = "";
try {
messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(str.getBytes("UTF-8"));
encodestr = byte2Hex(messageDigest.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return encodestr;
}
/**
* 将byte转为16进制
* @param bytes
* @return
*/
private static String byte2Hex(byte[] bytes){
StringBuffer stringBuffer = new StringBuffer();
String temp = null;
for (int i=0;i<bytes.length;i++){
temp = Integer.toHexString(bytes[i] & 0xFF);
if (temp.length()==1){
stringBuffer.append("0");
}
stringBuffer.append(temp);
}
return stringBuffer.toString();
}
}
坑爹的点:
- 接口测试中使用的AppId、密钥等并非Taptap那边的数据,而是网络游戏防沉迷实名认证系统中的相关数据:
- 测试数据要尽可能多地使用《网络游戏防沉迷实名认证系统测试系统说明》中的所有数据,数据集一定要够多,有部分数据是有规律的,可以类推更多的其他数据,加大训练集,比如这些:
- 出现错误码:1005 SYS REQ IP ERROR (接口请求IP地址非法),应该是在网络游戏防沉迷实名认证系统的IP白名单中没有填入公网IP:
- 出现错误码:1007 SYS REQ EXPIRE ERROR (接口请求过期) ,原因是传入的timestamp没有算东八区的时间戳(单位毫秒),在Java中比较简单,直接用System.currentTimeMillis(),但是其他编程语言要记得算上时区
- 出现错误码:1011 SYS REQ PARTNER AUTH ERROR(接口请求方身份核验错误),原因是上面提到的接口加密算法(AES-128/GCM + BASE64加密)或者 SHA256算法加签算法有问题,可以直接参考一下上述Java版的代码
- 出现错误码:1012 SYS REQ PARAM CHECK ERROR (接口请求报文核验失败),看一下自己报文的拼接是否出现了问题,要严格按照文档的格式来拼接,详情可以看我置顶文件,里面有整个maven项目
- 出现错误码:4002 TEST TASK NOT EXIST (测试任务不存在),原因是某一项测试数据已经通过了,这个测试数据就不能再用了,也有可能是你的测试码过期了,更新一下测试码即可