加密解密RAS+AES。(二)源碼及測試代碼在文章末尾。

背景
RAS是一個非常好的非對稱加密算法。AES則是一個目前國際應用廣泛的對稱加密算法。這兩者優劣皆有,需要結合具體的加密場景,選擇不同的加密方式,針對性能和安全,大家需要做出自己的判斷。
我們設計了兩個工具類,將RAS和AES的一些邏輯封裝進去,適合我們在開發時候直接調用。

代碼邏輯:

首先是AES算法。

/**
 * AES工具類,密鑰必須是16位字符串
 */
public class AESUtils {

首先給他一個隨機密鑰的方法。

/**
 * 產生隨機密鑰(這裏產生密鑰必須是16位)
 */
public static String generateKey() {
    String key = UUID.randomUUID().toString().
    		replace("-", "").substring(0, 16);// 替換掉-號
    return key;
}

這裏是加密算法Encrypt。

public static String encryptData(String key, String content) {
    byte[] encryptedBytes = new byte[0];
    try {
    //缺省是ISO-8859-1,content可能是中文,所以這裏用UTF-8。
        byte[] byteContent = content.getBytes("UTF-8");
        // 爲了與 iOS 統一, 這裏的 key 不可以使用 KeyGenerator、SecureRandom、SecretKey 生成
        byte[] enCodeFormat = key.getBytes();
        //會把參數放到secretKeySpec的變量Key裏,AES會放到algorithm。
        SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
        //取得常量的編碼。
        byte[] initParam = IV_STRING.getBytes();
        //把initParam裏的字節編碼copy到ivParameterSpec的iv字節數組裏
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
        // 指定加密的算法、工作模式和填充方式
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        //初始化。用密鑰和一組算法參數初始化此 Cipher。 
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        //執行
        encryptedBytes = cipher.doFinal(byteContent);
        // 同樣對加密後數據進行 base64 編碼
        return Base64Utils.encode(encryptedBytes);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

解密的代碼這裏就不放了。

RAS加密AES密鑰。
這是一個測試程序。
在這裏插入圖片描述
這個RAEUtils類的加密解密邏輯如下:

public static String encryptByPublicKey(String data) throws Exception {
    byte[] dataByte = data.getBytes();
    byte[] keyBytes = Base64Utils.decode(PUBLIC_KEY);
    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    Key key = keyFactory.generatePublic(x509KeySpec);
    // 對數據加密
    // Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    /** 得到Cipher對象來實現對源數據的RSA加密 */

    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] encryptedData = cipher.doFinal(dataByte);
return Base64Utils.encode(encryptedData);

解密方法:

public static String decryptByPrivateKey(String data) throws Exception {
    byte[] encryptedData = Base64Utils.decode(data);
    byte[] keyBytes = Base64Utils.decode(PRIVATE_KEY);
    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
    // Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    //解密
    cipher.init(Cipher.DECRYPT_MODE, privateK);

這是解密代碼。

byte[] encryptedData = Base64Utils.decode(data);
byte[] keyBytes = Base64Utils.decode(PRIVATE_KEY);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
// Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 對數據分段解密
while (inputLen - offSet > 0) {
    if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
        cache = cipher
                .doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
    } else {
        cache = cipher
                .doFinal(encryptedData, offSet, inputLen - offSet);
    }
    out.write(cache, 0, cache.length);
    i++;
    offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return new String(decryptedData);

因爲密文太長,所以要分段解碼。

這裏用了默認的公鑰值,對AES產生的密鑰進行加密。先對數據進行編碼處理,然後就是用cipher對象對數據進行加密,一些參數的含義,有興趣的可以查閱JDK文檔和JAVAX文檔瞭解。

補充:
AES絕對不要使用 ECB 模式!
https://zh.wikipedia.org/wiki/塊密碼的工作模式

RSA 1024已經不安全了,起碼要2048!

參考文檔: https://segmentfault.com/a/1190000015943620
https://github.com/wustrive2008/aes-rsa-java/blob/master/src/main/java/com/wustrive/aesrsa/util/RSA.java

http://tool.oschina.net/uploads/apidocs/jdk-zh/javax/crypto/Cipher.html#init(int, java.security.Key, java.security.spec.AlgorithmParameterSpec)

http://tool.oschina.net/apidocs/apidoc?api=jdk-zh

源碼地址: 添加鏈接描述
有空的,可以star一下,後續源碼會更新的。看到問題可以提Issue給我。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章