常用的对称加密算法

本文介绍了对称加密算法的基本概念,强调了其在信息安全中的重要性。重点讲解了AES加密算法,包括ECB和CBC两种工作模式。ECB模式简单但安全性较低,而CBC模式引入初始化向量提高安全性。文中提供了Java代码示例,展示了如何使用AES进行加密和解密操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

随着互联网的飞速发展,信息安全变得尤为重要,在这里我给大家介绍几种常用的对称加密算法以及AES算法不同模式的使用案例。


一、对称加密算法简介

对称加密算法就是传统的用一个密钥进行加密和解密。例如:我们常用的WinZip和WinRAR对压缩包的加密和解密,就是使用的对称加密算法。

特点:算法公开,计算量小,加密速度快,加密效率搞。
不足点:交易双方都使用相同的钥匙,安全性得不到保证。

  1. 对称加密时加密/解密都必须使用相同的密钥
  2. 明文:指没有任何经过加密的信息
  3. 加密算法:对明文进行替换,变形等操作的步骤规则
  4. 密钥:明文转换成密文或将密文转换成明文的算法中输入的参数
  5. 密文:明文经过加密算法处理后的输出
  6. 解密算法:加密算法的逆向操作

在软件开发中,常见的对称加密算法有:

算法密钥长度工作模式填充模式
DES54/64ECB/CBC/PCBC/CTR/…NoPadding/PKCS5Padding
AES128/192/256ECB/CBC/PCBC/CTR/…NoPadding/PKCS5Padding/PKCS7Padding
IDEA128ECBPKCS5Padding/PKCS7Padding

密钥长度直接决定加密的强度,而工作模式和填充模式可以看成是对称加密算法的参数和格式选择。
最后,值得注意的是,DES算法因密钥太短,很容易被破解,所以现在已经不安全不怎么使用了。

二、AES加密

AES加密是目前应用最广泛的加密算法。比较常用的工作模式是ECBCBC

1.ECB模式

最基本的加密模式,也就是通常理解的加密,相同的明文将永远加密成相同的密文,无初始向量,容易受到密码本重放攻击,一般情况下很少用。

使用ECB模式代码如下:

// AES + ECB
public class Work01 {
	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 keySpec = new SecretKeySpec(key, "AES");
		// 初始化秘钥:设置加密模式ENCRYPT_
		cipher.init(cipher.ENCRYPT_MODE, keySpec);
		// 根据原始内容(字节),进行加密
		return cipher.doFinal(input);
	}

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

我自己定义了两个静态方法封装加密和解密的过程,要使用AES加密算法的ECB模式,得先通过Cipher.getInstance(“AES/ECB/PKCS5Padding”)方法传入算法,工作模式和填充模式参数,得到Cipher对象
再通过SecretKey构造方法传入key算法,得到keySpec对象,再用Cipher.init()方法初始化密钥,其中是加密还是解密就体现在Cipher.init()方法中第一个参数传入的是cipher.ENCRYPT_MODE还是cipher.DECRYPT_MODE,最终返回cipher.doFinal(input)方法,参数是要加密内容的字节数组

注意:密钥必须是16个字节,在实际运用中不会写死密钥。

运行结果如图:
在这里插入图片描述(由于我打印的加密内容做了Bease64编码转成字符串,所以打印出来的不是字节数组。)

2.CBC模式

CBC模式相较于ECB模式更安全,它需要一个随机数作为IV参数,这样对于同一份明文,每次输出都会有不同的密文。
使用CBC模式的代码如下:

//AES + CBC
public class Work02 {
	public static void main(String[] args) throws Exception {
		// 原文:
		String message = "天王盖地虎";
		System.out.println("Message(原始信息): " + message);

		// 256位密钥 = 32 bytes Key:
		byte[] key = "123456789qwertyuiopasdfghjklzxcv".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));
	}

	// 加密:
	@SuppressWarnings("static-access")
	public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
		// 设置算法/工作模式CBC/填充
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

		// 恢复秘钥对象
		SecretKey keySpec = new SecretKeySpec(key, "AES");
		// CBC模式需要生成一个16 bytes的initialization vector:
		SecureRandom sr = SecureRandom.getInstanceStrong();
		byte[] iv = sr.generateSeed(16);
		System.out.println("生成的iv字节数组" + Arrays.toString(iv));
		IvParameterSpec ivps = new IvParameterSpec(iv);
		// 初始化秘钥:操作模式、秘钥、IV参数
		cipher.init(cipher.ENCRYPT_MODE, keySpec, ivps);
		// 加密
		byte[] data = cipher.doFinal(input);
		// IV不需要保密,把IV和密文一起返回:
		return join(iv, 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("解密后的iv字节数组" + Arrays.toString(iv));
		// 解密:
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		IvParameterSpec ivps = new IvParameterSpec(iv);
		SecretKey keySpec = new SecretKeySpec(key, "AES");
		// 初始化秘钥:操作模式、秘钥、IV参数
		cipher.init(Cipher.DECRYPT_MODE, keySpec, ivps);
		// 解密操作
		return cipher.doFinal(data);
	}

	// 合并数组
	public static byte[] join(byte[] bs1, byte[] bs2) {
		byte[] ret = new byte[bs1.length + bs2.length];
		System.arraycopy(bs1, 0, ret, 0, bs1.length);
		System.arraycopy(bs2, 0, ret, bs1.length, bs2.length);
		return ret;
	}
}

观察代码可以发现,与ECB模式不同的地方在于,加密时多生成了一个固定长度为16个字节的SecureRandom随机数iviv作为参数生成了IvParameterSpec对象ivps,在初始化时cipher.init()方法第三个参数放入了ivps。为了解码方便,我还写了一个join()方法,将iv的字节数组和加密后的字节数组合并,由于iv的字节数组长度是固定的,这样在解码时,可以很轻松的提取到加密时使用的iv和加密的字节数组,最终达成解密的效果。
运行结果如图:
在这里插入图片描述


总结

以上就是对称加密算法的基本内容了,我简单介绍了几种常用对称加密算法,以及AES算法不同模式的使用案例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值