AES加密算法

版权声明:有关于交易的部分,如果有使用blog的策略,盈亏自负。https://blog.csdn.net/ydonghao2 https://blog.csdn.net/ydonghao2/article/details/11060251

           1977年l月数据加密标准DES(Data Encryption Standard)正式向社会公布,它是世界上第一个公认的实用分组密码算法标准。但DES在经过20年的实践应用后,现在已被认为是不可靠的。1997年1月2日美国国家标准和技术研究所(NSIT)发布了高级加密标准(AES—FIPS)的研发计划,并于同年9月12日正式发布了征集候选算法公告[18],希望确定一种保护敏感信息的公开、免费并且全球通用的算法作为AES,以代替DES。在征集公告中,NSIT对算法的基本要求是:算法必须是私钥体制的分组密码,支持128位分组长度和128、192、256 bits密钥长度。

        经过三轮遴选,Rjindael最终胜出。2000年10月2日,NIST宣布采用Rjindael算法作为新一代高级加密标准。2001年11月26日联邦信息处理标准出版社发布了正式的AES标准即FIPS PUBS 197,其中制定的标准生效时间为2002年5月26日。

        Rnjidael算法是一种可变分组长度和密钥长度的迭代型分组密码,它的分组长度和密钥长度均可独立地指定为128、192、256 bits,它以其安全性和多方面的优良性能,成为AES的最佳选择。Rjindael算法能抵抗现在的所有己知密码攻击,它在广泛的计算环境中的硬件和软件实现性能都表现得非常优秀,它的密钥建立时间极短且灵活性强,它极低的内存要求使其非常适合在存储器受限的环境中使用,并且表现出很好的性能[19]

 

        算法的实现方案:目前AES算法 实现研究主要分为软件实现和硬件实现两个方向。软件实现是在微机上的编程实现,它具有实现容易、可移植性强、成本低廉、易于升级等优点;它的缺点是需要庞大的操作系统和大量硬件资源的支持。由于通用CPU主频的不断提高,现在的软件实现也能达到相当高的速度。

AES的实现算法的Java细节如下表所示:

AES算法

算法

密钥长度

密钥长度默认值

工作模式

填充方式

备注



AES

128、

192、

256


128

ECB、CBC、PCBC、

CTR、CTS、CFB、

CFB8至CFB128、

OFB、OFB8OFB128

NoPadding、

PKCS5Padding、

ISO1012Padding

Java 6实现若使用256位密

钥需要获得无政策限制文件

(Unlimited Strength 

Jurisdiction Policy Files)

同上

同上

同上

PKCS7Padding、

ZeroBytePadding

Bouncy Castle实现


AESCoder.java
/*
 * Copyright 2013 WeCode authors
 * 
 *  Licensed under the WeCode, Version 1.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License from ydonghao2@gmail.com
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.wecode.security.algorithes;

import java.security.Key;

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

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

/**
 * AES安全编码组件,Bouncy Castle 256字长密钥
 * 
 * @author ydonghao2
 * @version 2.0 使用Commons Codec提供Base64算法对密钥进行封装和解包
 * 
 */

public abstract class AESCoder {
	// 密钥算法
	public static final String KEY_ALGORITHM = "AES";
	/**
	 * 加密/解密算法 /工作方式 / 填充方式 Bouncy Castle支持PKCS7Padding填充方式
	 */
	public static final String CIPTHER_ALGORITHM = "AES/ECB/PKCS7Padding";

	/**
	 * 转换密钥
	 * 
	 * @param key二进制密钥
	 * @return Key 密钥
	 * @throws Exception
	 */
	private static Key toKey(byte[] key) throws Exception {
		// 实例化AES密钥材料
		SecretKey secretKey = new SecretKeySpec(key, KEY_ALGORITHM);
		return secretKey;
	}

