Android 和java平臺通用的AES加密解密

g2b4 9年前發布 | 6K 次閱讀 Java Android

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class AES {

static final String algorithmStr = "AES/ECB/PKCS5Padding";

private static final Object TAG = "AES";

static private KeyGenerator keyGen;

static private Cipher cipher;

static boolean isInited = false;

  private static  void init() {
    try { 
            /**為指定算法生成一個 KeyGenerator 對象。
            *此類提供(對稱)密鑰生成器的功能。
            *密鑰生成器是使用此類的某個 getInstance 類方法構造的。
            *KeyGenerator 對象可重復使用,也就是說,在生成密鑰后,
            *可以重復使用同一 KeyGenerator 對象來生成進一步的密鑰。
            *生成密鑰的方式有兩種:與算法無關的方式,以及特定于算法的方式。
            *兩者之間的惟一不同是對象的初始化:
            *與算法無關的初始化
            *所有密鑰生成器都具有密鑰長度 和隨機源 的概念。
            *此 KeyGenerator 類中有一個 init 方法,它可采用這兩個通用概念的參數。
            *還有一個只帶 keysize 參數的 init 方法,
            *它使用具有最高優先級的提供程序的 SecureRandom 實現作為隨機源
            *(如果安裝的提供程序都不提供 SecureRandom 實現,則使用系統提供的隨機源)。
            *此 KeyGenerator 類還提供一個只帶隨機源參數的 inti 方法。
            *因為調用上述與算法無關的 init 方法時未指定其他參數,
            *所以由提供程序決定如何處理將與每個密鑰相關的特定于算法的參數(如果有)。
            *特定于算法的初始化
            *在已經存在特定于算法的參數集的情況下,
            *有兩個具有 AlgorithmParameterSpec 參數的 init 方法。
            *其中一個方法還有一個 SecureRandom 參數,
            *而另一個方法將已安裝的高優先級提供程序的 SecureRandom 實現用作隨機源
            *(或者作為系統提供的隨機源,如果安裝的提供程序都不提供 SecureRandom 實現)。
            *如果客戶端沒有顯式地初始化 KeyGenerator(通過調用 init 方法),
            *每個提供程序必須提供(和記錄)默認初始化。
            */
        keyGen = KeyGenerator.getInstance("AES");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    // 初始化此密鑰生成器,使其具有確定的密鑰長度。
    keyGen.init(128); //128位的AES加密
    try {    
            // 生成一個實現指定轉換的 Cipher 對象。
        cipher = Cipher.getInstance(algorithmStr);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    }
    //標識已經初始化過了的字段
    isInited = true;
}

private static byte[] genKey() {
    if (!isInited) {
        init();  
    }
    //首先 生成一個密鑰(SecretKey),
    //然后,通過這個秘鑰,返回基本編碼格式的密鑰,如果此密鑰不支持編碼,則返回 null。 
    return keyGen.generateKey().getEncoded();
}

private static byte[] encrypt(byte[] content, byte[] keyBytes) {
    byte[] encryptedText = null;
    if (!isInited) { 
        init();
    }
    /**
    *類 SecretKeySpec
    *可以使用此類來根據一個字節數組構造一個 SecretKey,
    *而無須通過一個(基于 provider 的)SecretKeyFactory。
    *此類僅對能表示為一個字節數組并且沒有任何與之相關聯的鑰參數的原始密鑰有用 
    *構造方法根據給定的字節數組構造一個密鑰。
    *此構造方法不檢查給定的字節數組是否指定了一個算法的密鑰。
    */
    Key key = new SecretKeySpec(keyBytes, "AES");
    try {
            // 用密鑰初始化此 cipher。
        cipher.init(Cipher.ENCRYPT_MODE, key);
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }
    try {
            //按單部分操作加密或解密數據,或者結束一個多部分操作。(不知道神馬意思)
        encryptedText = cipher.doFinal(content);
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    }
    return encryptedText;
}

private static byte[] encrypt(String content, String password) {
    try {
        byte[] keyStr = getKey(password);
        SecretKeySpec key = new SecretKeySpec(keyStr, "AES");
        Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr          
        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;
}

private static byte[] decrypt(byte[] content, String password) {
    try {
        byte[] keyStr = getKey(password);
        SecretKeySpec key = new SecretKeySpec(keyStr, "AES");
        Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr           
        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;
}

private static byte[] getKey(String password) {
    byte[] rByte = null;
    if (password!=null) {
        rByte = password.getBytes();
    }else{
        rByte = new byte[24];
    }
    return rByte;
}

/**
 * 將二進制轉換成16進制
 * @param buf
 * @return
 */
public static String parseByte2HexStr(byte buf[]) {
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < buf.length; i++) {
        String hex = Integer.toHexString(buf[i] & 0xFF);
        if (hex.length() == 1) {
            hex = '0' + hex;
        }
        sb.append(hex.toUpperCase());
    }
    return sb.toString();
}

/**
 * 將16進制轉換為二進制
 * @param hexStr
 * @return
 */
public static byte[] parseHexStr2Byte(String hexStr) {
    if (hexStr.length() < 1)
        return null; 
    byte[] result = new byte[hexStr.length() / 2];
    for (int i = 0; i < hexStr.length() / 2; i++) {
        int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
        int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
                16);
        result[i] = (byte) (high * 16 + low);
    }
    return result;
}

    //注意: 這里的password(秘鑰必須是16位的)
private static final String keyBytes = "abcdefgabcdefg12"; 

/**
*加密
*/
public static String encode(String content){
        //加密之后的字節數組,轉成16進制的字符串形式輸出
    return parseByte2HexStr(encrypt(content, keyBytes));
}

/**
*解密
*/
public static String decode(String content){
        //解密之前,先將輸入的字符串按照16進制轉成二進制的字節數組,作為待解密的內容輸入
    byte[] b = decrypt(parseHexStr2Byte(content), keyBytes);
    return new String(b);
}

//測試用例
public static void test1(){
    String content = "hello abcdefggsdfasdfasdf";
    String pStr = encode(content );
    System.out.println("加密前:"+content);
    System.out.println("加密后:" + pStr);

    String postStr = decode(pStr);
    System.out.println("解密后:"+ postStr );
}

public static void main(String[] args) {
    test1();
}

}</pre>

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