对称加密算法AES+ECB(CBC)

目录

什么是对称加密算法?

步骤

CBC和ECB的区别

(1)AES + ECB 

(2)AES + CBC


什么是对称加密算法?

对称加密算法是一种加密技术,使用相同的密钥(称为对称密钥)同时进行加密和解密。在对称加密中,发送方使用密钥将原始数据转换为加密数据,接收方使用相同的密钥将加密数据解密成原始数据。

对称加密算法的特点是算法公开、计算量小、加密速度快、加密效率高。

不足之处是,交易双方都使用同样钥匙,安全性得不到保证。

由于发送方和接收方需要共享相同的密钥,因此在安全传输密钥的过程中可能存在风险。此外,如果有第三方获取了密钥,他们可以轻松地解密通信内容。因此,在某些情况下,对称加密算法可能不适用,需要使用非对称加密算法。

步骤

  1. 生成密钥:根据选定的算法,生成一个合适的密钥。密钥的长度和安全性是根据需要来确定的。
  2. 加密:将明文数据按照算法规定的方式进行加密。加密过程中使用的密钥必须与解密过程中使用的密钥相同。
    1. 1.创建密码对象,需要传入算法/工作模式/填充模式

    2. 2.根据key的字节内容,"恢复"秘钥对象

    3. 3.初始化秘钥:设置加密模式ENCRYPT_

    4. 4.根据原始内容(字节),进行加密

    5. //CBC多了一个16字节的随机数

  3. 解密:使用相同的密钥对密文进行解密,还原为明文数据。
    1. 1.创建密码对象,需要传入算法/工作模式/填充模式

    2. 2.根据key的字节内容,"恢复"秘钥对象

    3. 3.初始化秘钥:设置解密模式DECRYPT_MODE

    4. 4.根据原始内容(字节),进行解密

 

CBC和ECB的区别

  • ECB模式:它需要一个固定长度的密钥,固定的明文会生成固定的密文。是不安全的。
  • CBC模式:它需要一个随机数作为IV参数,这样对于同一份明文,每次生成的密文都不同。更高的安全性。

错误传播:

  • ECB模式:如果一个数据块发生错误,只会影响该数据块本身,不会影响其它数据块。
  • CBC模式:如果一个数据块发生错误,该错误将传播到后续的所有数据块。这可能导致解密时的错误恢复问题。

综上所述,CBC模式相对于ECB模式更安全,因为它提供了更好的混淆性和错误传播。因此,在实际应用中,推荐使用CBC模式来保护数据的机密性。

(1)AES + ECB 

import java.security.GeneralSecurityException;
import java.util.Base64;

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

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

		// 128位密钥 = 16 bytes Key:
		byte[] key = "1234567890abcdef".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 {
		//1.创建密码对象,需要传入算法/工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

		//2.根据key的字节内容,"恢复"秘钥对象
		SecretKey key2  = new SecretKeySpec(key, "AES");
		
		//3.初始化秘钥:设置加密模式ENCRYPT_
		cipher.init(Cipher.ENCRYPT_MODE, key2);
		
		//4.根据原始内容(字节),进行加密
		return cipher.doFinal(input);
	}

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

(2)AES + CBC

import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

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

// AES + CBC(多了一个16字节的随机数)
public class Main {
	public static void main(String[] args) throws Exception {
        // 原文:
		String message = "天生我材必有用飞流直下三千尺";
        byte[] data = message.getBytes();
        System.out.println("Message(原始信息): " + message);
        
        // 256位密钥 = 32 bytes Key:
        byte[] key = "weos28eud8s8dueiwudujeusj2bd983j".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 {
        // 设置算法/工作模式CBC/填充
    	Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    	// 恢复秘钥对象
        SecretKey key2 = new SecretKeySpec(key, "AES");
        // CBC模式需要生成一个16 bytes的initialization vector:
        SecureRandom random = SecureRandom.getInstanceStrong();
        byte[] by = random.generateSeed(16);
        //随机数封装成IvParameterspec参数对象
        IvParameterSpec iv = new IvParameterSpec(by);
        System.out.println("随机数"+Arrays.toString(by));
        // 初始化秘钥:操作模式、秘钥、IV参数
        cipher.init(Cipher.ENCRYPT_MODE, key2,iv);
        // 加密
        byte[] data = cipher.doFinal(input);
        // IV不需要保密,把IV和密文一起返回:
        return join(by, data);
    }

    // 解密:
    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");
        SecretKey key2 = new SecretKeySpec(key, "AES"); 
        IvParameterSpec ivp = new IvParameterSpec(iv);
        // 初始化秘钥:操作模式、秘钥、IV参数
        cipher.init(Cipher.DECRYPT_MODE, key2,ivp);
        // 解密操作
        return cipher.doFinal(data);
    }
    
    // 合并数组
    public static byte[] join(byte[] bs1, byte[] bs2) {
        byte[] by = new byte[bs1.length+bs2.length];
        System.arraycopy(bs1, 0, by, 0, bs1.length);
        System.arraycopy(bs2, 0, by, bs1.length, bs2.length);
        return by;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lcannal

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值