AES加密中的CBC和ECB

目录

1.说明

2.ECB模式(base64)

3.CBC模式

4.总结


1.说明

AES是常见的对称加密算法,加密和解密使用相同的密钥,流程如下:

主要概念如下:

①明文

②密钥

用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过加密算法(如非对称加密或者md5加密等)加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取机密数据。

③加密函数

将明文,密钥及IV变量作为参数,生成加密后的密文,有的加密模式没有IV变量

④解密函数

将密文,密钥及IV变量作为参数,生成解密后的明文,有的加密模式没有IV变量

⑤密文

2.加密模式的组成

①密钥长度

分为AES128,AES192,AES256。

AES128:要求密钥长度为16个字节,分为四行四列的矩阵。

AES192:要求密钥长度为24个字节,分为四行六列的矩阵。

AES256:要求密钥长度为32个字节,分为四行八列的矩阵。

②加密模式

ECB,CBC,CFB,OFB,CTR,CCM,GCM,XTS

③填充模式

 AES加密是以16个字节为一组进行分组加密,要求明文的长度一定是16个字节的整数倍,如果不够16个字节的倍数,需要按照填充模式进行填充。填充模式如下:

NONE:不填充,要求明文长度必须是16个字节的整数倍。

PKCS7:缺多少就补充多少个字节数量。

ZERO:缺多少就补充多少个字节的0。

ANSI923:最后一个字节填充缺少的数量,其他字节填充0。

ISO7816_4:填充的第一个字节为16进制的0x80,其他字节填充0。

ISO10126:最后一个字节填充缺少的数量,其他字节填充随机数。

注意:当明文长度已经是16个字节的整数倍时,当填充模式为NONE以外的模式时,也会进行填充,填充16个16。

2.ECB模式(base64)

加密执行流程:

(1)前端加密及解密

①引入依赖

npm install crypto-js 

②加密及解密的工具类

import CryptoJS from 'crypto-js'

// ECB模式
export function Encrypt(word,key) {
	let srcs = CryptoJS.enc.Utf8.parse(word);
  let keyInfo = CryptoJS.enc.Utf8.parse(key);
	let encrypted = CryptoJS.AES.encrypt(srcs, keyInfo, {
		mode: CryptoJS.mode.ECB,
		padding: CryptoJS.pad.Pkcs7
	})
//返回base64格式的加密结果
	return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
}

export function Decrypt(word,key) {
  let keyInfo = CryptoJS.enc.Utf8.parse(key);
	let base64 = CryptoJS.enc.Base64.parse(word);
	let srcs = CryptoJS.enc.Base64.stringify(base64);
	const decrypt = CryptoJS.AES.decrypt(srcs, keyInfo, {
		mode: CryptoJS.mode.ECB,
		padding: CryptoJS.pad.Pkcs7
	});
	const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
	return decryptedStr;
}

密钥长度必须是16个字节,24个字节或者32个字节,如果不是,可以进行加密,但是不能进行解密。

前端填充方式:

        /**
         * Padding namespace.
         */
        export namespace pad {
            /**
             * PKCS #5/7 padding strategy.
             */
            const Pkcs7: Padding;

            /**
             * ANSI X.923 padding strategy.
             */
            const AnsiX923: Padding;

            /**
             * ISO 10126 padding strategy.
             */
            const Iso10126: Padding;

            /**
             * ISO/IEC 9797-1 Padding Method 2.
             */
            const Iso97971: Padding;

            /**
             * Zero padding strategy.
             */
            const ZeroPadding: Padding;

            /**
             * A noop padding strategy.
             */
            const NoPadding: Padding;
        }

(2)后端加密及解密

①引入依赖

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.14</version>
        </dependency>

②后端加密及解密工具类

package com.example.utils;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;

/**
 * ECB加解密工具类
 */
public class AesTool {
    private static String ALGO = "AES";
    private static byte[] keyValue = "TD2g45EfXqGnBLaXpzPZ6A==".getBytes();

    /**
     * <p>description: 加密</p >
     * <p>param: [Data] </p >
     * <p>return: java.lang.String </p >
     * <p>author: zhangcj </p >
     * <p>date: 2021/12/29 </p >
     */
    public static String encrypt(String data) {
        try {
            Key key = generateKey();
            Cipher c = Cipher.getInstance(ALGO);
            c.init(1, key);
            byte[] encVal = c.doFinal(data.getBytes());
            String encryptedValue = Base64.encodeBase64String(encVal);
            return encryptedValue;
        } catch (Exception var5) {
            throw new RuntimeException(var5);
        }
    }

