Android、IOS、JS实现AES加密

174 阅读2分钟

问题

  1. 要求四端(安卓/IOS/JS/JAVA后端)统一。
  2. 安卓(虽然也是用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();
            }
        });
    }

});