小工具知识网

当前位置: 首页 > 行业知识 > springboot 数据传输的加密解密方式一: AES(对称加密)

行业知识

springboot 数据传输的加密解密方式一: AES(对称加密)

2026-11-06 01:31:26 来源:互联网转载

全文目录,一步到位

  • 1.加密/解密方式一: `AES`
    • 1.1 AES`加密`简介
    • 1.2 AES`解密`简介
    • 1.3 AES细致介绍(`外链`)
    • 2. AES加密解密使用
      • 2.1 应用场景
        • 2.2 工具包使用方式
        • 2.2.0 (关键)生成一个`秘钥`(16位)
        • 2.2.1 AES加密文本
        • 2.2.2 AES解密文本
        • 2.2.3 AES加密文件(源)
        • 2.2.4 AES解密文件(源)
        • 2.2.5 文件AES加密并输出(终)
        • 2.2.6 文件AES解密并输出(终)
        • 2.2.7 使用(测试)方式一: `文本`
        • 2.2.8 使用(测试)方式二: `文件`
        • 2.3 执行结果
          • 2.3.1 控制台输出
          • 2.3.2 如图所示
          • 2.4 跳过2.2 工具包代码
            • 2.4.1 CryptoUtils密码学工具包
            • 2.4.2 测试代码完整版
            • 2.4.3 秘钥和IV随机 都是16位字符串即可 不可暴露
            • 3. 结合业务使用
              • 3.1 (`模拟`简易数据传输-收集功能)
                • 3.1.1 创建统一返回值(`叫啥都行`)
                • 3.1.2 controller层写一个demo
                • 3.1.3 数据采集注解(标记是否采集和加密)
                • 3.1.4 业务具体实现逻辑数据处理(略)
                • 3.1.5 测试结果(如图所示)
                • 4. 前端使用AES加密(大致流程)
                  • 4.1 前端js实现方式
                  • 5. 文章的总结与预告
                    • 5.1 本文总结
                    • 5.2 下文预告

                      1.加密/解密方式一: AES

                      本篇文章介绍的是 对称加密 AES

                      插一句:

                      非对称加密比对称加密更安全。

                      • 对称加密: 安全性要求一般、且数据量较大的场景

                        对称加密那样在通信之前要先同步秘钥

                      • 非对称性加密: 对于安全性要求高、且数据量不大的场景

                        非对称加密使用一对秘钥,一个用来加密,一个用来解密,而且公钥是公开的,秘钥是自己保存

                        1.1 AES加密简介

                        AES(Advanced Encryption Standard)是一种对称加密算法,也是目前最常用的加密方式之一。它在国际上被广泛使用,并且被应用于保护各种机密信息,如密码、信用卡信息、银行账户信息、电子邮件等。

                        AES加密算法使用的加密密钥和解密密钥都是相同的,并且加密和解密使用的算法方法也是相同的,因此称为对称加密算法。AES算法的密钥长度可以是128位、192位或256位,其中256位的密钥长度提供了最高的安全性,但同时也需要更高的计算能力。一般128位(bit) 即可 16字节

                        AES算法在加密时主要是通过替换、置换和异或等方式进行操作,具体过程包括四个步骤:密钥扩展、初始轮、重复轮和最后的输出。密钥扩展是根据输入的密钥生成相关的轮密钥,用于后续的加密过程中。初始轮是将输入数据进行基本的置换和异或操作。重复轮是将初始轮的结果进行多轮替换、置换和异或操作。最后的输出是将最后的结果输出为密文。

                        总体来说,AES加密算法具有可靠性高、安全性强的特点,被广泛使用于各种安全系统中。

                        1.2 AES解密简介

                        AES(Advanced Encryption Standard)解密操作是将加密过的数据使用相同的加密密钥进行解密操作,还原成原始数据的过程。AES解密算法使用的过程和加密算法相同,只是操作的顺序和方法稍有不同。

                        在AES解密过程中,需要使用相同的密钥才能成功解密数据。因此,需要确保密钥的安全性,防止被泄露。解密过程和加密过程是相反的,首先需要对密文进行逆向操作,还原经过置换和代换操作后的数据,然后进行逆向的轮操作,得到最终的明文。

                        具体的AES解密步骤如下:

                        1. 密钥扩展:使用相同的加密密钥生成相应的轮密钥,用于后续的解密过程中。
                        2. 逆向的输出:首先对密文进行逆向的输出,还原经过置换和代换操作后的数据。
                        3. 逆向的重复轮:对还原的数据进行逆向的重复轮操作,还原初始轮和重复轮操作中的所有代换和置换操作。
                        4. 最终输出:得到最终的明文,即加密前的数据。

                        需要注意的是,解密过程需要使用相同的密钥和相同的加密算法,否则将无法还原原始数据。同时,AES解密算法仅对数据进行加密和解密操作,不包括数据传输和存储的安全性问题。因此,在实际的应用中,还需要其他的安全机制来保障数据的安全。

                        1.3 AES细致介绍(外链)

                        介绍的相当全面(外链)

                        ===> 传送门: aes加密原理及优势与劣势

                        2. AES加密解密使用

                        2.1 应用场景

                        应用于保护各种机密信息,如密码、信用卡信息、银行账户信息、电子邮件等

                        2.2 工具包使用方式

                        javax包下的javax.crypto.Cipher;

                        2.2.0 (关键)生成一个秘钥(16位)

                        这个密钥需要是16位 - 对应128bit

                        原因: 128的密钥长度是目前能对安全性和性能的一种比较理想的折中选择

                        可以放到nacos等配置中心中

                        也可以随机生成(很关键)

                        //示例: public static final String KEY_DES = "pzy0123456789pzy";

                        2.2.1 AES加密文本

                          /**     * AES加密文本     *     * @param content    明文     * @param encryptKey 秘钥,必须为16个字符组成     * @return 密文     */    public static String aesEncryptForFront(String content, String encryptKey) {        if (StringUtils.isEmpty(content) || StringUtils.isEmpty(encryptKey)) {            return null;        }        try {            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));            byte[] encryptStr = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));            return Base64.getEncoder().encodeToString(encryptStr);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }

                        2.2.2 AES解密文本

                            /**     * AES解密文本     *     * @param encryptStr 密文     * @param decryptKey 秘钥,必须为16个字符组成     * @return 明文     */    public static String aesDecryptForFront(String encryptStr, String decryptKey) {        if (StringUtils.isEmpty(encryptStr) || StringUtils.isEmpty(decryptKey)) {            return null;        }        try {            byte[] encryptByte = Base64.getDecoder().decode(encryptStr);            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));            byte[] decryptBytes = cipher.doFinal(encryptByte);            return new String(decryptBytes);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }

                        2.2.3 AES加密文件(源)

                            /**     * AES加密文件     *     * @param bytes      字节     * @param encryptKey 秘钥key     * @return 字节byte     */    public static byte[] aesEncryptForFront(byte[] bytes, String encryptKey) {        if (StringUtils.isEmpty(bytes) || StringUtils.isEmpty(encryptKey)) {            return null;        }        try {            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));            return cipher.doFinal(bytes);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }

                        2.2.4 AES解密文件(源)

                          /**     * AES解密文件     *     * @param bytes      字节     * @param decryptKey 解密key     * @return 解密字节     */    public static byte[] aesDecryptForFront(byte[] bytes, String decryptKey) {        if (StringUtils.isEmpty(bytes) || StringUtils.isEmpty(decryptKey)) {            return null;        }        try {            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));            return cipher.doFinal(bytes);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }

                        2.2.5 文件AES加密并输出(终)

                            /**     * 文件AES加密并输出     *     * @param fileSourcePath 文件原始路径     * @param outEncryptPath 加密数据文件路径     * @throws IOException io异常     */    public static void fileAcsEncrypt(String fileSourcePath, String outEncryptPath) throws IOException {        System.out.println("加密开始!");        File file = new File(fileSourcePath);        // 以 byte 的形式读取,不改变文件数据的编码格式        byte[] bytes = Files.readAllBytes(file.toPath());        byte[] outFile = CryptoUtils.aesEncryptForFront(bytes, CryptoUtils.KEY_DES);        OutputStream out = new BufferedOutputStream(new FileOutputStream(outEncryptPath));        assert outFile != null;        out.write(outFile);        out.flush();    }

                        2.2.6 文件AES解密并输出(终)

                          /**     * 文件AES解密并输出     *     * @param fileEncryptPath 加密后文件路径     * @param outDecryptPath  解密后文件路径     * @throws IOException io异常     */    public static void fileAcsDecrypt(String fileEncryptPath, String outDecryptPath) throws IOException {        File file = new File(fileEncryptPath);        // 以 byte 的形式读取,不改变文件数据的编码格式        byte[] outFile = CryptoUtils.aesDecryptForFront(Files.readAllBytes(file.toPath()), CryptoUtils.KEY_DES);        OutputStream out = new BufferedOutputStream(new FileOutputStream(outDecryptPath));        assert outFile != null;        out.write(outFile);        out.flush();        System.out.println("解密结束!");    }

                        2.2.7 使用(测试)方式一: 文本

                        main方法进行测试

                         public static void main(String[] args) throws Exception {        String old = "12345678";        String target = "mbn/Mykb4f7xt2Zhz0xS6w=="; // 加密后的字符串        //加密        System.out.println(CryptoUtils.aesEncryptForFront(old, CryptoUtils.KEY_DES));        //解密        System.out.println(CryptoUtils.aesDecryptForFront(target, CryptoUtils.KEY_DES));    }

                        2.2.8 使用(测试)方式二: 文件

                        举例中: pzy.txt文件需要有内容, 名称随意 后缀随意

                        //加密/解密(生成加密后的文件后缀可以自定义)CryptoUtils.fileAcsEncrypt("D:\pzy.txt", "D:\pzy1.txt");CryptoUtils.fileAcsDecrypt("D:\pzy1.txt", "D:\pzy2.txt");

                        2.3 执行结果

                        2.3.1 控制台输出

                        mbn/Mykb4f7xt2Zhz0xS6w==

                        12345678

                        加密开始!

                        解密结束!

                        2.3.2 如图所示

                        文件生成 beta版

                        文件内容解释

                        • 第一个是原文件
                        • 第二个是加密byte后文件 不重要
                        • 第三个是解密后文件

                          2.4 跳过2.2 工具包代码

                          2.2详细解释 2.4 完整版

                          后续版本中同时对上面介绍的部分代码进行调整如下:

                          • 加密模式EBC-> CBC 进行调整
                            1. EBC: 一种简单的加密模式,每个明文块独立加密,不需要前后的文块信息, 并且不需要IV
                            2. CBC: 更安全的加密模式,它使用前一个密文块的一部分(通常是最后8个字节)作为下一个明文块的加密密钥, 需要IV
                            • 增加了初始化向量(IV)
                            • 使用方式没有变化, 与上面解释完全相同

                              2.4.1 CryptoUtils密码学工具包

                              /** * AES 加密/解密工具类 beta版 * 

                              * 版本更新 * 1. 新增json串加密解密 * 2. 新增文件加密与解密 * 3. 增加测试用例 * * @author pzy * @version v2.0.1 * @description OK */public class CryptoUtils { //这个密钥需要是16位 //对应128bit 原因: 128的密钥长度是目前能对安全性和性能的一种比较理想的折中选择 public static final String KEY_DES = "pzyPzyPzyPzyPzyP"; // 偏移量 16位 private static final String iv = "0102030405060708"; // private static final String algorithmStr = "AES/EBC/PKCS5Padding"; private static final String algorithmStr = "AES/CBC/PKCS5Padding"; private static final byte[] ivByte = iv.getBytes(StandardCharsets.UTF_8); /** * AES加密文本 * * @param content 明文 * @param encryptKey 秘钥,必须为16个字符组成 * @return 密文 */ public static String aesEncryptForFront(String content, String encryptKey) { if (StringUtils.isEmpty(content) || StringUtils.isEmpty(encryptKey)) { return null; } try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE"); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"), new IvParameterSpec(ivByte)); byte[] encryptStr = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encryptStr); } catch (Exception e) { e.printStackTrace(); return null; } } /** * AES解密文本 * * @param encryptStr 密文 * @param decryptKey 秘钥,必须为16个字符组成 * @return 明文 */ public static String aesDecryptForFront(String encryptStr, String decryptKey) { if (StringUtils.isEmpty(encryptStr) || StringUtils.isEmpty(decryptKey)) { return null; } try { byte[] encryptByte = Base64.getDecoder().decode(encryptStr); Cipher cipher = Cipher.getInstance(algorithmStr); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"), new IvParameterSpec(ivByte)); byte[] decryptBytes = cipher.doFinal(encryptByte); return new String(decryptBytes); } catch (Exception e) { e.printStackTrace(); return null; } } /** * AES加密文件 * * @param bytes 字节 * @param encryptKey 秘钥key * @return 字节byte */ public static byte[] aesEncryptForFront(byte[] bytes, String encryptKey) { if (StringUtils.isEmpty(bytes) || StringUtils.isEmpty(encryptKey)) { return null; } try { Cipher cipher = Cipher.getInstance(algorithmStr); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"), new IvParameterSpec(ivByte)); return cipher.doFinal(bytes); } catch (Exception e) { e.printStackTrace(); return null; } } /** * AES解密文件 * * @param bytes 字节 * @param decryptKey 解密key * @return 解密字节 */ public static byte[] aesDecryptForFront(byte[] bytes, String decryptKey) { if (StringUtils.isEmpty(bytes) || StringUtils.isEmpty(decryptKey)) { return null; } try { Cipher cipher = Cipher.getInstance(algorithmStr); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"), new IvParameterSpec(ivByte)); return cipher.doFinal(bytes); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 文件AES加密并输出 * * @param fileSourcePath 文件原始路径 * @param outEncryptPath 加密数据文件路径 * @throws IOException io异常 */ public static void fileAcsEncrypt(String fileSourcePath, String outEncryptPath) throws IOException { System.out.println("加密开始!"); File file = new File(fileSourcePath); // 以 byte 的形式读取,不改变文件数据的编码格式 byte[] bytes = Files.readAllBytes(file.toPath()); byte[] outFile = CryptoUtils.aesEncryptForFront(bytes, CryptoUtils.KEY_DES); OutputStream out = new BufferedOutputStream(new FileOutputStream(outEncryptPath)); assert outFile != null; out.write(outFile); out.flush(); } /** * 文件AES解密并输出 * * @param fileEncryptPath 加密后文件路径 * @param outDecryptPath 解密后文件路径 * @throws IOException io异常 */ public static void fileAcsDecrypt(String fileEncryptPath, String outDecryptPath) throws IOException { File file = new File(fileEncryptPath); // 以 byte 的形式读取,不改变文件数据的编码格式 byte[] outFile = CryptoUtils.aesDecryptForFront(Files.readAllBytes(file.toPath()), CryptoUtils.KEY_DES); OutputStream out = new BufferedOutputStream(new FileOutputStream(outDecryptPath)); assert outFile != null; out.write(outFile); out.flush(); System.out.println("解密结束!"); }}

                              2.4.2 测试代码完整版

                                  /**     * 提供测试方式     *     * @param args ...     * @throws Exception 异常     */    public static void main(String[] args) throws Exception {        String old = "pzy: 今天天气挺好";        String target = "c882579N5IQtAGKJcgYWGhvIbNTMZb6dGugSBl3IGzU="; // 加密后的字符串//文本------------------>        //加密        System.out.println(CryptoUtils.aesEncryptForFront(old, CryptoUtils.KEY_DES));        //解密        System.out.println(CryptoUtils.aesDecryptForFront(target, CryptoUtils.KEY_DES));//文件 beta版------------------------>        //加密/解密(生成加密后的文件后缀可以自定义)        CryptoUtils.fileAcsEncrypt("D:\pzy.txt", "D:\pzy1.txt");        CryptoUtils.fileAcsDecrypt("D:\pzy1.txt", "D:\pzy2.txt");    }

                              2.4.3 秘钥和IV随机 都是16位字符串即可 不可暴露

                              3. 结合业务使用

                              java 业务中需要数据加密的地方

                              1. 数据安全:在处理敏感数据如: 个人信息、财务信息、或公司核心机密,这些数据在存储和传输过程中都必须保证是安全的。可以使用Java提供的加密和解密库来加密这些数据,以防止数据泄露。
                              2. 网络安全:在构建网络应用时,如Web服务、或者在两个系统之间进行数据传输时,你需要保护数据的完整性。这时,你可以使用加密技术来确保数据在传输过程中不会被篡改。
                              3. 保护密码和令牌:敏感密码或令牌如: 数据库密码、API的密钥等。防止被恶意用户获取, 就得使用加密技术来存储这些密码,并在需要的时候解密。
                              4. 云存储和数据保护:在云存储服务中,如Amazon S3, Google Cloud Storage等,你可以使用加密技术来保护你的数据。这样即使数据被泄露,也需要有正确的密钥才能解密。
                              5. 数据库保护:数据库中存储敏感数据时需要使用加密技术来保护数据。数据库被泄露,关键信息也需要正确的密钥才能解密。
                              6. 物联网:物联网设备中,通常会使用加密技术来保护数据的传输和存储。例如,智能家居设备传输和接收指令时, 设备的数据都会通过加密的连接发送,以确保数据的安全。

                              3.1 (模拟简易数据传输-收集功能)

                              后端返回值加密 然后获取到这个值解密

                              [异步处理, 解耦]

                              1. 服务(1-n)取出数据进行处理(关键核心数据)
                              2. 加密后交给mq(其他)去处理[省略,mq具体操作请看mq系列文章]
                              3. (数据处理类)服务 接收到mq(其他)消息进行解密处理

                              3.1.1 创建统一返回值(叫啥都行)

                              ResultResponse 这个类名随意, AaaResponse都行

                              注意: 加密前需要将Object对象转换成json 然后再加密解密

                              JSON.toJSONString(data)

                              累加一下 加几个方法

                              /** * 获取数据分析data(主)解密 * 

                              * 1. 修复返回 空字符串 null 的情况(主) * 2. 解密数据分析字符串 */public String getAnalyseData() throws JsonProcessingException {Object data = get("analyseData");//解密专用return data == null ? null : CryptoUtils.aesDecryptForFront(String.valueOf(data), CryptoUtils.KEY_DES);//return data == null ? null : new ObjectMapper().writeValueAsString(CryptoUtils.aesDecryptForFront(String.valueOf(data), CryptoUtils.KEY_DES));}/** * 获取数据分析数据 * * @param typeReference * @param * @return */public T getAnalyseData(TypeReference typeReference) {Object data = get("analyseData");//解密操作String cryptoDecodeStr = CryptoUtils.aesDecryptForFront(String.valueOf(data), CryptoUtils.KEY_DES);//String jsonStr = JSON.toJSONString(cryptoDecodeStr);return JSON.parseObject(cryptoDecodeStr, typeReference);}/** * 数据分析专用(主) 加密 *

                              * 数据完全不暴露给前端 * @param data * @return */public ResultResponse setAnalyseData(Object data) {if (data != null) {//加密(密钥)data = CryptoUtils.aesEncryptForFront(JSON.toJSONString(data), CryptoUtils.KEY_DES);}put("analyseData", data);return this;}//---------------------------------------->

                              3.1.2 controller层写一个demo

                                  @Analyse(analyseBaseType = 1,value = "测试")    @ApiOperation(value = "测试1")    @PostMapping("/addTest01")    public ResultResponse addTest01(@RequestBody User user) {        log.info("===> 测试1 

上一篇:挂载多个服务器怎么删除?

下一篇:服务器怎么共享流量给电脑?