AES/CBC/PKCS5Padding详解

AES(Advanced Encryption Standard)是一种对称加密算法,被广泛用于密码学中。而CBC(Cipher Block Chaining)是一种加密模式,通过将前一次加密的结果与明文异或再进行加密的方式,增强了加密的安全性。而PKCS5Padding则是一种填充方式,通过填充字节来满足AES算法对明文长度的要求,保证加密的正常进行。

一、AES的实现

AES算法的实现需要使用密钥来进行加密和解密,密钥的长度分别为128位、192位和256位。我们可以使用Java自带的javax.crypto包中的Cipher类来实现AES的加密和解密。以下是AES加密的代码示例:

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

public class AESUtil {
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";

    public static byte[] encrypt(byte[] data, byte[] key, byte[] iv) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));
        return cipher.doFinal(data);
    }

    public static byte[] decrypt(byte[] encryptedData, byte[] key, byte[] iv) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
        return cipher.doFinal(encryptedData);
    }
}

在该示例中,我们使用了SecretKeySpec类来创建一个密钥对象,使用Cipher类来创建加密和解密对象。在加密和解密时都需要传入密钥和偏移量,这两个参数应当在加密和解密过程中保持一致。

二、CBC模式

CBC是一种加密模式,其工作方式是将前一个加密块的密文与当前的明文进行异或运算,然后再进行加密。这样可以增强加密的随机性,提高了安全性。以下是CBC模式的加密和解密代码示例:

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class CBCUtil {
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
    private static final String CHARSET = "UTF-8";

    public static String encrypt(String data, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(CHARSET));
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes(CHARSET));
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    public static String decrypt(String data, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(CHARSET));
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(data));
        return new String(decryptedBytes, CHARSET);
    }
}

在该示例中,我们使用了IvParameterSpec类来设置偏移量,该类需要传入一个byte数组来表示偏移量,使用了Base64算法来进行字节码与字符串的转换。

三、PKCS5Padding填充方式

PKCS5Padding是一种填充方式,主要用于满足AES算法对明文长度的要求,因为AES算法要求明文长度必须是16的倍数。PKCS5Padding的填充规则是用一个字节的数值来填充不足的字节,填充的数值即为缺少的字节数。以下是PKCS5Padding的填充和去填充代码示例:

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class PKCS5PaddingUtil {
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
    private static final String CHARSET = "UTF-8";

    public static String encrypt(String data, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(CHARSET));
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
        byte[] dataBytes = data.getBytes(CHARSET);
        int blockSize = cipher.getBlockSize();
        int plaintextLength = dataBytes.length;
        int paddedLength = blockSize * (plaintextLength / blockSize + 1);
        int paddingLength = paddedLength - plaintextLength;
        byte[] paddedData = new byte[paddedLength];
        System.arraycopy(dataBytes, 0, paddedData, 0, plaintextLength);
        for (int i = plaintextLength; i < paddedLength; i++) {
            paddedData[i] = (byte) paddingLength;
        }
        byte[] encryptedBytes = cipher.doFinal(paddedData);
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    public static String decrypt(String data, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(CHARSET));
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        byte[] encryptedBytes = Base64.getDecoder().decode(data);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        int paddingLength = decryptedBytes[decryptedBytes.length - 1];
        int originalLength = decryptedBytes.length - paddingLength;
        byte[] originalBytes = new byte[originalLength];
        System.arraycopy(decryptedBytes, 0, originalBytes, 0, originalLength);
        return new String(originalBytes, CHARSET);
    }
}

在该示例中,我们首先计算出明文缺少的字节数,在原始数据后面加上缺少的字节数目的字节,在解密时从后面截去对应的字节数。

四、结论

通过以上的阐述,我们可以了解到AES、CBC和PKCS5Padding在加密和解密过程中分别扮演了什么样的角色,如何相互配合,从而保证信息加密的安全性。我们可以根据这些知识来编写安全性更高的程序,并在实际应用中使用。

原创文章,作者:PMKLG,如若转载,请注明出处:https://www.506064.com/n/333764.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
PMKLGPMKLG
上一篇 2025-02-01 13:34
下一篇 2025-02-01 13:34

相关推荐

  • 使用Vue实现前端AES加密并输出为十六进制的方法

    在前端开发中,数据传输的安全性问题十分重要,其中一种保护数据安全的方式是加密。本文将会介绍如何使用Vue框架实现前端AES加密并将加密结果输出为十六进制。 一、AES加密介绍 AE…

    编程 2025-04-29
  • AES加密解密算法的C语言实现

    AES(Advanced Encryption Standard)是一种对称加密算法,可用于对数据进行加密和解密。在本篇文章中,我们将介绍C语言中如何实现AES算法,并对实现过程进…

    编程 2025-04-29
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • Python输入输出详解

    一、文件读写 Python中文件的读写操作是必不可少的基本技能之一。读写文件分别使用open()函数中的’r’和’w’参数,读取文件…

    编程 2025-04-25
  • nginx与apache应用开发详解

    一、概述 nginx和apache都是常见的web服务器。nginx是一个高性能的反向代理web服务器,将负载均衡和缓存集成在了一起,可以动静分离。apache是一个可扩展的web…

    编程 2025-04-25
  • 详解eclipse设置

    一、安装与基础设置 1、下载eclipse并进行安装。 2、打开eclipse,选择对应的工作空间路径。 File -> Switch Workspace -> [选择…

    编程 2025-04-25
  • Python安装OS库详解

    一、OS简介 OS库是Python标准库的一部分,它提供了跨平台的操作系统功能,使得Python可以进行文件操作、进程管理、环境变量读取等系统级操作。 OS库中包含了大量的文件和目…

    编程 2025-04-25
  • git config user.name的详解

    一、为什么要使用git config user.name? git是一个非常流行的分布式版本控制系统,很多程序员都会用到它。在使用git commit提交代码时,需要记录commi…

    编程 2025-04-25

发表回复

登录后才能评论