	/**
	 * 解密
	 * 
	 * @param data
	 *            待解密数据
	 * @param key
	 *            密钥
	 * @return byte[]解密数据
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
		// 还原密钥
		Key k = toKey(key);
		/**
		 * 实例化
		 * 
		 */
		Cipher cipher = Cipher.getInstance(CIPTHER_ALGORITHM, "BC");
		// 初始化
		cipher.init(Cipher.DECRYPT_MODE, k);
		// 执行操作
		return cipher.doFinal(data);
	}

	/**
	 * 解密
	 * 
	 * @param data
	 *            待解密数据
	 * @param key
	 *            密钥
	 * @return byte[]解密数据
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] data, String key) throws Exception {
		return decrypt(data, getKey(key));
	}

	/**
	 * 加密
	 * 
	 * @param data
	 *            待加密数据
	 * @param key
	 *            密钥
	 * @return byte[] 加密数据
	 * @throws Exception
	 */
	public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
		// 还原密钥
		Key k = toKey(key);
		/**
		 * 实例化
		 */
		Cipher cipher = Cipher.getInstance(CIPTHER_ALGORITHM, "BC");
		// 初始化,设置为加密模式
		cipher.init(Cipher.ENCRYPT_MODE, k);
		// 执行操作
		return cipher.doFinal(data);
	}

	/**
	 * 加密
	 * 
	 * @param data
	 *            待加密数据
	 * @param key
	 *            密钥
	 * @return byte[] 加密数据
	 * @throws Exception
	 */
	public static byte[] encrypt(byte[] data, String key) throws Exception {
		return encrypt(data, getKey(key));
	}

	/**
	 * 生成密钥
	 * 
	 * @return byte[] 二进制密钥
	 * @throws Exception
	 */
	public static byte[] initKey() throws Exception {
		// 实例化
		KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
		// AES要求密钥长度为256位
		kg.init(256);
		// 生成密钥
		SecretKey secretKey = kg.generateKey();
		// 获取密钥的二进制编码形式
		return secretKey.getEncoded();
	}

	/**
	 * 初始化密钥 
	 * @return String Base64编码密钥
	 * @throws Exception
	 */
	public static String initKeyString() throws Exception {
		return Base64.encodeBase64String(initKey());
	}

	/**
	 * 获取密钥
	 * @param key 密钥
	 * @return byte[] 密钥
	 * @throws Exception
	 */
	public static byte[] getKey(String key) throws Exception {
		return Base64.decodeBase64(key);
	}
	
	/**
	 * 摘要处理
	 * @param data 待摘要数据
	 * @return 摘要字符串
	 */
	public static String shaHex(byte[] data) {
		return DigestUtils.md5Hex(data);
	}
	
	/**
	 * 验证
	 * @param data 待摘要数据
	 * @param messageDigest 摘要字符串
	 * @return 验证结果
	 */
	public static boolean validate(byte[] data, String messageDigest) {
		return messageDigest.equals(shaHex(data));
	}
}

关于本系统的AES具体实现主要代码和说明如下:

         public abstract classAESCoder extends java.lang.Object

AES安全编码组件,Bouncy Castle 256字长密钥

版本: 2.0 使用Commons Codec提供Base64算法对密钥进行封装和解包

密钥算法

这里指定我们在此次用的密钥算法,方便后面的SecretKey的实例化。

      

public static final String KEY_ALGORITHM = "AES";

        加密/解密算法 /工作方式 / 填充方式 ,Java 6支持PKcs5Padding填充方式,Bouncy Castle支持PKCS7Padding填充方式,本系统采用Bouncy CastlePKCS7Padding方式

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

转换密钥

参数:

        key- 二进制密钥,

返回:

        Key- 密钥。

抛出:

        java.lang.Exception

        SecretKey在javax.crypto.SecretKey包中。SecretKey接口是对称密钥顶层接口。DES、AES等多种对称密码算法密钥均可通过该接口提供。通常使用的SecretKey接口的实现类SecretKeySpec(javax.crypto.spec.SecretkeySpec)。本系统这里使用SecretKey是进行密钥转换,将二进制的key密钥转换成Key类型的密钥。

      

private static Key toKey(byte[] key) throws Exception {
             // 实例化AES密钥材料
             SecretKey secretKey = new SecretKeySpec(key,KEY_ALGORITHM);
             return secretKey;
      }

解密方法

参数:

        data- 待解密数据

        key- 密钥

返回:

        byte[]解密数据

抛出:

        java.lang.Exception

       Cipher类是一个引擎类,它通过getInstance()工厂方法来实例化对象。此处通过上面的CIPTHER_ALGORITHM说明:使用的算法是AES算法,工作模式是ECB,填充方式是PKCS7Padding。不同的算法支持不同的工作模式及填充方式。“BC”是指Bouncy Castle。

