最近做一个电商类的APP,进行后台数据接口的调用。这期间涉及到财务账目的往来,自然很需要重视数据安全的问题。我没有搞过爬虫、抓包之类的技术,但是如果传输过程中的数据被抓,如果被破解了肯定会出问题的。所以我考虑自己做一个加密和解密的算法,在后台将数据打包后进行加密,APP拿到数据又进行解密。
经过测试,基本实现了这个过程。
首先,我要确定一个思路,就是如何进行加密。解密的过程是一个逆运算。我决定先将字符串和密码进行循环的异或运算,因为抑或运算的逆运算就是自己,比较方便,然后拿这个结果进行base64编码。其实这期间还可以根据自己的设定进行一些其他的运算,只要不公开算法,破解起来恐怕也不容易的。至于解码,就是先将拉到的数据进行base64解码,再和相同的密码进行一次循环异或运算就OK了。
思路已敲定,我先开启一个Idea+SpringBoot的项目,写一个加密与解密的工具类CodeUtils.java,其中包含两个方法encode()和decode():
public class CodeUtils {
/**
* 加密
*
* @param source 未加密的字符串
* @param passWord 密码
* @return
*/
public static String encode(String source, String passWord) {
byte[] arr1 = source.getBytes();
byte[] arr2 = passWord.getBytes();
//先进行异或运算
//在此前后进行其他个性化算法
byte[] bytes = xorByteArray(arr1, arr2);
//再进行Base64编码
String encodeStr = new BASE64Encoder().encode(bytes);
return encodeStr;
}
/**
* 解密
*
* @param encodeStr 已经加密过的字符串
* @param passWord 密码
* @return
*/
public static String decode(String encodeStr, String passWord) throws IOException {
byte[] arr2 = passWord.getBytes();
//先进行Base64解码
byte[] arr1 = new BASE64Decoder().decodeBuffer(encodeStr);
//再进行异或运算
byte[] bytes = xorByteArray(arr1, arr2);
//再进行Base64编码
String decodeStr = new String(bytes, "utf-8");
//在此前后进行其他个性化算法
return decodeStr;
}
/**
* 对两个字节数组进行抑或运算
*
* @param arr1 基本数组
* @param arr2 运算数组
* @return
*/
public static byte[] xorByteArray(byte[] arr1, byte[] arr2) {
int len2 = arr2.length;
byte[] arr3 = new byte[arr1.length];
for (int i = 0; i < arr1.length; i++) {
arr3[i] = (byte) (arr1[i] ^ arr2[i % len2]);
}
return arr3;
}
}
加密和解密的思路有两点:一是处理过程相反,二是字节数组是密码字符串字节数组循环与数据字符串字节数组进行异或运算。
接下来在接口方法中调用处理:
@PostMapping("/getuserbyte")
public String getuserbyte() throws UnsupportedEncodingException {
UserModel userModel = new UserModel(1, "Chris Chen", "123456");
String passWord = "kalychen";
String resultStr = new Gson().toJson(new NetResult<UserModel>(0, "getUserByte Success", userModel));
System.out.println("有人调用~~~~~~~~");
return CodeUtils.encode(resultStr, passWord);
}
另外建一个Java项目,通过配置retrofit2来调用接口。具体代码就不贴了。解码的处理要在json解析之前,所以我在;拦截器中进行处理。
public class NetInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
String passWord="kalychen";
Request request = chain.request();
Response response = chain.proceed(request);
ResponseBody responseBody=response.body();
String encodeStr = responseBody.string();
System.out.println("拦截到的返回数据==>"+encodeStr);
String decodeStr= CodeUtils.decode(encodeStr,passWord);
System.out.println("解码后的返回数据==>"+decodeStr);
return response.newBuilder()
.body(responseBody.create(responseBody.contentType(),decodeStr))
.build();
}
}
写一段测试代码:
public class Test {
public static void main(String[] args){
NetCallback callback=new NetCallback() {
@Override
protected void onComplete(NetResponse netResponse) {
}
};
TestApi.getUserByte(callback);
}
}
测试结果是这样的:
"C:\Program Files\Java\jdk1.8.0_92\bin\java" "-javaagent:C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2017.1\lib\idea_rt.jar=55249:C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2017.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_92\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar;F:\WorkSpace\IdeaProjects\GradleJavaProject\build\classes\java\main;D:\Gradle\gradle-4.1\caches\modules-2\files-2.1\com.squareup.retrofit2\converter-gson\2.1.0\aa557d71ead91cbf26e0c316a0f593d168303309\converter-gson-2.1.0.jar;D:\Gradle\gradle-4.1\caches\modules-2\files-2.1\com.squareup.retrofit2\retrofit\2.1.0\2de7cd8b95b7021b1d597f049bcb422055119f2c\retrofit-2.1.0.jar;D:\Gradle\gradle-4.1\caches\modules-2\files-2.1\com.google.code.gson\gson\2.8.0\c4ba5371a29ac9b2ad6129b1d39ea38750043eff\gson-2.8.0.jar;D:\Gradle\gradle-4.1\caches\modules-2\files-2.1\com.squareup.okhttp3\okhttp\3.3.0\2b802460eea20f8f2ad9c08c74e0f14718e88aa9\okhttp-3.3.0.jar;D:\Gradle\gradle-4.1\caches\modules-2\files-2.1\com.squareup.okio\okio\1.8.0\5ea7af56cc7c567ed9856d99efb30740e9b17ff\okio-1.8.0.jar" cn.chrischens.gd.Test
拦截到的返回数据==>EEMPFgcNR1RbTU4UEA9HVEkGCQ02GwAcKRgYHEM7EA0IBB8KQURHCgoVDVtZE0cHD0NWSE9KEB0O
EyIYDg1HVEkiBAsKG0UtAwQCW09KFQ8YEhsWEQxHVElQXkpXXVNMFhw=
解码后的返回数据==>{"code":0,"msg":"getUserByte Success","data":{"id":1,"userName":"Chris Chen","password":"123456"}}
返回的可解析的json===>{"code":0,"msg":"getUserByte Success","data":{"id":1.0,"userName":"Chris Chen","password":"123456"}}//这一句是callback打印的
测试结果符合预期。