JAVA AES算法

.前言html

AES(Advanced Encryption Standard),高級加密標準,是美國政府用於替換DES的一種加密算法標準,Java SDK中包含了部分AES的實現,但javadoc對於算法的描述很是少,本文將解釋Java AES實現的使用和原理。java

.示例代碼算法

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class AesECB {
    public static byte[] Encrypt(byte[] text, byte[] key) throws Exception {
        SecretKeySpec aesKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // default, same as "AES"
        // Cipher cipher = Cipher.getInstance("AES"); // same as above
        cipher.init(Cipher.ENCRYPT_MODE, aesKey);
        return cipher.doFinal(text);
    }
    public static byte[] Decrypt(byte[] text, byte[] key) throws Exception {
        SecretKeySpec aesKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, aesKey);
        return cipher.doFinal(text);
    }
    public static String bytes2hex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String temp = (Integer.toHexString(bytes[i] & 0XFF));
            if (temp.length() == 1) {
                temp = "0" + temp;
            }
            sb.append(temp);
            sb.append(" ");
        }
        return sb.toString().toUpperCase();
    }
    public static void main(String[] args) {
        try {
            String key = args[0];
            String text = args[1];
            System.out.printf("text   : %s\n", bytes2hex(text.getBytes()));
            byte[] enc = AesECB.Encrypt(text.getBytes(), key.getBytes());
            System.out.printf("encrypt: %s\n", bytes2hex(enc));
            byte[] dec =  AesECB.Decrypt(enc, key.getBytes());
            System.out.printf("decrypt: %s\n", bytes2hex(dec));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

.代碼分析api

JDK AES加密主要是幾個步驟:oracle

1.key變換app

將傳入的明文key作變換,AESkey固定爲128bit,但變換後的key爲加密位數的一倍,128bit的加密變換後key256bit。注意加密和解密的key變換不同。ide

2.加密解密函數

選擇加密的模式和補齊填充方法生成加密實例,加密獲得密文。ui

.密碼塊工做模式編碼

塊密碼工做模式(Block cipher mode of operation),是對於按塊處理密碼的加密方式的一種擴充,不單單適用於AES,包括DES, RSA等加密方法一樣適用。

名稱

英文

全名

方法

優勢

缺點

ECB

Electronic codebook

電子密碼本

每塊獨立加密

1.分塊能夠並行處理

1.一樣的原文獲得相同的密文,容易被***

CBC

Cipher-block chaining

密碼分組連接

每塊加密依賴於前一塊的密文

1.一樣的原文獲得不一樣的密文
2.
原文微小改動影響後面所有密文

1.加密須要串行處理
2.
偏差傳遞

PCBC

Propagating cipher-block chaining

填充密碼塊連接

CBC的擴種,較少使用

1.一樣的原文獲得不一樣的密文
2.
互換兩個鄰接的密文塊不會對後續塊的解密形成影響

1.加密須要串行處理

CFB

Cipher feedback

密文反饋




OFB

Output feedback

輸出反饋模式

加密後密文與原文異或XOR


1.可以對密文進行校驗

CTR

Counter mode

計數器模式

增長一個序列函數對全部密文快作XOR



.填充

填充(Padding),是對須要按塊處理的數據,當數據長度不符合塊處理需求時,按照必定方法填充滿塊長的一種規則。

名稱

方法

示例

Zero padding

最多見的方式,全填充0x00

AA AA AA AA 00 00 00 00

ANSI X.923

Zero的改進,最後一個字節爲填充字節個數

AA AA AA AA 00 00 00 04

ISO 10126

隨機填充

AA AA AA AA 81 A6 23 04

PKCS7

ANSI X.923的變體
填充1個字符就全0x01
填充2個字符就全0x02
不須要填充就增長一個塊,填充塊長度,塊長爲8就填充0x08,塊長爲16就填充0x10

AA AA AA AA AA AA AA 01
AA AA AA AA 04 04 04 04
AA AA AA AA AA AA AA AA 08 08 08 08 08 08 08 08

ISO/IEC 7816-4

0x80開始做爲填充開始標記,後續全填充0x00

AA AA AA AA AA AA AA 80
AA AA AA AA 80 00 00 00

.JDK AES實現

1.實現支持

AES理論上支持128,192,256三種長度的密鑰,幾乎所有密碼塊工做模式和填充方法,但JDK 7中只實現以下四種AES加密算法:

(1)AES/CBC/NoPadding (128)
(2)AES/CBC/PKCS5Padding (128)
(3)AES/ECB/NoPadding (128)
(4)AES/ECB/PKCS5Padding (128)

2.使用須知

(1)缺省模式和填充爲「AES/ECB/PKCS5Padding」Cipher.getInstance(「AES」)Cipher.getInstance(「AES/ECB/PKCS5Padding」)等效。

(2)JDKPKCS5Padding實際是上述的PKCS7的實現。

(3)因爲AES是按照16Byte爲塊進行處理,對於NoPadding而言,若是須要加密的原文長度不是16Byte的倍數,將沒法處理拋出異常,實際上是由用戶本身選擇Padding的算法。密文則必然是16Byte的倍數,不然密文確定異常。

(4)若是加密爲PKCS5Padding,解密能夠選擇NoPadding,也能解密成功,內容爲原文加上PKCS5Padding以後的結果。

(5)若是原文最後一個字符爲>=0x00&&<=0x10的內容,PKCS5Padding的解密將會出現異常,要麼是符合PKCS5Padding,最後的內容被刪除,要麼不符合,則解密失敗拋出異常。對此有兩種思路,一是原文經過Base64編碼爲可見字符,二是原文自帶長度使用NoPadding解密。

.參考

(1)AES(Wiki)
(2)
Block cipher mode of operation(Wiki)
(3)塊密碼的工做模(Wiki)
(4)
Padding(Wiki)
(5)
PKCS(Wiki)
(6)
JAVA 7 Cipher

相關文章
相關標籤/搜索