C中AES_cbc_encrypt加密对应java中的解密
前言知识:
1.AES(Advanced Encryption Standard)高级加密标准,作为分组密码(把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文)。
2.在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)8的倍数。密钥的长度可以使用128位、192位或256位,分别对应的就是AES128
,AES192
,AES256,
密钥的长度不同,推荐加密轮数也不同,从安全性来看,AES256
安全性最高。从性能看,AES128
性能最高。本质原因就是它们的加密处理轮数不同
3.AES属于对称加密算法,是因为加解密使用同一个秘钥,
4.AES
支持三种长度的密钥: 128位,192位,256位,一般有至少4种模式,即ECB、CBC、CFB、OFB等
5.AES
算法在对明文加密的时候,并不是把整个明文一股脑的加密成一整段密文,而是把明文拆分成一个个独立的明文块,每一个明文块长度128bit
。这些明文块经过
AES
加密器复杂处理,生成一个个独立的密文块,这些密文块拼接在一起,就是最终的AES
加密的结果。但这里涉及到一个问题,假如一段明文长度是
196bit
,如果按每128bit
一个明文块来拆分的话,第二个明文块只有64bit
,不足128bit
。这时候怎么办呢?就需要对明文块进行填充(Padding) 。
6.几种典型的填充方式:
NoPadding
: 不做任何填充,但是要求明文必须是16字节的整数倍。PKCS5Padding
(Java默认): 如果明文块少于16个字节(128bit
),在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。 比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则补全为{1,2,3,4,5,a,b,c,d,e,6,6,6,6,6,6 }ISO10126Padding
:如果明文块少于16个字节(128bit
),在明文块末尾补足相应数量的字节,最后一个字符值等于缺少的字符数,其他字符填充随机数。比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则可能补全为{1,2,3,4,5,a,b,c,d,e,5,c,3,G,$,6}PKCS7Padding
原理与PKCS5Padding
相似,区别是PKCS5Padding
的blocksize
为8字节,而PKCS7Padding
的blocksize
可以为1到255字节需要注意的是,如果在
AES
加密的时候使用了某一种填充方式,解密的时候也必须采用同样的填充方式,ZeroPadding
(C++默认,java没有次填充方式):java操作的话,明文不足16位则手动补零,然后调用NoPadding
AES四种工作模式原理:
1、ECB模式:
ECB (电子密码本)模式是最简单的块密码加密模式,加密前根据数据块大小(如AES为128位,每组大小跟加密秘钥长度相同)分成若干块,之后将每块使用相同的密钥单独通过块加密器密器。这种加密模式的优点就是简单,不需要初始化向量(IV) ,每个数据块独立进行加/解密,利于并行计算,加/解密效率很高。但这种模式中,所有数据都采用相同密钥进行加/解密,也没有经过任何逻辑运算,相同明文得到相同的密文,所以可能导致“选择明文攻击”的发生。(最早采用和最简单的模式)
优点: 1.简单; 2.有利于并行计算; 3.误差不会被扩散;
缺点: 1.不能隐藏明文的模式; 2.可能对明文进行主动攻击; 因此,此模式适于加密小消息
2、CBC模式: 参考
CBC (密码分组链接)模式是先将明文切分成若干小块,然后每个小块与初始块或者上一段的密文段进行逻辑异或运算后,再用密钥进行加密。第一个明文块与一个叫初始化向量的数据块进行逻辑异或运算。这样就有效的解决了ECB模式所暴露出来的问题,即使两个明文块相同,加密后得到的密文块也不相同。但是缺点也相当明显,如加密过程复杂,效率低等。
优点: 不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
缺点: 1.不利于并行计算; 2.误差传递; 3.需要初始化向量IV
3、CFB模式:
与ECB和CBC模式只能够加密块数据不同,CFB模式能够将密文转化成为流密文。这种加密模式中,由于加密流程和解密流程中被块加密器加密的数据是前块的密文,因此即使本块明文数据的长度不是数据块大小的整数倍也是不需要填充的,这保证了数据长度在加密前后是相同的。
优点: 1.隐藏了明文模式; 2.分组密码转化为流模式; 3.可以及时加密传送小于分组的数据;
缺点: 1.不利于并行计算; 2.误差传送:一个明文单元损坏影响多个单元; 3.唯一的IV;
4、OFB模式:
不再直接加密明文块,其加密过程是先使用块加密器生成密钥流,然后再将密钥流和明文流进行逻辑异或运算得到密文流。
优点: 1.隐藏了明文模式; 2.分组密码转化为流模式; 3.可以及时加密传送小于分组的数据;
缺点: 1.不利于并行计算; 2.对明文的主动攻击是可能的; 3.误差传送:一个明文单元损坏影响多个单元;
AES的算法原理
加密算法的一般设计准则
混淆 (Confusion) 最大限度地复杂化密文、明文与密钥之间的关系,通常用非线性变换算法达到最大化的混淆。
扩散 (Diffusion) 明文或密钥每变动一位将最大化地影响密文中的位数,通常采用线性变换算法达到最大化的扩散。
对Rijndael算法来说解密过程就是加密过程的逆向过程。下图为AES加解密的流程,从图中可以看出:1)解密算法的每一步分别对应加密算法的逆操作,2)加解密所有操作的顺序正好是相反的。正是由于这几点(再加上加密算法与解密算法每步的操作互逆)保证了算法的正确性。具体参考1 参考2
正文(C中AES_cbc_encrypt加密对应java中的解密)
//C中的加密方式
AES_cbc_encrypt((const unsigned char*)in.data(),(unsigned char*)out.data(),len,&aes,(unsigned char*)ivec.data(),AES_ENCRYPT);
AES_cbc_encrypt:这是C++中AES中的CBC加密方式,可以对任意长度的输入数据进行加密,若输入数据不为16字节整数倍时,该函数内部会使用ZeroPadding自动对输入数据,进行填充,再进行加密。然后我查了一下,java中没有ZeroPadding,都是手动实现补零然后调用NoPadding的,我的具体实现:
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;/*** @ClassName AESCBCUtil* @Description TODO* @Author wanghaha* @Date 2023/3/1**/
public class AESCBCUtil {/** @Description: 满足pc的加密方式 生成128位* @Author: wanghaha* @Date: 2023/3/1* @param: data* @param: iv* @return: java.lang.String**/public static String encrypt128(String data, String iv) {byte[] key = new byte[16];for (int i = 0; i < 16; i++) {key[i] = (byte) (29 + i * 3);}try {Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");byte[] dataBytes = data.getBytes();byte[] plaintext = new byte[128];//填充System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);SecretKeySpec keySpec = new SecretKeySpec(key, "AES");//设置偏移量参数IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);byte[] encryped = cipher.doFinal(plaintext);return DatatypeConverter.printBase64Binary(encryped);} catch (Exception e) {e.printStackTrace();return null;}}/* 加密 正常长度* @Description:* @Author: wanghaha* @Date: 2023/3/1* @param: null* @return: null**/public static String encrypt(String data, String iv) {byte[] key = new byte[16];for (int i = 0; i < 16; i++) {key[i] = (byte) (29 + i * 3);}try {Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");byte[] dataBytes = data.getBytes();int blockSize = cipher.getBlockSize();int length = dataBytes.length;//计算需填充长度if (length % blockSize != 0) {length = length + (blockSize - (length % blockSize));}byte[] plaintext = new byte[length];//填充System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);SecretKeySpec keySpec = new SecretKeySpec(key, "AES");//设置偏移量参数IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);byte[] encryped = cipher.doFinal(plaintext);return DatatypeConverter.printBase64Binary(encryped);} catch (Exception e) {e.printStackTrace();return null;}}//解密public static String desEncrypt(String data, String iv) {byte[] key = new byte[16];for (int i = 0; i < 16; i++) {key[i] = (byte) (29 + i * 3);}try {byte[] encryp = DatatypeConverter.parseBase64Binary(data);Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");SecretKeySpec keySpec = new SecretKeySpec(key, "AES");IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);byte[] original = cipher.doFinal(encryp);//因为pc端使用加密的是zeroPadding: 后补0的Nopadding方式 且 都是字符unsigned限制的 char正数 可以通过判断第一个0的位置判断字符长度int end=0;while(end < original.length && original[end] != 0){end++;}return new String(original,0, end);} catch (Exception e) {e.printStackTrace();}return null;}//测试public static void main(String[] args) {String data = "232342342342342";String iv = "2334022720230227";String encrypt= encrypt(data ,iv);String desencrypt = desEncrypt(encrypt,iv);System.out.println("长加密后:"+encrypt);System.out.println("长解密后:"+desencrypt);}
}
遇到的bug解决方法:
bug1:在做AES解密的时候,碰到了"Given final block not properly padded. Such issues can arise if a bad key is used during decryption"报错,意思就是加密和加密所所对应的秘钥不同
bug2:在使用java的Cipher类进行AES加密时,报错:IllegalBlockSizeException: Input length not multiple of 16 bytes
报错的代码 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding")
填充方式如果是Nopadding,那么加密的明文就得是8的倍数,或者是密钥必须是16位的
待加密内容的长度必须是16的倍数,如果不是16的倍数
总结:Java虽然支持AES的CBC模式,但是填充方式不支持ZeroPadding。
原理:ZeroPadding就是用'\0'将加密内容填充至BlockSize(CBC一般是16)的整数倍,再用NoPadding方式填充即可。
相关文章:

C中AES_cbc_encrypt加密对应java中的解密
前言知识: 1.AES(Advanced Encryption Standard)高级加密标准,作为分组密码(把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文)。 2.在AES标准…...

演化算法:乌鸦搜索算法 (Crow Search Algorithm)
前言 如果你对这篇文章感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。 在机器学习中,我们所要优化的问题很多时候难以求导,因此通常会采用一些演化算法(又称零…...

基于open62541的OPC UA服务器和客户端开发技术
一、OPC UA的基本概念 1、OPC(OLE for Process Control),是一个工业标准,管理这个标准的国际组织是OPC基金会; 2、OPC通信结构:是指包含一个或多个OPC客户端与服务器相互通信的集合。以下是一个简单的流程图:标准的C/S结构。 3、OPC服务器:TOPC基金会定义了四种;...

测试测开面试要知道的那些事01
列表与元组的区别列表是动态数组,它们可变且可以重设长度(改变其内部元素的个数)。元组是静态数组,它们不可变,且其内部数据一旦创建便无法改变。元组缓存于Python运行时环境,这意味着我们每次使用元组时无…...

物联网毕设 -- 智能厨房监测系统(改)
前言 在家庭生活中,厨房是必不可少的,所以厨房的安全问题关乎着我们大家的生命,所以提出智能厨房监测系统,目的就是为我们减少不必要的安全问题 ⚠️⚠️(本文章仅提供思路和实现方法,并不包含代码&#x…...

macOS 13.3 Beta 3 (22E5236f)发布
系统介绍3 月 8 日消息,苹果今日向 Mac 电脑用户推送了 macOS 13.3 开发者预览版 Beta 3 更新(内部版本号:22E5236f),本次更新距离上次发布隔了 7 天。macOS Ventura 带来了台前调度、连续互通相机、FaceTime 通话接力…...
Failed to configure a DataSource: ‘url‘ attribute
一 完整的错误信息 *************************** APPLICATION FAILED TO START *************************** Description: Failed to configure a DataSource: url attribute is not specified and no embedded datasource could be configured. Reason: Failed to dete…...
Mysql高级——锁
锁 mysql锁的分类 从性能上分为:乐观锁、悲观锁从锁的粒度上分:行锁、间隙锁、页锁、悲观锁从对数据库的操作分类:读锁、写锁 乐观锁需要我们自己通过version字段来实现,如果更新失败则在代码中进行where重试。而我们常见的读锁…...

Spring的Async注解线程池扩展方案
目录- [Spring的Async注解线程池扩展方案]- [目录]- [1. 扩展目的]- [2. 扩展实现]- [2.1 扩展Async注解的执行拦截器AnnotationAsyncExecutionInterceptor]- [2.2 扩展Async注解的Spring代理顾问AsyncAnnotationAdvisor]- [2.3 扩展Async注解的 Spring Bean 后置处理器AsyncAn…...
wfb-ng 锁定WiFi接口
wfb-ng 锁定WiFi接口1. 源由2. 需求3. 分析4. 步骤4.1 确认网卡MAC地址4.2 修改udev配置文件4.3 配置重载&重启4.4 确认逻辑网卡接口4.6 修改wfb-ng逻辑WiFi通信接口5. 参考资料6. 补充资料为了更加方便的调试和使用wfb-ng软件,解决由于设备枚举发现时命名可能存…...

Python所有方向的入门和进阶路线,20年老师傅告诉你方法
干了20多年程序员,对于Python研究一直没停过,这几天把我自己对Python的认知和经验,再结合很多招聘网站上的技术要求,整理出了Python所有方向的学习路线图,基本上各个方向应该学什么,都在上面了,…...

RLOAM/RO-LOAM
LOAM框架 LOAM框架包含三个步骤: Scan registration:从原始激光扫描点数据中提取点特征。点特征是角点或者面点。 odometry estimation:在特征提取之后,特征点传递到里程计模块,通过特征匹配和优化步骤计算相对坐标变…...

JUC并发编程之Semaphore-应用与深度源码剖析
目录 JUC并发编程之Semaphore-应用与深度源码剖析 1. Semaphore 是什么? 2.怎么使用Semaphore? 2.1构造方法 2.2 重要方法 2.3 基本使用 需求场景 基础版代码实现 tryAcquire()引入代码实现 acquireUninterruptibly(),acquire()对比代码实现 3.…...

JWT详细介绍使用
一、JWT介绍 JWT是JSON Web Token的缩写,即JSON Web令牌,是一种自包含令牌。 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。 JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务…...

C/C++开发,无可避免的多线程(篇六).线程池封装类
一、线程池概念 线程池是一种多线程处理方式,它包含一个线程工作队列和一个任务队列。当有任务需要处理时,线程池会从线程工作队列中取出一个空闲线程来处理任务,如果线程工作队列中没有空闲线程,则任务会被放入任务队列中等待处理…...
HIVE中如何实现针对IPv6 CIDR的查询
Hive默认情况下不支持IPv6 CIDR查询,因为IPv6 CIDR查询需要使用一些额外的函数。 但是可以通过使用UDF(用户自定义函数)来实现这一点。 IPv6 CIDR表示为网络地址/前缀长度,其中网络地址是一个IPv6地址,前缀长度是一个介于0和128之间的整数,表示网络地址中前多少位是网络…...

【微信小程序】-- 生命周期(二十八)
💌 所属专栏:【微信小程序开发教程】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &…...

Kafka 概述
Kafka 概述Broker消费者Kafka 属于分布式的消息引擎系统,主要功能 :提供一套完备的消息发布与订阅解决方案 生产者和消费者都是客户端(Clients): 生产者(Producer):向主题发布消息…...

详解Java8中如何通过方法引用获取属性名/::的使用
在我们开发过程中常常有一个需求,就是要知道实体类中Getter方法对应的属性名称(Field Name),例如实体类属性到数据库字段的映射,我们常常是硬编码指定 属性名,这种硬编码有两个缺点。 1、编码效率低&#x…...

0106广度优先搜索和最短路径-无向图-数据结构和算法(Java)
1 单点最短路径 单点最短路径。 给定一幅图和一个起点s,回答“从s到给定目的顶点v是否存在一条路径?如果有,找出其中最短的那条(所含边数最少)。“等类似问题。 深度优先搜索在这个问题上没有什么作为,因为…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...