AES算法基础

AES算法是对称加密中的算法之一,常用的对称加密算法(加密和解密使用同一个秘钥)还有DES,IDEA等。现在主流的算法是AES算法。

他们之间的区别如下:

算法秘钥长度工作模式填充模式
DES56/64ECB/CBC.....NoPadding.........
AES(主流)128/192/256ECB/CBC......NoPadding/PKCS5Padding......
IDEA128ECBPKCS5Padding......

AES有两种常用工作模式,分别是ECB和CBC。

注:工作模式不同,密钥的长度不同

       CBC模式下允许出现随机内容

        AES对长度有着绝对的要求

ECB工作模式

ECB模式下的加密过程:

ECB模式是最简单的模式,固定的明文生成固定的密文。

1、定义要加密的原文和秘钥

在ECB工作模式下,这里的秘钥是128位,16字节,且原文和秘钥均为字节数组类型的(getBytes)

2、进行真正的加密操作

(1)、创建加密对象:

Cipher  cipher  =  Cipher.getInstance()     

==>里面传入参数:A/B/C;算法名/工作模式/填充模式

(2)、根据字节内容(在上面的步骤定义的秘钥key),恢复秘钥对象

Secretkey  sk  =  new  Secretkey (A,B);

参数A:秘钥key                参数B:算法名

(3)、初始化秘钥并设置加密模式

cipher.init(A,B);

参数A:加密模式,Cipher类中定义的常量                参数B:恢复的秘钥对象(sk)

(4)、根据原文内容(字节形式)进行加密

Cipher.doFinal(A)

参数A:传入要加密的明文内容

实际代码案例:

// AES + ECB
public class AESDemon01 {
	public static void main(String[] args) throws GeneralSecurityException {
		// 原文:
		String message = "天生我材必有用飞流直下三千尺";
		System.out.println("Message(原始信息): " + message);

		// 128位密钥 = 16 bytes Key:
		byte[] key = "1234567890abcdef".getBytes();

		// 加密:
		byte[] data = message.getBytes();
		byte[] encrypted = encrypt(key, data);
		System.out.println("Encrypted(加密内容): " + Base64.getEncoder().encodeToString(encrypted));

		// 解密:
		byte[] decrypted = decrypt(key, encrypted);
		System.out.println("Decrypted(解密内容): " + new String(decrypted));
	}

	
	
	// 加密:
	public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
		// 创建密码对象,需要传入算法/工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

		// 根据key的字节内容,"恢复"秘钥对象
		SecretKey secretKey = new SecretKeySpec(key, "AES");
		
		// 初始化秘钥:设置加密模式ENCRYPT_
		cipher.init(Cipher.ENCRYPT_MODE,secretKey );

		// 根据原始内容(字节),进行加密
		return cipher.doFinal(input);
//		At7FZSwCFfk69p8Anw9tWA==
//		a8MJCOSonzcdWEZ6suh6kLbiHdf5K1SQxuwZHrUJNdM=
	}
}

解密过程:

解密过程的操作和加密过程完全一致,只是在最后做doFinal()操作时,将参数改为传入的已经加密的内容(密文,且是字节形式)

eg:

/ 解密:
	public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
		// 创建密码对象,需要传入算法/工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		
		// 根据key的字节内容,"恢复"秘钥对象
		SecretKey secretKey = new SecretKeySpec(key, "AES");
		
		// 初始化秘钥:设置解密模式DECRYPT_MODE
		cipher.init(Cipher.DECRYPT_MODE, secretKey);
		
		// 根据原始内容(字节),进行解密
		return cipher.doFinal(input);
	}

CBC工作模式

在这种工作模式下会有一个随机数IV,相同的明文会产生不同的随机数不同,所以加密形成的密文也不同,这就使得安全性有了提高。

与EBC模式进行区别:

在加密的过程中,进行初始化时:

cipher.initiate(A,B,C);

参数A:加密模式        参数B:秘钥        参数C:IV参数

IV参数是在初始化之前进行定义的。具体过程如下:

(1)首先使用核心类库中的方法:

SecureRandom random = SecureRandom.getInstanceStrong();

byte[]  b= random.generateSeed(16);

这里是用random随机数产生的IV随机数,参数中的16代表生成16个字节的随机数。

(2)将随机数封装成 IvParameterSpec 对象

IvParameterSpec  IV  =  new  IvParameterSpec(b);

其他过程与流程与ECB模式的流程基本一致,CBC模式下的IV不需要保密,把IV随机数和密文一起返回。

注:CBC模式下的秘钥长度为256位,也就是32字节

具体代码案例如下:

public class AESCBCDemon {
	public static void main(String[] args) throws Exception {
        // 原文:
        String message = "天动万象";
        System.out.println("Message(原始信息): " + message);
        
        // 256位密钥 = 32 bytes Key:
        byte[] key = "1234567890abcdef1234567890987654".getBytes();
        
        // 加密:
        byte[] data = message.getBytes();
        byte[] encrypted = encrypt(key, data);
        System.out.println("Encrypted(加密内容): " + 
				Base64.getEncoder().encodeToString(encrypted));
        
        // 解密:
        byte[] decrypted = null;
        System.out.println("Decrypted(解密内容): " + new String(decrypted));
    }

    // 加密:
    public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        // 设置算法/工作模式CBC/填充
    	Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    	
    	// 恢复秘钥对象
    	SecretKey secretKey = new SecretKeySpec(key, "AES");
        
        // CBC模式需要生成一个16 bytes的initialization vector:
    	SecureRandom random = SecureRandom.getInstanceStrong();
    	byte[] iv = random.generateSeed(16);
    	System.out.println(Arrays.toString(iv));
    	
    	IvParameterSpec ivp = new IvParameterSpec(iv);
    	System.out.println(ivp);
        
        // 初始化秘钥:操作模式、秘钥、IV参数
    	cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivp);
    	System.out.println("-----------");
        
        // 加密
    	byte[] bu = cipher.doFinal(input);
    	System.out.println("------" + bu);
        
        // IV不需要保密,把IV和密文一起返回:
        return join(iv, bu);
    }

    // 解密:
    public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        // 把input分割成IV和密文:
        byte[] iv = new byte[16];
        byte[] data = new byte[input.length-iv.length];
        
        // 解密:
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKey secretKey = new SecretKeySpec(key, "AES");
        IvParameterSpec ivp = new IvParameterSpec(iv);
       
        // 初始化秘钥:操作模式、秘钥、IV参数
        cipher.init(Cipher.DECRYPT_MODE, secretKey,ivp);
        
        // 解密操作
        return cipher.doFinal(data);
    }
    
    // 合并数组
    public static byte[] join(byte[] bs1, byte[] bs2) {
    	byte[] newbuf = new byte[bs1.length+bs2.length];
    	System.arraycopy(bs1, 0, newbuf, 0, bs1.length);
    	System.arraycopy(bs2, 0, newbuf, bs1.length, bs2.length);
       
        return newbuf;
    }

}

 

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值