    // public static String decrypt(String encryptedData, String keyValue) {
    //     try {
    //         Key key = generateKey(keyValue);
    //         Cipher c = Cipher.getInstance(ALGO);
    //         c.init(2, key);
    //         byte[] decordedValue = Base64.decodeBase64(encryptedData);
    //         byte[] decValue = c.doFinal(decordedValue);
    //         String decryptedValue = new String(decValue);
    //         return decryptedValue;
    //     } catch (Exception var6) {
    //         throw new RuntimeException(var6);
    //     }
    // }
    public static String decrypt(String content,String password) throws Exception {
        byte[] contentNew = Base64.decodeBase64(content);
        SecretKeySpec skeySpec = new SecretKeySpec(password.getBytes("UTF-8"), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // "算法/模式/补码方式"
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        return new String(cipher.doFinal(contentNew));
    }
    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGO);
        return key;
    }
    private static Key generateKey(String key) throws Exception {
        return new SecretKeySpec(key.getBytes(), ALGO);
    }
}

③调用方式

        String decrypt = AesTool.decrypt("D5DT/9wwi89s0ny9VYwMTA==", "5bzMeuzs2XQfG8QFyx1hGg==");
        System.out.println(decrypt);

(3)说明

 ECB模式加密,将明文及密钥通过CryptoJS.enc.Utf8.parse进行转换,将UTF8编码的字符串转换为字节数组,然后加密模式及填充方式,最后生成密文。

密文分为两种格式,一种是base64,另一种是hex。

前端加密之后,后端进行解密时,首先根据前端的密文格式,将密文转换成字节数组,再设置和前端一致的模式和补充方式进行解密。

ECB模式加密安全性较低,但性能很高,相同的明文段加密后的密文一致。

前端加密需要的密钥可以由后端生成,生成方式如下:

        // 方式1
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(128);
        SecretKey secretKey = keyGen.generateKey();
        byte[] keyBytes = secretKey.getEncoded();
        String key = Base64.getEncoder().encodeToString(keyBytes);
        System.out.println(key);
        // 方式2
        SecureRandom secureRandom = new SecureRandom();
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128, secureRandom);
        byte[] key2 = keyGenerator.generateKey().getEncoded();
        String base64Key = java.util.Base64.getEncoder().encodeToString(key2);
        System.out.println(base64Key);

主要分为两步:生成一个随机的AES密钥;将密钥已base64编码的形式保存或传输。

3.CBC模式

(1)前端加密及解密

①引入依赖

npm install crypto-js 

②加密及解密工具类

import CryptoJS from 'crypto-js'

// CBC模式
export function Encrypt1(word,key,iv) {
  let srcs = CryptoJS.enc.Utf8.parse(word);
  let keyInfo = CryptoJS.enc.Utf8.parse(key);
  let ivInfo = CryptoJS.enc.Utf8.parse(iv);
  let encrypted = CryptoJS.AES.encrypt(srcs, keyInfo, {
      iv: ivInfo ,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
  })
  return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
}
export function Decrypt1(word,key,iv) {
  let keyInfo = CryptoJS.enc.Utf8.parse(key);
  let ivInfo = CryptoJS.enc.Utf8.parse(iv);
  let base64  = CryptoJS.enc.Base64.parse(word);
  let srcs = CryptoJS.enc.Base64.stringify(base64);
  const decrypt = CryptoJS.AES.decrypt(srcs, keyInfo, {
    iv: ivInfo ,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  });
  const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
  return decryptedStr;
}

 (2)后端加密及解密

①引入依赖

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.14</version>
        </dependency>

②加密及解密工具类

package com.example.utils;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * @Author linaibo
 * @Date 2024/2/7 15:53
 * CBC加解密工具
 * @Version 1.0
 */

public class AexCbcTool {

    // public static String decryptAES(String content,String key, String ivInfo) throws Exception {
    //     SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ASCII"), "AES");
    //     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    //     IvParameterSpec iv = new IvParameterSpec(ivInfo.getBytes());
    //     cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
    //     byte[] encrypted1 = Base64.decodeBase64(content);//先用bAES64解密
    //     return new String(cipher.doFinal(encrypted1));
    // }

    /**
     * 解密
     *
     * @param enc       加密内容
     * @param uniqueKey 唯一key
     * @return
     */
    public static String decrypt(String enc, String uniqueKey, String iv) throws Exception {
        byte[] key = uniqueKey.getBytes();
        SecretKey secretKey = new SecretKeySpec(key, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes("utf-8"));
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        byte[] encrypted1 = Base64.decodeBase64(enc);//先用bAES64解密
        byte[] plainBytes = cipher.doFinal(encrypted1);
        return new String(plainBytes, "UTF-8");
    }