Cipher中有着了如下两个常量:

//用于将Cipher对象进行初始化为解密常量。

       public final static intDECRYPT_MODE;

//用于将Cipher对象初始化为加密模式常量。

       public final static intENCRYPT_MODE;

通过这两个常量来完成用于加密或是解密的初始化。

      init(Cipher.DECRYPT_MODE,k)则是运用了DECRYPT_MODE变量初始化了解密算法。

此次的解密操作不需要多次更新数据,因此可以直接执行public final byte[] doFinal(byte[]input),将解密的数据保存在data中。

     

 public static byte[] decrypt(byte[] data, byte[] key) throwsException {
             // 还原密钥
             Key k = toKey(key);
             Cipher cipher = Cipher.getInstance(CIPTHER_ALGORITHM,"BC");
             // 初始化
             cipher.init(Cipher.DECRYPT_MODE, k);
             // 执行操作
             return cipher.doFinal(data);
      }

解密方法

参数:

        data- 待解密数据

        key- 密钥

返回:

        byte[]解密数据

抛出:

java.lang.Exception

这个重载方法建的目的是为了在网络中传输密钥,在后面的加密方法中也有同样的重载方法所以在后面不再累述。

      

public static byte[] decrypt(byte[] data, String key) throwsException {
             return decrypt(data, getKey(key));
      }

加密方法

参数:

       data- 待加密数据

       key- 密钥

返回:

      byte[]加密数据

抛出:

     java.lang.Exception

     init(Cipher.ENCRYPT_MODE,k)则是运用了ENCRYPT_MODE变量初始化了加密算法。

此次的加密操作不需要多次更新数据,因此可以直接执行public final byte[] doFinal(byte[]input),将加密的数据保存在data中。

      

public static byte[] encrypt(byte[] data, byte[] key) throwsException {
             // 还原密钥
             Key k = toKey(key);
             Cipher cipher = Cipher.getInstance(CIPTHER_ALGORITHM,"BC");
             // 初始化,设置为加密模式
             cipher.init(Cipher.ENCRYPT_MODE, k);
             // 执行操作
             return cipher.doFinal(data);
      }

 

生成密钥

返回:

        byte[]二进制密钥

抛出:

        java.lang.Exception      

在这里本系统AES要求密钥长度为256位。KeyGenerator类用来生成密钥。称为秘密密钥生成器。KeyGenerator类通过如下方法获得实例化:

   

  public static final KeyGeneratorgetInstance(String algorithm)
     返回生成指定算法的秘密密钥的KeyGenerator对象。
      public static byte[] initKey() throws Exception {
             // 实例化
             KeyGenerator kg =KeyGenerator.getInstance(KEY_ALGORITHM);
             kg.init(256);
             // 生成密钥
             SecretKey secretKey = kg.generateKey();
             // 获取密钥的二进制编码形式
             return secretKey.getEncoded();
       }

AESCoderTest.java,测试AESCoder.java封装类

/*
 * Copyright 2013 WeCode authors
 * 
 *  Licensed under the WeCode, Version 1.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License from ydonghao2@gmail.com
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.wecode.security.algorithes;

import static org.junit.Assert.*;
import org.apache.commons.codec.binary.Base64;
import org.junit.Test;
/**
 * AES安全组件校验
 * @author ydonghao2
 * @version 2.0
 */
public class AESCoderTest {
	/**
	 * 测试
	 */
	
	//@Test
	public static void main(String[] args) throws Exception {
		String inputStr = "AES";
		byte[] inputData = inputStr.getBytes();
		System.err.println("原文:" + inputStr);
		//初始化密钥
		byte[] key = AESCoder.initKey();
		System.err.println("密钥:" + Base64.encodeBase64String(key));
		//加密
		inputData = AESCoder.encrypt(inputData, key);
		System.out.println("加密后:" + Base64.encodeBase64String(inputData));
		//解密
		byte[] outputData = AESCoder.decrypt(inputData, key);
		String outputStr = new String(outputData);
		System.out.println("解密后:" + outputStr);
		//校验
		assertEquals(inputStr, outputStr);
	}
}



阅读更多

扫码向博主提问

Tal.Yuan

非学,无以致疑;非问,无以广识
去开通我的Chat快问

没有更多推荐了,返回首页