前后端 AES 加解密

593 阅读1分钟

前后端 AES 加解密

1.场景

目前在公司有一个业务需求,会员邀请新会员注册时。前端生成邀请码后进行 AES 加密,后端解密后将邀请码存储到数据库中,是前端加密,后端解密的场景。在 CSDN、掘金等平台尝试了几个例子,又自己修改了下后达成了想要的效果。写这篇文章用以记录存档,欢迎大家讨论交流!

2.类库使用

3.后端代码实现

工具类:

这个 ENCODE_KEY 的长度有指定要求,所以我用 Hutool 的 MD5 加密工具将字符串加密了一层

IV_KEY 偏移量也是 16 位也是有固定长度限制的

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.symmetric.AES;
import java.nio.charset.StandardCharsets;
import java.util.Base64;


public class KeyUtil {
    /**
     * 密钥key
     */
    private static final String ENCODE_KEY = DigestUtil.md5Hex("xxxxxxx");
    /**
     * 偏移量。16 字节
     */
    private static final String IV_KEY = "4382822409223508";


    public static String decryptFromString(String data) {
        AES aes = new AES(Mode.CBC, Padding.ISO10126Padding, Base64.getDecoder().decode(ENCODE_KEY), IV_KEY.getBytes());
        return aes.decryptStr(Base64.getDecoder().decode(data), CharsetUtil.CHARSET_UTF_8);
    }

    public static String encryptFromString(String data) {
        AES aes = new AES(Mode.CBC, Padding.ISO10126Padding, Base64.getDecoder().decode(ENCODE_KEY), IV_KEY.getBytes());
        return aes.encryptBase64(data, StandardCharsets.UTF_8);
    }
}

Junit 测试类:

    @Test
    public void testHutoolDecrypt() {
        String encryptData = KeyUtil.encryptFromString("Hello World");
        System.out.println("加密:" + encryptData);
        String decryptData = KeyUtil.decryptFromString(encryptData);
        System.out.println("解密:" + decryptData);
    }

测试结果:

image

4.前端代码实现(只包含加密部分)

从上面的 GitHub 仓库地址下载了 js 代码后,将 js 本地引用,没有使用 npm 安装的方式使用(太麻烦....)

下方是例子:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
  <script src="js/crypto-js.js"></script>
  <script>
    // 待加密的原文,使用 utf-8 编码处理
    let message = CryptoJS.enc.Utf8.parse("xxx");

    // 密钥,我这里随意填写的,和后端的ENCODE_KEY对应即可
    let key = CryptoJS.enc.Base64.parse("xxx");

    // iv,和后端的IV_KEY对应即可
    let iv = CryptoJS.enc.Utf8.parse("4382822409223508");

    // 加密
    let encrypted = CryptoJS.AES.encrypt(message, key, {
      iv: iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Iso10126,
    });

    // 密文,使用 base64 编码
    let cipherTextBase64 = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);

    // 打印密文
    console.log(cipherTextBase64);
  </script>
</html>

前端加密后的结果在浏览器控制台上进行了打印,可以复制后直接调用 java 代码的解密 function 进行测试,我这里不再进行截图演示。