Java 实现 AES 加密和解密

embedded/2024/12/23 4:42:04/

目录

前言

一、AES 加密算法简介

1.诞生背景

2.简介

二、AES 加密算法的核心原理

1.分组密码模式

2.密钥扩展

3.加密轮次与操作

三、AES 加密算法的优势

1.高效性

2.安全

3.广泛的适用性

四、AES加密模式的几种方式

1.电子密码本模式(ECB,Electronic Codebook)

2.密码分组链接模式(CBC,Cipher - Block - Chaining)

3.密码反馈模式(CFB,Cipher - Feedback)

4.输出反馈模式(OFB,Output - Feedback)

5.计数器模式(CTR,Counter)

五、Java实现AES加密完整案例

注:ECB为什么不用加入ivParameterSpec参数


前言

        在当今数字化飞速发展的时代,数据如洪流般在网络世界中穿梭。从个人隐私信息到企业的核心商业机密,数据的安全成为了重中之重。而在众多加密算法中,AES(Advanced Encryption Standard)加密算法犹如一座坚固的堡垒,为数据的保密性、完整性和安全性提供了强有力的保障。今天,就让我们一同深入探究 AES 加密算法的神秘世界。

一、AES 加密算法简介

1.诞生背景

        AES 是一种分组密码算法,它将明文数据划分为固定长度的分组,每个分组长度为 128 位。当明文长度不是 128 位的整数倍时,会采用特定的填充方式进行补齐,例如常见的 PKCS7 填充。这种分组处理的方式使得 AES 能够高效地处理大量数据,并且保证了加密过程的规范性和一致性。

2.简介

        AES,全称为 Advanced Encryption Standard,是一种分组密码算法,用于保护敏感数据的传输和存储。AES 分为 128 位和 256 位两种密钥长度,可以对数据进行加密和解密,保证数据的安全性和完整性。AES 主要应用于电子商务、移动支付、网络安全等领域,被广泛运用于现代社会的各个方面。AES 算法被设计为高度安全,可以在理论上保证其分组密码的安全性。然而,由于其复杂性和密钥长度,AES 算法的实现和应用也具有一定的技术难度。因此,在应用 AES算法时,需要注意加强密钥管理和安全性保障。

这个标准用来替代原先的 DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。

AES 算法具有很多优点,例如快速、安全、可靠等。它可以加密大量数据,而不会因为加密过程中的数据量过大而变得缓慢。此外,AES 算法还支持块大小的自动调整,可以处理不同大小的数据块。

二、AES 加密算法的核心原理

1.分组密码模式

        AES 是一种分组密码算法,它将明文数据划分为固定长度的分组,每个分组长度为 128 位。当明文长度不是 128 位的整数倍时,会采用特定的填充方式进行补齐,例如常见的 PKCS7 填充。这种分组处理的方式使得 AES 能够高效地处理大量数据,并且保证了加密过程的规范性和一致性。

2.密钥扩展

        AES 支持 128 位、192 位和 256 位三种不同长度的密钥。在加密开始前,会根据所选的密钥长度进行密钥扩展操作。通过一系列复杂的数学变换和算法,将原始密钥扩展成多个轮密钥。这些轮密钥在后续的加密轮次中依次被使用,每一轮加密都依赖于特定的轮密钥,从而极大地增加了密码的安全性和破解难度。

3.加密轮次与操作

  • 字节替换(SubBytes):这是 AES 加密中的一个关键非线性变换步骤。通过一个预先定义好的 S 盒(Substitution Box),将每个字节按照特定的规则替换为另一个字节。S 盒的设计经过精心考量,具有良好的混淆特性,能够有效地打乱数据的原始结构,使得攻击者难以从密文中直接获取明文的信息。
  • 行移位(ShiftRows):在字节替换之后,对 4×4 的状态矩阵(由 128 位分组数据组成)进行行移位操作。不同行按照不同的位移量进行循环左移,这种操作进一步扩散了数据在矩阵中的位置关系,增加了数据的复杂性。
  • 列混合(MixColumns):此操作针对状态矩阵的每一列进行线性变换。通过与一个固定的矩阵相乘,使得每一列的数据相互影响、相互交织,从而将数据的信息更加均匀地分布在整个矩阵中,提高了密码的扩散性。
  • 轮密钥加(AddRoundKey):在每一轮加密中,将经过前面几步变换后的状态矩阵与当前轮的轮密钥进行逐位异或运算。这一步骤将密钥信息融入到数据中,确保了加密结果与密钥紧密相关,只有拥有正确密钥的接收方才能进行解密操作。

        对于不同长度的密钥,AES 分别有不同的轮数:128 位密钥对应 10 轮加密,192 位密钥对应 12 轮加密,256 位密钥对应 14 轮加密。在最后一轮加密中,通常会省略列混合操作,以保证加密和解密过程的可逆性。

