【工具类】Java实现AES算法 加密和解密

最近在学AES加密,通过网上学习查找资料,封装了一个AES加密解密工具类,说几点:

  1. 算法/模式/填充,这个最好使用"AES/CBC/PKCS5Padding","ECB"在IOS中不安全(网上查找资料得知),不要使用默认填充
  2. 参数密钥要使用16位,不使用"AES/CBC/PKCS5Padding"这种模式是不需要16位密钥的,不过这种安全性比较高,关于安全性可以查找下资料
  3. 这里主要是代码方面,理论方面要查找其他资料(修改版:第一次发的代码,跨域解密不出来,这次的可以了)
  4. 重点)Linux下解密一定要加上SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
      secureRandom.setSeed(secretKey.getBytes());否则会报错,javax.crypto.BadPaddingException: Given final block not properly padded
  5. 重点)使用Base64再包一层是为了防止加密后在变量之间传递丢字符

如果有不对的地方,请大家多指点。微笑 多反馈。


模式/填充参考:

算法/模式/填充16字节加密后数据长度不满16字节加密后长度
AES/CBC/NoPadding16 不支持
AES/CBC/PKCS5Padding3216
AES/CBC/ISO10126Padding3216
AES/CFB/NoPadding16原始数据长度
AES/CFB/PKCS5Padding3216
AES/ECB/NoPadding16不支持
AES/ECB/PKCS5Padding3216
AES/ECB/ISO10126Padding3216
AES/OFB/NoPadding16 原始数据长度
AES/OFB/PKCS5Padding32 16
AES/OFB/ISO10126Padding3216
AES/PCBC/NoPadding16不支持
AES/PCBC/PKCS5Padding3216
AES/PCBC/ISO10126Padding3216
多了一行。。。微笑奋斗

代码如下:


package com.test;

import java.security.SecureRandom;

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

import org.apache.commons.codec.binary.Base64;

/**
 * AES加密和解密工具类
 * 
 * @author zhancy
 */
public class AESUtilFinal {

	// AES密码器
	private static Cipher cipher;

	// 字符串编码
	private static final String KEY_CHARSET = "UTF-8";

	// 算法方式
	private static final String KEY_ALGORITHM = "AES";

	// 算法/模式/填充
	private static final String CIPHER_ALGORITHM_CBC = "AES/CBC/PKCS5Padding";

	// 私钥大小128/192/256(bits)位 即:16/24/32bytes,暂时使用128,如果扩大需要更换java/jre里面的jar包
	private static final Integer PRIVATE_KEY_SIZE_BIT = 128;
	private static final Integer PRIVATE_KEY_SIZE_BYTE = 16;


	public static void main(String[] args) {
		String secretKey = "1234567812345678";
		String text = "test123测试";
		String miwen = encrypt(secretKey, text);
		System.out.println("密文为:" + miwen);
		String mingwen = decrypt(secretKey, miwen);
		System.out.println("明文为:" + mingwen);
	}
	
	/**
	 * 加密
	 * 
	 * @param secretKey
	 *            密钥:加密的规则 16位
	 * @param plainText
	 *            明文:要加密的内容
	 * @return cipherText
	 * 			     密文:加密后的内容,如有异常返回空串:""
	 */
	public static String encrypt(String secretKey, String plainText) {
		if (secretKey.length() != PRIVATE_KEY_SIZE_BYTE) {
			throw new RuntimeException("AESUtil:Invalid AES secretKey length (must be 16 bytes)");
		}
		
		// 密文字符串
		String cipherText = "";
		try {
			// 加密模式初始化参数
			initParam(secretKey, Cipher.ENCRYPT_MODE);
			// 获取加密内容的字节数组
			byte[] bytePlainText = plainText.getBytes(KEY_CHARSET);
			// 执行加密
			byte[] byteCipherText = cipher.doFinal(bytePlainText);
			cipherText = Base64.encodeBase64String(byteCipherText);
		} catch (Exception e) {
			throw new RuntimeException("AESUtil:encrypt fail!", e);
		}
		return cipherText;
	}

