【Android工具類】DES加密時代的終結者——AES加密算法

ph44 9年前發布 | 3K 次閱讀 Java Android

    轉載請注明出處:http://blog.csdn.net/zhaokaiqiang1992

    在前面的兩篇文章中,我們介紹了DES算法,3DES算法以及他們的Android程序實現,并研究了如何才能實現不同平臺下加密算法的一致性。不過話說 起來,DES算法是在1976年被美國的國家標準局定為聯邦資料的加密標準的,到現在已經接近40年了。我們都知道,在計算機的世界里有一個摩爾定律,就 是每過18個月,計算機的晶體管的數量就會翻一番,對應的計算速度也會翻倍,雖然現在的發展速度有所放緩,但是每過三年左右,計算機的運算速度還是在翻倍 的增長。DES采用的是56的加密密鑰,在計算機計算能力飛速發展的今天,已經不再安全,經過算法優化的暴力破解方式能在一天之內就將DES密鑰破解,因 此,DES加密只推薦使用在加密等級不高的場景中。既然DES加密算法不再安全,那么有沒有更加強大的加密算法呢?當然有!今天給大家介紹的,就是如今被 金融機構等對安全性要求等級很高的機構所廣泛應用的加密算法——AES加密。

    高級加密標準(英語: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加密的代碼實現。

    需要注意的是,在4.2以上的版本中,SecureRandom實例的獲取方式發生了變化,因此為了兼容高版本,添加了版本判斷。

    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));  
    }  
}  </pre> 


 本文由用戶 ph44 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!