    /**
     * 加密
     *
     * @param src
     * @param uniqueKey
     * @return
     */
    public static String encrypt(String src, String uniqueKey, String iv) throws Exception {
        byte[] key = uniqueKey.getBytes();
        SecretKey secretKey = new SecretKeySpec(key, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes("utf-8"));
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
        byte[] cipherBytes = cipher.doFinal(src.getBytes("UTF-8"));
        String encryptedValue = Base64.encodeBase64String(cipherBytes);
        return encryptedValue;
    }

}

4.总结

在项目中使用时,比如对密码的加密,需要先调用后端接口获取加密密钥,根据获取的加密密钥在前端对密码进行加密,将加密后的信息发送给后端,在后端进行解密,解密之后再进行加密,将加密后的密码和表中的密码进行比较,一致则登录成功

https://blog.51cto.com/u_16175526/7323980

AES算法的CBC和ECB两种工作模式_aes iv需要保密吗-CSDN博客

AES加解密模式_aes_cbc_encrypt-CSDN博客

AES解密报错Invalid AES key length: xx bytes与Given final block not properly padded的解决方法-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/382377.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CTF-PWN-沙箱逃脱-【侧信道爆破】(2021-蓝帽杯初赛-slient)

文章目录 侧信道攻击测信道爆破2021-蓝帽杯初赛-slient先自己准备个flag检查沙箱IDA源码mainsub_A60() 相关知识size_t getpagesize(void)void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);range(i,j)编写相关shellcode发现"的用法此时…

什么是宿主软件?宿主软件有哪些?

什么是宿主软件? 宿主软件就是专业的音乐制作软件&#xff0c;我们日常听到的大多数正规音乐作品都是用宿主软件制作出来的&#xff0c;这些软件一般需要安装各类插件&#xff0c;插件就像寄生虫需要在宿主软件里加载才可以工作。 插件主要分虚拟乐器插件和音频处理插件两类…

JZ36 二叉搜索树与双向链表

目录 题目描述 二叉搜索树与双向链表_牛客题霸_牛客网 题目解析 题目答案 最后 题目描述 二叉搜索树与双向链表_牛客题霸_牛客网 题目解析 这里采用的是采用前序遍历的思想&#xff0c;找到要转换的双向链表的头节点也就是这个二叉搜索树的最左节点&#xff0c;找到之后依…

MySQL篇----第十九篇

系列文章目录 文章目录 系列文章目录前言一、什么是存储过程?用什么来调用?二、如何通俗地理解三个范式?三、什么是基本表?什么是视图?四、试述视图的优点?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这…