三、AES 加密算法的优势

1.高效性

        AES 算法在设计上兼顾了安全性和效率。其分组处理方式和相对简洁的加密轮次设计,使得它在现代计算机系统中能够快速地对大量数据进行加密和解密操作。无论是在高速网络通信中的数据实时加密,还是在大规模数据存储时的批量加密处理,AES 都能够表现出色,不会对系统性能造成过大的负担。

2.安全

        凭借其较长的密钥长度选项、复杂的密钥扩展机制以及多轮加密操作中的混淆和扩散特性,AES 能够抵御多种形式的攻击,包括暴力破解、差分攻击和线性攻击等。经过多年的实践检验和学术界、工业界的深入研究,AES 被广泛认为是一种高度安全的加密算法,为全球范围内的敏感数据提供了可靠的保护。

3.广泛的适用性

        AES 加密算法几乎适用于所有需要数据加密的场景。在网络通信领域,如 SSL/TLS 协议中,它被用于保护网页浏览、电子邮件传输、文件下载等过程中的数据安全;在数据存储方面,无论是本地硬盘存储还是云端存储,AES 都可以对数据进行加密存储,防止数据泄露;在移动应用开发中,用于保护用户的隐私信息,如聊天记录、个人资料等。

四、AES加密模式的几种方式

1.电子密码本模式(ECB,Electronic Codebook)

原理:
ECB 是最基本的 AES 加密模式。它将明文数据按照分组长度(AES 分组长度为 128 位)划分为若干个分组。每个分组都独立地使用相同的密钥进行加密,就好像在查密码本一样,相同的明文分组加密后得到相同的密文分组。加密后的密文分组简单拼接起来就形成了最终的密文。
优点:
简单直观,易于理解和实现。由于每个分组独立加密,所以加密过程可以并行处理,在一些对性能要求较高且对数据模式不太敏感的场景下有一定优势。
缺点:
安全性较低。因为相同的明文分组会产生相同的密文分组,这使得攻击者可以通过分析密文的模式来获取明文信息。例如,如果明文数据中有重复的部分,密文也会出现相应的重复部分,容易被攻击者利用来进行频率分析等攻击。
应用场景:
适用于对安全性要求不高,或者数据内容随机性较强、重复率较低的场景。例如,加密一些临时的、内部使用的、且价值较低的数据,或者加密简单的配置文件等。

2.密码分组链接模式(CBC,Cipher - Block - Chaining)

原理:
CBC 模式在加密过程中引入了反馈机制。它需要一个初始值,即初始化向量(IV),这个向量的长度与分组长度相同(对于 AES 为 128 位)。在加密时,第一个明文分组先和初始化向量进行异或(XOR)操作,然后使用密钥进行加密得到第一个密文分组。对于后续的明文分组,先将其与前一个密文分组进行异或操作,再用密钥加密,依次类推。
优点:
安全性较高。由于每个明文分组在加密前都与前一个密文分组进行了异或操作,这使得相同的明文分组在不同的位置加密后会得到不同的密文分组,避免了 ECB 模式中密文重复的问题,能够有效抵抗多种形式的攻击。
缺点:
加密过程不能并行进行,因为每个分组的加密依赖于前一个分组的密文。另外,需要妥善管理和传输初始化向量,保证其在加密和解密过程中的一致性。
应用场景:
广泛应用于各种对安全性要求较高的数据加密场景,如网络通信加密、数据存储加密等。在实际的安全协议(如 SSL/TLS)和大多数加密应用中,CBC 模式是比较常见的选择。

3.密码反馈模式(CFB,Cipher - Feedback)

原理:
CFB 模式将 AES 加密算法作为一个伪随机数生成器来使用。它也需要一个初始化向量(IV),长度与分组长度相同。首先对初始化向量进行加密,得到的结果与明文的第一个字节(或多个字节,取决于具体的 CFB 位数)进行异或操作,得到密文的第一个字节。然后将这个加密后的初始化向量左移一定位数(取决于 CFB 位数),再将新的明文字节放入最右边的空位,再次进行加密和异或操作,以此类推,直到所有明文都被加密。
优点:
可以将分组密码转换为流密码的工作方式,使得加密可以在数据长度小于分组长度时也能进行。它对明文长度没有严格要求,并且具有较好的实时性,适合对数据长度不确定的流式数据进行加密。
缺点:
与 CBC 模式类似,加密过程不能完全并行进行,并且对初始化向量的管理要求较高。同时,由于其工作方式类似于流密码,存在一些针对流密码的攻击方式可能对其构成威胁。
应用场景:
适用于对实时性要求较高的流式数据加密,如网络通信中的实时语音、视频数据加密,或者在一些需要按字节或小段数据进行加密的场景。

