问题
- 要求四端(安卓/IOS/JS/JAVA后端)统一。
- 安卓(虽然也是用JAVA写的),但是和后端JAVA加密的结果却不一样,主要是因为加密算法可能
方案
- 全部采用服务端JAVA(或其他语言)生成
- 客户端和H5采用JS加解密,然后保持JS和JAVA加解密对等-本文采用的方案
- 各端原生代码分别做加解密,有算法爱好者可以试试
2.1 JS代码
加密:
const key = CryptoJS.enc.Utf8.parse('!QAZxsw2#EDCvfr4');
//因为默认是AES128,是16字节的 iv就必须是16位
const iv = CryptoJS.enc.Utf8.parse('1234123412341234');
const mode = CryptoJS.mode.CBC;
const padding = CryptoJS.pad.Pkcs7;
//需要加密的数据
const message = "abc";
const encrypted = CryptoJS.AES.encrypt(message, key, {
iv,
mode,
padding
});
//输出Base64
const base64Encrypted = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
console.log('Base64 Encrypted:', base64Encrypted);
解密:
// AES解密
const decrypted = CryptoJS.AES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(base64Encrypted)
}, key, {
iv,
mode,
padding
});
// 输出字符串
const decryptedMessage = decrypted.toString(CryptoJS.enc.Utf8);
console.log('Decrypted Message:', decryptedMessage);
2.2 IOS,Objective-c代码
将JS库存在IOS项目中,aes.js
// 创建JavaScriptContext
JSContext *context = [[JSContext alloc] init];
// 设置JavaScript文件的URL:上一步的aes.js
NSURL *jsFileURL = [[NSBundle mainBundle] URLForResource:@"aes" withExtension:@"js"];
// 使用URL加载JavaScript文件
NSError *error;
BOOL success = [context evaluateScriptAtURL:jsFileURL sourceURL:jsFileURL completionHandler:nil];
if (!success) {
NSLog(@"Failed to load JavaScript file: %@", error);
return;
}
// 定义JavaScript方法
JSValue *encryptFunction = [context evaluateScript:@"function encryptAES(key, iv, plainText) { return CryptoJS.AES.encrypt(plainText, key, {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}); }"];
JSValue *decryptFunction = [context evaluateScript:@"function decryptAES(key, iv, encryptedText) { return CryptoJS.AES.decrypt(encryptedText, key, {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}).toString(CryptoJS.enc.Utf8); }"];
// 调用加密方法
JSValue *encryptedText = [encryptFunction callWithArguments:@[key, iv, plainText]];
NSData *encryptedData = [NSData dataWithBase64EncodedString:encryptedText.toString() options:0];
// 调用解密方法
JSValue *decryptedText = [decryptFunction callWithArguments:@[key, iv, encryptedData]];
NSString *decryptedPlainText = [decryptedText toString];
// 输出结果
NSLog(@"Encrypted Data: %@", encryptedData.base64EncodedStringWithOptions:0);
NSLog(@"Decrypted Plain Text: %@", decryptedPlainText);
2.3 Android,JAVA代码
将js写在一个html文件中crypto.html
<script src="./crypto.js"></script>
<script>
// AES加密
function encryptedByJS(message, key,iv){
const c= CryptoJS.AES.encrypt(message, CryptoJS.enc.Utf8.parse(key), {
iv: CryptoJS.enc.Utf8.parse(iv),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return CryptoJS.enc.Base64.stringify(c.ciphertext);
}
// AES解密
function decryptedByJS(message, key,iv){
const d = CryptoJS.AES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(message)
},CryptoJS.enc.Utf8.parse(key),{
iv: CryptoJS.enc.Utf8.parse(iv),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return d.toString(CryptoJS.enc.Utf8);
}
</script>
安卓原生代码(注意要起新线程)
jsWebView.getSettings().setJavaScriptEnabled(true);
jsWebView.getSettings().setAllowFileAccessFromFileURLs(true);
jsWebView.loadUrl("file:///android_asset/crypto.html");
jsWebView.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view,String url){
super.onPageFinished(view,url);
String scriptText = "decryptedByJS('"+aSOPQWKD+"','"+aKKWE+"','"+KIV+"');";
jsWebView.evaluateJavascript(scriptText, new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
str = s;
}
});
String scriptText2 = "decryptedByJS('"+bSOPQWKD+"','"+bKKWE+"','"+KIV+"');";
jsWebView.evaluateJavascript(scriptText2, new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
trueBWD = s;
startAutoTicket();
}
});
}
});