	/**
	 * 解密
	 * 
	 * @param secretKey
	 *            密钥:加密的规则 16位
	 * @param cipherText
	 *            密文:加密后的内容,即需要解密的内容
	 * @return plainText 
	 * 		  	      明文:解密后的内容即加密前的内容,如有异常返回空串:""
	 */
	public static String decrypt(String secretKey, String cipherText) {
		if (secretKey.length() != PRIVATE_KEY_SIZE_BYTE) {
			throw new RuntimeException("AESUtil:Invalid AES secretKey length (must be 16 bytes)");
		}
		
		// 明文字符串
		String plainText = "";
		try {
			initParam(secretKey, Cipher.DECRYPT_MODE);
			// 将加密并编码后的内容解码成字节数组
			byte[] byteCipherText = Base64.decodeBase64(cipherText);
			// 解密
			byte[] bytePlainText = cipher.doFinal(byteCipherText);
			plainText = new String(bytePlainText, KEY_CHARSET);
		} catch (Exception e) {
			throw new RuntimeException("AESUtil:decrypt fail!", e);
		}
		return plainText;
	}
	
	/**
	 * 初始化参数
	 * @param secretKey
	 * 			 	密钥:加密的规则 16位
	 * @param mode
	 * 				加密模式:加密or解密
	 */
	public static void initParam(String secretKey, int mode) {
		try {
			// 防止Linux下生成随机key
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
	        secureRandom.setSeed(secretKey.getBytes());
			// 获取key生成器
			KeyGenerator keygen = KeyGenerator.getInstance(KEY_ALGORITHM);
			keygen.init(PRIVATE_KEY_SIZE_BIT, secureRandom);
			
			// 获得原始对称密钥的字节数组
			byte[] raw = secretKey.getBytes();
			
			// 根据字节数组生成AES内部密钥
			SecretKeySpec key = new SecretKeySpec(raw, KEY_ALGORITHM);
			// 根据指定算法"AES/CBC/PKCS5Padding"实例化密码器
			cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
			IvParameterSpec iv = new IvParameterSpec(secretKey.getBytes());
			System.out.println("iv:" + new String(iv.getIV()));
			cipher.init(mode, key, iv);
		} catch (Exception e) {
			throw new RuntimeException("AESUtil:initParam fail!", e);
		}
	}

}


  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
以下是 Java 中使用 AES 加密解密工具类,其中包括了 AES/CBC/PKCS5Padding 算法加密解密方法: ```java import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.util.Base64; public class AESUtil { private static final String ALGORITHM_AES = "AES"; private static final String CIPHER_AES_CBC_PKCS5PADDING = "AES/CBC/PKCS5Padding"; private static final String IV = "0123456789abcdef"; // 16 位 /** * AES 加密 * * @param data 需要加密的数据 * @param key 密钥字符串(16、24 或 32 位) * @return 加密后的字符串 */ public static String encryptByAES(String data, String key) { try { byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM_AES); Cipher cipher = Cipher.getInstance(CIPHER_AES_CBC_PKCS5PADDING); IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8)); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encryptedBytes); } catch (Exception e) { e.printStackTrace(); } return null; } /** * AES 解密 * * @param data 需要解密的数据 * @param key 密钥字符串(16、24 或 32 位) * @return 解密后的字符串 */ public static String decryptByAES(String data, String key) { try { byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM_AES); Cipher cipher = Cipher.getInstance(CIPHER_AES_CBC_PKCS5PADDING); IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8)); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); byte[] encryptedBytes = Base64.getDecoder().decode(data); byte[] decryptedBytes = cipher.doFinal(encryptedBytes); return new String(decryptedBytes, StandardCharsets.UTF_8); } catch (Exception e) { e.printStackTrace(); } return null; } } ``` 使用示例: ```java public static void main(String[] args) { String data = "Hello, world!"; String key = "1234567890123456"; String encryptedData = AESUtil.encryptByAES(data, key); System.out.println("加密后的数据:" + encryptedData); String decryptedData = AESUtil.decryptByAES(encryptedData, key); System.out.println("解密后的数据:" + decryptedData); } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值