4.输出反馈模式(OFB,Output - Feedback)

原理:
OFB 模式与 CFB 模式有些类似,但它是将加密后的结果反馈给下一轮加密作为输入,而不是像 CFB 模式那样将明文和加密后的结果进行异或。具体来说,首先对初始化向量进行加密,得到的结果作为密钥流的第一个部分,与明文的第一个字节(或多个字节,取决于具体的 OFB 位数)进行异或操作,得到密文的第一个字节。然后将这个加密后的结果(不进行左移等操作)再次进行加密,得到密钥流的下一部分,继续与下一个明文字节进行异或,以此类推。
优点:
与 CFB 模式一样,可以将分组密码转换为流密码的工作方式,对数据长度的适应性较好,并且在加密过程中,密钥流的生成与明文无关,只要密钥和初始化向量相同,就可以生成相同的密钥流,这使得它在一些需要提前生成密钥流的场景下比较方便。
缺点:
对初始化向量的要求严格,一旦初始化向量泄露,可能会导致整个加密过程的安全性受损。并且,如果加密过程中密钥流出现重复部分,可能会被攻击者利用。
应用场景:
适用于对数据长度不确定的流式数据加密,尤其是在需要提前生成密钥流或者对密钥流的重复性有一定控制的场景,如一些特殊的通信协议或者数据加密场景。

5.计数器模式(CTR,Counter)

原理:
CTR 模式使用一个计数器来生成密钥流。计数器可以是一个简单的数字序列,从一个初始值开始,每次加密一个分组后,计数器的值增加。首先将计数器的值进行加密,得到的结果作为密钥流与明文分组进行异或操作,得到密文分组。然后计数器增加,重复上述过程,直到所有明文分组都被加密。
优点:
加密过程可以并行进行,因为每个分组的加密只依赖于计数器的值和密钥,而不依赖于其他分组的密文。同时,它能够将分组密码转换为流密码的工作方式,对数据长度的适应性较好,并且安全性较高。
缺点:
需要保证计数器的值在加密和解密过程中的一致性,并且计数器的使用方式如果不当,可能会导致安全问题,例如计数器重复或者可预测等情况。
应用场景:
适用于对高性能和高安全性都有要求的场景,如大规模数据加密、云计算环境中的数据加密等,并且在一些需要并行加密处理的场景中具有优势。

五、Java实现AES加密完整案例

