AES算法的两种工作模式

目录

一、AES算法描述:

二、不同工作模式的算法实现

ECB模式

2.1、加密 encrypt(key,input)   传入明文

2.2、解密decrypt(key,input)  传入密文

2.3、main主函数调用

结果展示

CBC模式

3.1、加密 encrypt(key,input)   传入明文

3.2、合并数组: join(byte1,byte2) 

3.3、解密decrypt(key,input)  传入密文

3.4、main主函数调用 

结果展示


一、AES算法描述:

它是对称加密算法的一种:通过调用两种算法方法

        encrypt(key,messsage)------进行加密

        decrypt(key,message) ------进行解密

AES的明文分组长度为128位(16字节),

密钥:长度可以为128位(16字节)、192位(24字节)、256位(32字节)

    注意点:密钥必须是相应的字节数【多了少了都会报错】

根据密钥长度的不同,AES分为AES-128、AES-192、AES-256三种。

工作模式:ECB/CBC

填充模式:NOPadding/PKCS5Padding

二、不同工作模式的算法实现

ECB模式

简述:是最简单的AES加密模式,它需要一个固定长度的密钥

        特点:固定的明文会生成固定的密文
代码:完成加密和解密操作

加密和解密操作类似,

2.1、加密 encrypt(key,input)   传入明文

第一步:创建Cipher对象,需要传入参数,格式为:【算法名/工作模式/填充模式】

第二步:根据key的字节内容,“恢复”秘钥对象即:SecreKey实例 【第二个参数:传入算法名称 】

第三步:初始化秘钥 init()方法  设置秘钥模式为:【ENCRYPT_MODE】

第四步:根据原始字节内容(字节),进行加密:执行doFinal()方法

第五步:返回结果【得到密文】

public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
	
	Cipher  cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

	SecretKey keyspec = new SecretKeySpec(key, "AES");
	
    cipher.init(Cipher.ENCRYPT_MODE, keyspec);

	return cipher.doFinal(input);
}

2.2、解密decrypt(key,input)  传入密文

第一步:创建Cipher对象,需要传入参数,格式为:【算法名/工作模式/填充模式】

第二步:根据key的字节内容,“恢复”秘钥对象 即:SecreKey实例

第三步:初始化秘钥  init()方法  设置秘钥模式为:【DECRYPT_MODE】

第四步:根据原始字节内容(字节),进行解密 :执行doFinal()方法

第五步:返回结果【得到明文】

public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {

	Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
	
	SecretKey keySpec = new SecretKeySpec(key,"AES");
	
	cipher.init(Cipher.DECRYPT_MODE,keySpec);

	return cipher.doFinal(input);
}

2.3、main主函数调用

注意:密钥是16个字符,32个字节,多了少了都会报错

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));
}

结果展示

CBC模式

相比较ECB模式的一对一进行加密,CBC模式传入了一个随机数作为IV参数,使得同一份明文,产生不同的明文,安全性提高。

3.1、加密 encrypt(key,input)   传入明文

第一步:创建Cipher对象,需要传入参数,格式为:【AES/CBC/填充模式】

第二步:根据key的字节内容,“恢复”秘钥对象即:SecreKey实例 【第二个参数:传入算法名称 】

第三步:生成一个16 字节的随机数

       1.使用SecureRandom的getInstanceStrong()方法产生随机数sr

       2.将1产生的sr调用generateSeed(16)生成16个字节的随机数

       3.将随机数封装成IvParameterSpec对象Iv

第四步:初始化秘钥 init(操作模式、秘钥、IV参数)方法 

         设置秘钥模式为:【ENCRYPT_MODE】

第五步:根据原始字节内容(字节),进行加密:执行doFinal()方法

第六步:返回结果【得到密文】其中IV不要要保密,一起返回

       调用join(iv,data)方法

代码:

public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
  
	Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	
    SecretKey keySpet = new SecretKeySpec(key, "AES");
    
    SecureRandom sr = SecureRandom.getInstanceStrong();
    byte[] iv = sr.generateSeed(16);
    System.out.println(Arrays.toString(iv));
    System.out.println(iv.length);
    IvParameterSpec ivps = new IvParameterSpec(iv);
 
    cipher.init(Cipher.ENCRYPT_MODE, keySpet,ivps);
 
    byte[] data = cipher.doFinal(input);
    return join(iv,data);
}

3.2、合并数组: join(byte1,byte2) 

   由于秘钥是固定长度的,而密文是不定长的。

    所以先存储秘钥,解密时,只需要从数组的第16个位置截取即可获取密文

public static byte[] join(byte[] bs1, byte[] bs2) {
   byte[]  r = new byte[bs1.length+bs2.length];
   System.arraycopy(bs1, 0, r, 0, bs1.length);
   System.arraycopy(bs2, 0, r, bs1.length, bs2.length);
   return r;
}

3.3、解密decrypt(key,input)  传入密文

 第一步:把input分割成IV和密文

       从第16位开始截取

第二步:创建Cipher对象,需要传入参数,格式为:【AES/CBC/填充模式】

第三步:根据key的字节内容,“恢复”秘钥对象即:SecreKey实例 【第二个参数:传入算法名称 】

第四步:将传入的key封装成IvParameterSpec对象Iv

第四步:初始化秘钥 init(操作模式、秘钥、IV参数)方法 

         设置秘钥模为:【DECRYPT_MODE】

第五步:根据原始字节内容(字节),进行加密:执行doFinal()方法

第六步:返回结果【得到明文】

代码:

public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
    // 把input分割成IV和密文:
    byte[] iv = new byte[16];
    byte[] data = new byte[input.length-16];
    
    System.arraycopy(input, 0, iv, 0, 16);
    System.arraycopy(input, 16, data, 0, data.length);
    
    System.out.println(Arrays.toString(iv));
    
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
    IvParameterSpec ivps = new IvParameterSpec(iv);
    cipher.init(Cipher.DECRYPT_MODE, keySpec,ivps);

    return cipher.doFinal(data);
}

3.4、main主函数调用 

注意:秘钥的位数是32个字节【256位】 

public static void main(String[] args) throws Exception {
    // 原文:
    String message = "止于智者";
    System.out.println("Message(原始信息): " + message);
    
    // 256位密钥 = 32 bytes Key:
    byte[] key = "1234567890qwertyuiopasdfgasdfghj".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));
}

结果展示

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值