前后端 AES 加解密

本贴最后更新于 229 天前,其中的信息可能已经事过景迁

前后端 AES 加解密

1.场景

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

2.类库使用

3.后端代码实现

工具类:

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

IV_KEY 偏移量是 16 位,同样有固定长度要求。

本文更新:实际场景中如果使用 get 方式传递密文,有可能出现 + 号特殊字符被转义的情况。于是更新了写法。

import cn.hutool.core.codec.Base64;
import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.net.URLEncodeUtil;
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;

public class KeyUtil {

    /**
     * 密钥key
     */
    private static final String ENCODE_KEY = DigestUtil.md5Hex("xx");

    /**
     * 偏移量。16 字节
     */
    private static final String IV_KEY = "4382822409223508";

    /**
     * 将加密字符串进行解密
     *
     * @param data 加密字符串
     * @return 解密后的结果
     */
    public static String decryptFromString(String data) {
        //先进行URL解码,避免特殊符号带来的问题
        data = URLDecoder.decode(data, CharsetUtil.CHARSET_UTF_8);
        AES aes = new AES(Mode.CBC, Padding.ISO10126Padding, Base64.decode(ENCODE_KEY), IV_KEY.getBytes());
        return aes.decryptStr(Base64.decode(data));
    }

    /**
     * 将字符串进行加密
     *
     * @param data 未加密的字符串
     * @return 加密后的密文结果
     */
    public static String encryptFromString(String data) {
        AES aes = new AES(Mode.CBC, Padding.ISO10126Padding, Base64.decode(ENCODE_KEY), IV_KEY.getBytes());
        //将Base64加密后的结果,进行URL编码,避免GET方式传输的问题
        return URLEncodeUtil.encode(Base64.encodeUrlSafe(aes.encrypt(data)));
    }

}

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("加密原文");

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

    // 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 编码后使用URL函数再转一遍,避免GET方式调用的问题
    let cipherTextBase64 = encodeURIComponent(
      CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
    );
    // 打印密文
    console.log(cipherTextBase64);
  </script>
</html>

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

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    710 引用 • 1173 回帖 • 171 关注
  • 加密
    15 引用 • 32 回帖
2 操作
chirsgod 在 2023-09-08 16:41:55 更新了该帖
chirsgod 在 2023-09-08 16:40:39 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...