java">package com.ctb.demo;import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Random;/*** AES 加密解密示例* * @author biao** 2024年12月20日*/
public class AESExample {//加密模式之 ECB,AES/ECB/PKCS5Padding-----算法/模式/补码方式private static final String AES_ECB = "AES/ECB/PKCS5Padding";//加密模式之 CBC,算法/模式/补码方式private static final String AES_CBC = "AES/CBC/PKCS5Padding";//加密模式之 CFB,算法/模式/补码方式private static final String AES_CFB = "AES/CFB/PKCS5Padding";//AES 中的 IV 必须是 16 字节(128位)长private static final Integer IV_LENGTH = 16;/**** 空值校验* @param str 需要判断的值*/public static boolean isEmpty(Object str) {return null == str || "".equals(str);}/**** 字符串转byte字节* @param str 需要转换的字符串*/public static byte[] getBytes(String str){if (isEmpty(str)) {return null;}try {return str.getBytes(StandardCharsets.UTF_8);} catch (Exception e) {throw new RuntimeException(e);}}/**** 初始化向量(IV),它是一个随机生成的字节数组,用于增加加密和解密的安全性*/public static String getIV(){String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";Random random = new Random();StringBuffer sb = new StringBuffer();for(int i = 0 ; i < IV_LENGTH ; i++){int number = random.nextInt(str.length());sb.append(str.charAt(number));}return sb.toString();}/**** 获取一个 AES 密钥规范*/public static SecretKeySpec getSecretKeySpec(String key){SecretKeySpec secretKeySpec = new SecretKeySpec(getBytes(key), "AES");return secretKeySpec;}/*** 加密模式 --- ECB* @param text 需要加密的文本内容* @param key 加密的密钥 key* */public static String encrypt(String text, String key){if (isEmpty(text) || isEmpty(key)) {return null;}try {// 创建AES加密器Cipher cipher = Cipher.getInstance(AES_ECB);// 将密钥转换为SecretKeySpec格式SecretKeySpec secretKeySpec = getSecretKeySpec(key);// 初始化Cipher为加密模式,传入密钥cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);// 加密字节数组,将明文转换为字节数组进行加密byte[] encryptedBytes = cipher.doFinal(getBytes(text));// 将密文转换为 Base64 编码字符串return Base64.getEncoder().encodeToString(encryptedBytes);} catch (Exception e) {throw new RuntimeException(e);}}/*** 解密模式 --- ECB* @param text 需要解密的文本内容* @param key 解密的密钥 key* */public static String decrypt(String text, String key){if (isEmpty(text) || isEmpty(key)) {return null;}// 将密文转换为16字节的字节数组byte[] textBytes = Base64.getDecoder().decode(text);try {// 创建AES加密器Cipher cipher = Cipher.getInstance(AES_ECB);// 将密钥转换为SecretKeySpec格式SecretKeySpec secretKeySpec = getSecretKeySpec(key);// 初始化Cipher为加密模式,传入密钥cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);// 解密字节数组,将明文转换为字节数组进行解密byte[] decryptedBytes = cipher.doFinal(textBytes);// 将明文转换为字符串return new String(decryptedBytes, StandardCharsets.UTF_8);} catch (Exception e) {throw new RuntimeException(e);}}/*** 加密 - 自定义加密模式* @param text 需要加密的文本内容* @param key 加密的密钥 key* @param iv 初始化向量* @param mode 加密模式* */public static String encrypt(String text, String key, String iv, String mode){if (isEmpty(text) || isEmpty(key) || isEmpty(iv)) {return null;}try {// 创建AES加密器Cipher cipher = Cipher.getInstance(mode);// 将密钥转换为SecretKeySpec格式SecretKeySpec secretKeySpec = getSecretKeySpec(key);// 初始化Cipher为加密模式,传入密钥和初始化向量cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(getBytes(iv)));// 加密字节数组,将明文转换为字节数组进行加密byte[] encryptedBytes = cipher.doFinal(getBytes(text));// 将密文转换为 Base64 编码字符串return Base64.getEncoder().encodeToString(encryptedBytes);} catch (Exception e) {throw new RuntimeException(e);}}/*** 解密 - 自定义加密模式* @param text 需要解密的文本内容* @param key 解密的密钥 key* @param iv 初始化向量* @param mode 加密模式* */public static String decrypt(String text, String key, String iv, String mode){if (isEmpty(text) || isEmpty(key) || isEmpty(iv)) {return null;}// 将密文转换为16字节的字节数组byte[] textBytes = Base64.getDecoder().decode(text);try {// 创建AES加密器Cipher cipher = Cipher.getInstance(mode);// 将密钥转换为SecretKeySpec格式SecretKeySpec secretKeySpec = getSecretKeySpec(key);// 初始化Cipher为加密模式,传入密钥和初始化向量cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(getBytes(iv)));// 解密字节数组,将明文转换为字节数组进行解密byte[] decryptedBytes = cipher.doFinal(textBytes);// 将明文转换为字符串return new String(decryptedBytes, StandardCharsets.UTF_8);} catch (Exception e) {throw new RuntimeException(e);}}public static void main(String[] args) {String text = "我就是加密的内容";String key  = "1234567812345678"; // 16字节的密钥String iv  = getIV();//ECBString encryptTextECB = encrypt(text, key);System.out.println("ECB 加密后内容:" + encryptTextECB);System.out.println("ECB 解密后内容:" + decrypt(encryptTextECB, key));System.out.println();//CBCString encryptTextCBC = encrypt(text, key, iv, AES_CBC);System.out.println("CBC 加密IV:" + iv);System.out.println("CBC 加密后内容:" + encryptTextCBC);System.out.println("CBC 解密后内容:" + decrypt(encryptTextCBC, key, iv, AES_CBC));System.out.println();//CFBString encryptTextCFB = encrypt(text, key, iv, AES_CFB);System.out.println("CFB 加密IV:" + iv);System.out.println("CFB 加密后内容:" + encryptTextCFB);System.out.println("CFB 解密后内容:" + decrypt(encryptTextCFB, key, iv, AES_CFB));}
}

注:ECB为什么不用加入ivParameterSpec参数

