AES加密技术简介与应用

AES简介

AES最一种常见的对称加密算法,对称加密算法也就是加密和解密用相同的密钥。

具体的加密流程如下图:

下面简单介绍下各个部分的作用与意义:

  • 明文P

没有经过加密的数据。

  • 密钥K

用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取机密数据。

  • AES加密函数

设AES加密函数为E,则 C = E(K, P),其中P为明文,K为密钥,C为密文。也就是说,把明文P和密钥K作为加密函数的参数输入,则加密函数E会输出密文C。

  • 密文C

经加密函数处理后的数据

  • AES解密函数

设AES解密函数为D,则 P = D(K, C),其中C为密文,K为密钥,P为明文。也就是说,把密文C和密钥K作为解密函数的参数输入,则解密函数会输出明文P。

在这里简单介绍下对称加密算法与非对称加密算法的区别。

  • 对称加密算法

加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。

  • 非对称加密算法

加密和解密用的密钥是不同的,这种加密方式是用数学上的难解问题构造的,通常加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。常见的非对称加密算法为RSA、ECC和EIGamal。

AES使用

语言:java

jdk版本:1.7

算法:AEC

密钥长度:32   也就是AES-256

AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,密钥的长度可以使用128位、192位、256位。(每个字节8位)

AES 使用的密钥长度
AES-128 16
AES-192 24
AES-256 32

加密模式:ECB

电码本模式(Electronic Codebook Book (ECB),这种模式是将整个明文分成若干段相同的小段,然后对每一小段进行加密。

    

填充模式:PKCS7Padding

在分组加密算法中,我们首先要将原文进行分组,然后每个分组进行加密,然后组装密文。

其中有一步是分组。如何分组?

假设我们现在的数据长度是24字节,BlockSize是8字节,那么很容易分成3组,一组8字节;

因为加密算法的需求,明文字节必须按照block进行填充对齐,才能方便进行加密运算。

考虑过一个问题没,如果现有的待加密数据不是BlockSize的整数倍,那该如何分组?

例如,有一个17字节的数据,BlockSize是8字节,怎么分组?

我们可以对原文进行填充(padding),将其填充到8字节的整数倍!

加密结果编码方式:Base64

环境准备

JAVA实现“AES/ECB/PKCS7Padding”对称加解密,尤其是 AES256的加解密需要注意两点:

  • 技术出口限制,国内的JDK 默认不支持;

Java本身限制密钥的长度最多128位,而AES256需要的密钥长度是256位,因此需要到Java官网上下载一个Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files。

解决出口限制问题,下载以下两个包替换jdk安装路径下: jre\lib\security 的同名文件

JDK8 jar包下载地址:

http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

JDK7 jar包下载地址:

http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html 

JDK6 jar包下载地址:

http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

把里面的两个jar包:local_policy.jar 和 US_export_policy.jar 替换掉原来jdk安装目录\jre\lib\security 下的两个jar包接可以了

  • PKCS7Padding JAVA默认不支持PKCS7Padding填充模式,需借助第三方提供者。

一般的JRE(如Oracle JRE、OpenJRE)里面只有"AES/ECB/PKCS5Padding"算法,没有"AES/ECB/PKCS7Padding"算法。、故我们需要引入BouncyCastle的库,并给Cipher.getInstance方法传入参数"BC"来指定Java使用这个库里的加/解密算法。

maven工程pom.xml文件中添加以下配置:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15</artifactId>
    <version>1.44</version>
</dependency>

其Jar包的下载地址:http://www.bouncycastle.org/download/bcprov-jdk15on-160.jar

java 代码

import java.security.Security;

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

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class CryptAES {

	public static boolean initialized = false;

	public static final String ALGORITHM = "AES/ECB/PKCS7Padding";

	/**
	 * @param String data 	要被加密的字符串
	 * @param String key 	加/解密要用的长度为32的字节数组(256位)密钥
	 * @return String 		加密后数据
	 * @throws Exception
	 */
	public static String Aes256Encode(String data, String key) {
		initialize();
		byte[] result = null;
		try {
			Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");
			SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
			cipher.init(Cipher.ENCRYPT_MODE, keySpec);
			result = cipher.doFinal(data.getBytes("UTF-8"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return Base64.encodeBase64String(result);
	}

	/**
	 * @param String dataEncode 要被解密的数据(加密后的数据)
	 * @param String key 		加/解密要用的长度为32的字节数组(256位)密钥
	 * @return String 			解密后的字符串
	 */
	public static String Aes256Decode(String dataEncode, String key) {
		initialize();
		String result = null;
		try {
			Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");
			SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
			cipher.init(Cipher.DECRYPT_MODE, keySpec);
			byte[] decoded = cipher.doFinal(Base64.decodeBase64(dataEncode));
			result = new String(decoded, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	public static void initialize() {
		if (initialized)
			return;
		Security.addProvider(new BouncyCastleProvider());
		initialized = true;
	}

	public static void main(String[] args) {
		String key = "12345678901234567890123456789012";
		String data = "abc";

		String aes256Encode = Aes256Encode(data, key);
		System.out.println("加密前数据:" + data);
		System.out.println("加密后数据:" + aes256Encode);
		System.out.println();
		String aes256Decode = Aes256Decode(aes256Encode, key);
		System.out.println("解密前数据:" + aes256Encode);
		System.out.println("解密后数据:" + aes256Decode);
	}

}

输出结果:

加密前数据:abc
加密后数据:q2tSoCKKcbz8RCMso+R2QA==

解密前数据:q2tSoCKKcbz8RCMso+R2QA==
解密后数据:abc

猜你喜欢

转载自blog.csdn.net/loveLifeLoveCoding/article/details/86423161