基於AES演算法的Android工具類
高階加密標準(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經 被多方分析且廣為全世界所使用。經過五年的甄選流程,高階加密標準由美國國家標準與技術研究院(NIST)於2001年11月26日釋出於FIPS PUB 197,並在2002年5月26日成為有效的標準。2006年,高階加密標準已然成為對稱金鑰加密中最流行的演算法之一。
嚴格地說,AES和Rijndael加密法並不完全一樣(雖然在實際應用中二者可以互換),因為Rijndael加密法可以支援更大範圍的區塊和金鑰 長度:AES的區塊長度固定為128 位元,金鑰長度則可以是128,192或256位元;而Rijndael使用的金鑰和區塊長度可以是32位的整數倍,以128位為下限,256位元為上 限。加密過程中使用的金鑰是由Rijndael金鑰生成方案產生。
截至2006年,針對AES唯一的成功攻擊是旁道攻擊。美國國家安全域性稽核了所有的參與競選AES的最終入圍者(包括Rijndael),認為他們均能夠 滿足美國政府傳遞非機密檔案的安全需要。2003年6月,美國政府宣佈AES可以用於加密機密檔案。這標誌著,由美國國家安全域性NSA批准在最高機密資訊 上使用的加密系統首次可以被公開使用。許多大眾化產品只使用128位金鑰當作預設值;由於最高機密檔案的加密系統必須保證數十年以上的安全性,故推測 NSA可能認為128位太短,才以更長的金鑰長度為最高機密的加密保留了安全空間。
通常破解一個區塊加密系統最常見的方式,是先對其較弱版本(加密迴圈次數較少)嘗試各種攻擊。AES中128位金鑰版本有10個加密迴圈,192位元金鑰 版本有12個加密迴圈,256位元金鑰版本則有14個加密迴圈。至2006年為止,最著名的攻擊是針對AES 7次加密迴圈的128位金鑰版本,8次加密迴圈的192位元金鑰版本,和9次加密迴圈的256位元金鑰版本所作的攻擊。
因此,在當前階段來說,AES加密是非常安全的,因此可以用來對我們的敏感資料進行加密,下面給出android平臺下AES加密的程式碼實現。
package com.example.androiddemo;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import android.annotation.SuppressLint;
/**
*
* @ClassName : com.example.androiddemo.AESUtil
* @Description: AES加密解密工具類
* @author zhaokaiqiang
* @date 2014-11-15 上午10:08:44
*
*/
@SuppressLint("TrulyRandom")
public class AESUtil {
private final static String HEX = "0123456789ABCDEF";
private final static int JELLY_BEAN_4_2 = 17;
/**
* 加密
*
* @param key
* 金鑰
* @param src
* 加密文字
* @return
* @throws Exception
*/
public static String encrypt(String key, String src) throws Exception {
byte[] rawKey = getRawKey(key.getBytes());
byte[] result = encrypt(rawKey, src.getBytes());
return toHex(result);
}
/**
* 解密
*
* @param key
* 金鑰
* @param encrypted
* 待揭祕文字
* @return
* @throws Exception
*/
public static String decrypt(String key, String encrypted) throws Exception {
byte[] rawKey = getRawKey(key.getBytes());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
/**
* 獲取256位的加密金鑰
*
* @param seed
* @return
* @throws Exception
*/
@SuppressLint("TrulyRandom")
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = null;
// 在4.2以上版本中,SecureRandom獲取方式發生了改變
if (android.os.Build.VERSION.SDK_INT >= JELLY_BEAN_4_2) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
sr.setSeed(seed);
// 256 bits or 128 bits,192bits
kgen.init(256, sr);
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
/**
* 真正的加密過程
*
* @param key
* @param src
* @return
* @throws Exception
*/
private static byte[] encrypt(byte[] key, byte[] src) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(src);
return encrypted;
}
/**
* 真正的解密過程
*
* @param key
* @param encrypted
* @return
* @throws Exception
*/
private static byte[] decrypt(byte[] key, byte[] encrypted)
throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static byte[] toByte(String hexString) {
int len = hexString.length() / 2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
16).byteValue();
return result;
}
public static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2 * buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
}