密碼學(xué)中的高級(jí)加密標(biāo)準(zhǔn)(Advanced Encryption Standard,AES)牢贸,又稱(chēng)Rijndael加密法竹观,是美國(guó)聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。這個(gè)標(biāo)準(zhǔn)用來(lái)替代原先的DES潜索,已經(jīng)被多方分析且廣為全世界所使用臭增。經(jīng)過(guò)五年的甄選流程,高級(jí)加密標(biāo)準(zhǔn)由美國(guó)國(guó)家標(biāo)準(zhǔn)與技術(shù)研究院 (NIST)于2001年11月26日發(fā)布于FIPS PUB 197竹习,并在2002年5月26日成為有效的標(biāo)準(zhǔn)誊抛。2006年,高級(jí)加密標(biāo)準(zhǔn)已然成為對(duì)稱(chēng)密鑰加密中最流行的算法之一整陌。
該算法為比利時(shí)密碼學(xué)家Joan Daemen和Vincent Rijmen所設(shè)計(jì)拗窃,結(jié)合兩位作者的名字瞎领,以Rijndael之命名之,投稿高級(jí)加密標(biāo)準(zhǔn)的甄選流程随夸。(Rijdael的發(fā)音近于 “Rhinedoll”)
AES 是一個(gè)新的可以用于保護(hù)電子數(shù)據(jù)的加密算法九默。明確地說(shuō),AES 是一個(gè)迭代的宾毒、對(duì)稱(chēng)密鑰分組的密碼驼修,它可以使用128、192 和 256 位密鑰诈铛,并且用 128 位(16字節(jié))分組加密和解密數(shù)據(jù)乙各。與公共密鑰密碼使用密鑰對(duì)不同,對(duì)稱(chēng)密鑰密碼使用相同的密鑰加密和解密數(shù)據(jù)癌瘾。通過(guò)分組密碼返回的加密數(shù)據(jù)的位數(shù)與輸入數(shù)據(jù)相同觅丰。迭代加密使用一個(gè)循環(huán)結(jié)構(gòu),在該循環(huán)中重復(fù)置換(permutations )和替換(substitutions)輸入數(shù)據(jù)妨退。Figure 1 顯示了 AES 用192位密鑰對(duì)一個(gè)16位字節(jié)數(shù)據(jù)塊進(jìn)行加密和解密的情形妇萄。
對(duì)稱(chēng)密碼體制的發(fā)展趨勢(shì)將以分組密碼為重點(diǎn)。分組密碼算法通常由密鑰擴(kuò)展算法和加密(解密)算法兩部分組成咬荷。密鑰擴(kuò)展算法將b字節(jié)用戶主密鑰擴(kuò)展成r個(gè)子密鑰冠句。加密算法由一個(gè)密碼學(xué)上的弱函數(shù)f與r個(gè)子密鑰迭代r次組成⌒移梗混亂和密鑰擴(kuò)散是分組密碼算法設(shè)計(jì)的基本原則懦底。抵御已知明文的差分和線性攻擊,可變長(zhǎng)密鑰和分組是該體制的設(shè)計(jì)要點(diǎn)罕扎。
AES是美國(guó)國(guó)家標(biāo)準(zhǔn)技術(shù)研究所NIST旨在取代DES的21世紀(jì)的加密標(biāo)準(zhǔn)聚唐。
AES的基本要求是,采用對(duì)稱(chēng)分組密碼體制腔召,密鑰長(zhǎng)度的最少支持為128杆查、192、256臀蛛,分組長(zhǎng)度128位亲桦,算法應(yīng)易于各種硬件和軟件實(shí)現(xiàn)。1998年NIST開(kāi)始AES第一輪分析浊仆、測(cè)試和征集客峭,共產(chǎn)生了15個(gè)候選算法。1999年3月完成了第二輪AES2的分析抡柿、測(cè)試舔琅。2000年10月2日美國(guó)政府正式宣布選中比利時(shí)密碼學(xué)家Joan Daemen 和 Vincent Rijmen 提出的一種密碼算法RIJNDAEL 作為 AES.
AES加密數(shù)據(jù)塊大小最大是256bit,但是密鑰大小在理論上沒(méi)有上限沙绝。AES加密有很多輪的重復(fù)和變換搏明。大致步驟如下:
1. 密鑰擴(kuò)展(KeyExpansion)
2. 初始輪(Initial Round)
3. 重復(fù)輪(Rounds)鼠锈,每一輪又包括:SubBytes、ShiftRows星著、MixColumns购笆、AddRoundKey
4. 最終輪(Final Round),最終輪沒(méi)有MixColumns虚循。
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public abstract class AesHelper {
? ? /**
? ? * 加密
? ? *
? ? * @param content 需要加密的內(nèi)容
? ? * @param salt? ? 加密密碼
? ? * @return
? ? */
? ? public static byte[] encrypt(String content, String salt) {
? ? ? ? try {
? ? ? ? ? ? SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
? ? ? ? ? ? random.setSeed(salt.getBytes());
? ? ? ? ? ? KeyGenerator kgen = KeyGenerator.getInstance("AES");
? ? ? ? ? ? kgen.init(128, random);
? ? ? ? ? ? SecretKey secretKey = kgen.generateKey();
? ? ? ? ? ? byte[] enCodeFormat = secretKey.getEncoded();
? ? ? ? ? ? SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
? ? ? ? ? ? Cipher cipher = Cipher.getInstance("AES");// 創(chuàng)建密碼器
? ? ? ? ? ? byte[] byteContent = content.getBytes("utf-8");
? ? ? ? ? ? cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
? ? ? ? ? ? byte[] result = cipher.doFinal(byteContent);
? ? ? ? ? ? return result; // 加密
? ? ? ? } catch (NoSuchAlgorithmException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (NoSuchPaddingException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (InvalidKeyException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (UnsupportedEncodingException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (IllegalBlockSizeException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (BadPaddingException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return null;
? ? }
? ? /**
? ? * 解密
? ? *
? ? * @param content 待解密內(nèi)容
? ? * @param salt? ? 解密密鑰
? ? * @return
? ? */
? ? public static byte[] decrypt(byte[] content, String salt) {
? ? ? ? try {
? ? ? ? ? ? KeyGenerator kgen = KeyGenerator.getInstance("AES");
? ? ? ? ? ? SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
? ? ? ? ? ? secureRandom.setSeed(salt.getBytes());
? ? ? ? ? ? kgen.init(128, secureRandom);
? ? ? ? ? ? SecretKey secretKey = kgen.generateKey();
? ? ? ? ? ? byte[] enCodeFormat = secretKey.getEncoded();
? ? ? ? ? ? SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
? ? ? ? ? ? Cipher cipher = Cipher.getInstance("AES");// 創(chuàng)建密碼器
? ? ? ? ? ? cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
? ? ? ? ? ? byte[] result = cipher.doFinal(content);
? ? ? ? ? ? return result; // 加密
? ? ? ? } catch (NoSuchAlgorithmException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (NoSuchPaddingException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (InvalidKeyException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (IllegalBlockSizeException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? } catch (BadPaddingException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return null;
? ? }
? ? public static String bytesToHexString(byte[] src) {
? ? ? ? StringBuffer sb = new StringBuffer();
? ? ? ? for (int i = 0; i < src.length; i++) {
? ? ? ? ? ? String hex = Integer.toHexString(src[i] & 0xFF);
? ? ? ? ? ? if (hex.length() == 1) {
? ? ? ? ? ? ? ? hex = '0' + hex;
? ? ? ? ? ? }
? ? ? ? ? ? sb.append(hex.toUpperCase());
? ? ? ? }
? ? ? ? return sb.toString();
? ? }
? ? public static String encryptToStr(String content, String password){
? ? ? ? return bytesToHexString(encrypt(content,password));
? ? }
? ? public static byte[] decrypt(String content, String keyWord) {
? ? ? ? return decrypt(hexStringToBytes(content), keyWord);
? ? }
? ? public static byte[] hexStringToBytes(String hexString) {
? ? ? ? if (hexString.length() < 1)
? ? ? ? ? ? return null;
? ? ? ? byte[] result = new byte[hexString.length() / 2];
? ? ? ? for (int i = 0; i < hexString.length() / 2; i++) {
? ? ? ? ? ? int high = Integer.parseInt(hexString.substring(i * 2, i * 2 + 1), 16);
? ? ? ? ? ? int low = Integer.parseInt(hexString.substring(i * 2 + 1, i * 2 + 2), 16);
? ? ? ? ? ? result[i] = (byte) (high * 16 + low);
? ? ? ? }
? ? ? ? return result;
? ? }
}
public class TestMain {
? ? public void main(){
? ? ? ? String content = "carl.zhao";
? ? ? ? String Key = "http://www.csdn.net";
? ? ? ? //加密
? ? ? ? String encryptResult = AesHelper.encryptToStr(content, Key);
? ? ? ? //解密
? ? ? ? byte[] decryptResult = AesHelper.decrypt(encryptResult,Key);
? ? ? ? Assert.assertEquals(content, new String(decryptResult));
? ? }
}
輸出結(jié)果:
@@eac7cf4369966a656d1355939632cab1611696f7aed973b20f13e8a0e08f1b2ae51d24b41678e12267cd7d8e549674b0fef081fbc0557ec7a7f1eb37bf28e4645a0f6863dae03c2278ea668b03b50102@@