力扣[面试题 01.02. 判定是否互为字符重排(哈希表,位图)

Problem: 面试题 01.02. 判定是否互为字符重排 文章目录 题目描述思路复杂度Code 题目描述 思路 思路1&#xff1a;哈希表 1.若两个字符串长度不相等&#xff0c;则一定不符合题意&#xff1b; 2.创建一个map集合&#xff0c;先将字符串s1中的每一个字符与其对应的数量存入集合…

2024.2.10 DMS(数据库管理系统)初体验

数据库管理系统(Database Management System)是一种操纵和管理数据库的大型软件&#xff0c;用于建立、使用和维护数据库&#xff0c;简称DBMS。它对数据库进行统一的管理和控制&#xff0c;以保证数据库的安全性和完整性。用户通过DBMS访问数据库中的数据&#xff0c;数据库管…

大年初一,送出最后8000个红包封面!

今天是大年初一&#xff0c;大家都是怎么安排的&#xff1f; 小灰最近在南方旅游&#xff0c;玩得很开心&#xff0c;后面会给大家分享自己的见闻。 过年期间&#xff0c;大家多少都会给亲朋好友发一些微信红包&#xff0c;拥有个性化的红包封面绝对是一件很酷的事情。 前一段时…

007集——数据存储的端序(大端序和小端序转换代码)——VB/VBA

VB/VBA存储的端序 1、要想制造高性能的VB/VBA代码&#xff0c;离了指针是很难办到的。 2、因为VB/VBA里&#xff0c;用Long来表示指针&#xff0c;而32位(包括64位兼容的)计算机里4字节整数的处理&#xff0c;是最快的方式&#xff01; 3、要想用指针来处理数据&#xff0c;…

4. ⼤模型微调方法

到底有哪些微调⽅法呢&#xff1f; 第⼀类⽅法&#xff1a;借助OpenAI提供的在线微调⼯具进⾏微调&#xff1b;第⼆类⽅法&#xff1a;借助开源微调框架进⾏微调&#xff1b; 1. OpenAI在线微调⼯具 网址&#xff1a;https://platform.openai.com/docs/guides/fine-tuning/c…

无人机遥感技术应用分析,无人机遥感系统测绘技术详解

由于无人机具有机动快速、使用成本低、维护操作简单等技术特点,因此被作为一种理想的飞行平台广泛应用于军事和民用各个领域。尤其是进入二十一世纪以后,许多国家将无人机系统的研究、开发、应用置于优先发展的地位,体积小、重量轻、探测精度高的新型传感器的不断问世,也使无人…

让Python遇上Office--从编程入门到自动化办公实践

最近仔细的学习了这本《让Python遇上Office》的书&#xff0c;同时把我的学习进程与心得录制了同步视频。 到今天终于把全部90集完成&#xff0c;并且上传到下面的视频平台了&#xff0c;欢迎大家观看并指正&#xff01; 西瓜视频&#xff1a;https://www.ixigua.com/7300628…

c语言中的隐式类型转换

数据类型转化 我们在实际编程中&#xff0c;不管你是有意的还是无意的&#xff0c;有时候都会让两个不同类型的数据参与运算&#xff0c;编译器为了能够生成CPU可以正常 执行的指令&#xff0c;往往会对数据做类型转换&#xff0c;将两个不同类型的数据转换成同一种数据类型。…

Popper.js:ElementUI 中采用弹出,提示框库,好用的没朋友。

Hi&#xff0c;我贝格前端工场&#xff0c;继续介绍经典的js库&#xff0c;ElementUI 中Tooltip、Select、Cascader、TimePicker等组件中怎么把提示框定位到目标元素的&#xff0c;是用 Popperjs 来实现。 一、Popper.js是什么&#xff1f; Popper.js是一个用于创建弹出式组件…

LLM之LangChain(七)| 使用LangChain,LangSmith实现Prompt工程ToT

如下图所示&#xff0c;LLM仍然是自治代理的backbone&#xff0c;可以通过给LLM增加以下模块来增强LLM功能: Prompter AgentChecker ModuleMemory moduleToT controller 当解决具体问题时&#xff0c;这些模块与LLM进行多轮对话。这是基于LLM的自治代理的典型情况&#xff0c;…

回归预测模型:MATLAB多项式回归

1. 多项式回归模型的基本原理 多项式回归是线性回归的一种扩展&#xff0c;用于分析自变量 X X X与因变量 Y Y Y之间的非线性关系。与简单的线性回归模型不同&#xff0c;多项式回归模型通过引入自变量的高次项来增加模型的复杂度&#xff0c;从而能够拟合数据中的非线性模式。…

卫星通讯领域FPGA关注技术:算法和图像方面(3)

最近关注的公众号提到了从事移动通信、卫星通讯等领域的FPGA、ASIC、信号处理算法等工程师可能需要关注的技术&#xff0c;有通感融合、RNSS授时、惯导&#xff0c;以下做了一些基础的调研&#xff1a; 1 通感融合 1&#xff09;来自博鳌亚洲论坛创新报告2023:通感算融合已成…

Linux操作系统基础(三):虚拟机与Linux系统安装

文章目录 虚拟机与Linux系统安装 一、系统的安装方式 二、虚拟机概念 三、虚拟机的安装 四、Linux系统安装 1、解压人工智能虚拟机 2、找到解压目录中的node1.vmx 3、启动操作系统 虚拟机与Linux系统安装 一、系统的安装方式 Linux操作系统也有两种安装方式&#xf…

算法学习——LeetCode力扣栈与队列篇1

算法学习——LeetCode力扣栈与队列篇1 232. 用栈实现队列 232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; 描述 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQu…

动态水印怎么加 怎么去除动态水印 视频剪辑软件 会声会影安激活序列号 会声会影怎么剪辑视频

为了防止白嫖或者增加美观效果&#xff0c;视频制作者可能会采用动态水印的方式&#xff0c;让其他人难以盗取视频使用。动态水印的添加&#xff0c;需要应用到运动路径功能。接下来&#xff0c;本文会教大家动态水印怎么加&#xff0c;怎么去除动态水印的相关内容。感兴趣的小…

解析十六进制雷达数据格式:解析雷达数据长度。

以Cat62格式雷达数据为例&#xff0c;十六进制雷达数据部分代码&#xff1a; 3e0120bf7da4ffee0085 雷达数据长度使用4个字符&#xff08;2个字节&#xff09;标识&#xff0c;在这里是“0120”&#xff0c;转换为十进制数为288。 雷达数据长度父类&#xff1a; base_length_…