1.ECB(电子密码本模式)特点

  • ECB(Electronic Codebook)是一种最简单的分组密码工作模式。在这种模式下,每个明文分组都是独立地使用相同的密钥进行加密,加密后的密文分组组合起来就是最终的密文。
  • 由于每个分组的加密过程是相互独立的,没有反馈机制,所以不需要初始化向量(IV)。每个明文分组的加密只依赖于密钥,对于相同的明文分组和密钥,加密后的密文分组总是相同的。

2.示例对比(与需要 IV 的 CBC 模式对比)

        ECB 模式在Cipher.getInstance方法中指定的模式是AES/ECB/PKCS5Padding,在init方法初始化Cipher时不需要传入IvParameterSpec对象;而 CBC 模式指定的是AES/CBC/PKCS5Padding,在初始化Cipher时需要传入包含初始化向量的IvParameterSpec对象。

3.安全考量

        由于 ECB 模式每个明文分组的加密结果固定,这使得它存在一定的安全风险。如果攻击者获取到足够多的相同明文分组的密文,就有可能通过分析这些密文来获取明文信息。所以在实际应用中,对于对安全性要求较高的场景,通常不推荐使用 ECB 模式,而更倾向于使用 CBC、CFB(Cipher Feedback)、OFB(Output Feedback)等带有反馈机制且需要 IV 的加密模式,这些模式可以通过 IV 和反馈机制来增加密文的随机性,提高安全性。

示例结果:


http://www.ppmy.cn/embedded/147979.html

相关文章

【嵌入式开发笔记】OpenOCD到嵌入式调试

最近在把玩一块Risc-V的开发板&#xff0c;使用开发板调试时&#xff0c;需要用到专门的下载器和OpenOCD进行调试。 为了连接这个板子&#xff0c;费了九牛二虎之力。 这里简单记录一下自己的折腾经过吧。 0x00 环境准备 0x0001 调试背景 系统&#xff1a;Virtual Box Ub…

【软考高级】系统架构设计师复习笔记-精华版

文章目录 前言0 系统架构设计师0.1 考架构还是考系分0.2 架构核心知识0.3 架构教材变化 1 计算机操作系统1.1 cpu 组成1.2 内核的五大功能1.3 流水线技术1.4 段页式存储1.5 I/O 软件1.6 文件管理1.7 系统工程相关 2 嵌入式2.1 嵌入式技术2.2 板级支持包&#xff08;BSP&#xf…

Windows开机黑屏|Windows开机黑屏只有鼠标|Windows开机不运行explorer

输入regedit打开注册表&#xff0c;进入以下路径 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon 左键双击右侧的 Shell 查看是否设置为 Explorer.exe

MONI后台管理系统-swagger3(springdoc-openapi)集成

springdoc-openapi Java 库有助于使用 Spring Boot 项目自动生成 API 文档。springdoc-openapi 通过在运行时检查应用程序来根据 Spring 配置、类结构和各种注释推断 API 语义。 该库会自动生成 JSON/YAML 和 HTML 格式的页面文档。生成的文档可以使用swagger-api注释进行补充。…

聚观早报 | 百度回应进军短剧;iPad Air将升级OLED

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 12月18日消息 百度回应进军短剧 iPad Air将升级OLED 三星Galax S25 Ultra配色细节 一加Ace 5系列存储规格 小米…

呼入机器人:24小时客户服务的未来趋势

呼入机器人&#xff1a;24小时客户服务的未来趋势 作者&#xff1a;开源大模型智能呼叫中心系统FreeAICC&#xff0c;Github&#xff1a;https://github.com/FreeIPCC/FreeAICC 在当今快节奏的商业环境中&#xff0c;客户服务已成为企业竞争的核心要素之一。随着人工智能技术…

Spring篇--xml方式整合第三方框架

Spring xml方式整合第三方框架 xml整合第三方框架有两种整合方案&#xff1a; ​ 不需要自定义名空间&#xff0c;不需要使用Spring的配置文件配置第三方框架本身内容&#xff0c;例如&#xff1a;MyBatis&#xff1b; ​ 需要引入第三方框架命名空间&#xff0c;需要使用…

web组态软件开发详细流程介绍

什么是组态软件&#xff1f; 组态软件是一种用于创建、配置和管理各种工业控制系统的应用程序。它通过用户友好的图形界面和先进的功能&#xff0c;使工程师能够实时监控和控制复杂的工业过程。 一、组态软件的基本概念 1.1 组态软件的作用 组态软件在工业控制系统中起到关键…