java學習-AES加解密之AES-128-CBC算法


AES算法簡介

AES是一種對稱加密算法,或稱分組對稱加密算法。  是Advanced Encryption Standard高級加密標准,簡稱AES

AES的基本要求是,采用對稱分組密碼體制。分組密碼算法通常由密鑰擴展算法和加密(解密)算法兩部分組成

AES加密數據塊分組長度必須為128比特(bit位),密鑰長度可以是128比特、192比特、256比特中的任意一個(如果數據塊及密鑰長度不足時,會補齊)。

128位數據塊,16byte字節的數據為一組,192位,24字節數據為一組。256位,32字節數據為一組

 

AES加密有很多輪的重復和變換。大致步驟如下(大概知道步驟就好吧,不想太深入研究):

1、密鑰擴展(KeyExpansion),2、初始輪(Initial Round),3、重復輪(Rounds),

每一輪又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,4、最終輪(Final Round),最終輪沒有MixColumns。

AES加密算法有多種加密模式:

1.電碼本模式(Electronic Codebook Book (ECB));2.密碼分組鏈接模式(Cipher Block Chaining (CBC));

3.計算器模式(Counter (CTR));4.密碼反饋模式(Cipher FeedBack (CFB));5.輸出反饋模式(Output FeedBack (OFB))。

 

ECB:將明文分成若干段相同的小段,然后對每一小段進行加密。

優點:
1.簡單;
2.有利於並行計算;
3.誤差不會被傳送;
缺點:
1.不能隱藏明文的模式;
2.可能對明文進行主動攻擊;


CBC:這種模式是先將明文切分成若干小段,然后每一小段與初始塊或者上一段的密文段進行異或運算后,再與密鑰進行加密。

優點:
1.不容易主動攻擊,安全性好於ECB,適合傳輸長度長的報文,是SSL、IPSec的標准。
缺點:
1.不利於並行計算;
2.誤差傳遞;
3.需要初始化向量IV

 參考鏈接:AES加密的四種模式詳解

 AES加密明文數據的5種填充模式

這些都屬於字節填充

  PKCS7Padding(PKCS#7),PKCS5Padding(PKCS#5),Zero padding,ISO 10126 , ANSI X.923

例如,現在數據128位數據塊方式進行加密,即16字節數據,,,現在有字符串String encryptedStr = "012345678912"

  note:由於utf-8下漢字字節長度是可變的,所以直接使用英文或數字字符串舉例。

上面數據的字符串長度為12字節,還需要補充4字節數據。

ANSIX923是最后一個字節數據為所缺字節的數進行填充,其余填0。上面需要補充4字節數據,所以最后一字節填4,其余3字節都填0

ISO10126則是最后一字節填4,剩余的都填0,

PKCS#7 是在填充字節上都填相同的數據,上面數據缺少4字節,所以所有字節上都填4

  如果缺少10字節,則在補充的10字節數據上都填a

ANSI X.923:... | DD DD DD DD DD DD DD DD | DD DD DD DD (00 00 00 04)|【除了最后字節,其他填0】

ISO 10126:.... | DD DD DD DD DD DD DD DD | DD DD DD DD (81 A6 23 04)|【除了最后字節,其他隨機】

PKCS7(Rfc3852) | DD DD DD DD DD DD DD DD | DD DD DD DD (04 04 04 04)

模式說明:(不完整)
算法/模式/填充                16字節加密后數據長度        不滿16字節加密后長度
AES/CBC/NoPadding             16                          不支持
AES/CBC/PKCS5Padding          32                          16
AES/CBC/ISO10126Padding       32                          16
AES/CFB/NoPadding             16                          原始數據長度
AES/CFB/PKCS5Padding          32                          16
AES/CFB/ISO10126Padding       32                          16
AES/ECB/NoPadding             16                          不支持
AES/ECB/PKCS5Padding          32                          16
AES/ECB/ISO10126Padding       32                          16
AES/OFB/NoPadding             16                          原始數據長度
AES/OFB/PKCS5Padding          32                          16
AES/OFB/ISO10126Padding       32                          16
AES/PCBC/NoPadding            16                          不支持
AES/PCBC/PKCS5Padding         32                          16
AES/PCBC/ISO10126Padding      32                          16

 

AES-128-CBC加密解密算法 

  這個是使用AES加密算法的CBC模式,使用128位數據塊為一組進行加密解密,

即16字節明文,對應16字節密文,,明文加密時,如果數據不夠16字節,則會將數據補全剩余字節

  • 若最后剩余的明文不夠16字節,需要進行填充,通常采用PKCS7進行填充。比如最后缺3個字節,則填充3個字節的0x03;若最后缺10個字節,則填充10個字節的0x0a;
  • 若明文正好是16個字節的整數倍,最后要再加入一個16字節0x10的組再進行加密

 加密時需要的參數

1、傳入要加密的明文
2、傳入一個16字節的key
3、傳入一個16字節的初始偏移向量IV



用初始向量和密鑰加密第一組數據,然后把第一組數據加密后的密文重新賦值給IV,然后進行第二組加密,循環進行直到結束

解密時需要參數

1、帶解密的密文
2、加密解密的key一致
3、跟加密時傳遞IV參數一致

 AES加密解密類

需要額外的jar包bcprov-jdk16-1.46-sources.jar

可添加依賴

<dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk16</artifactId>
            <version>1.46</version>
        </dependency>

AES.java

import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchProviderException;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class AES {

    //加密方式
    public static String KEY_ALGORITHM = "AES";
    //數據填充方式
    String algorithmStr = "AES/CBC/PKCS7Padding";
    //避免重復new生成多個BouncyCastleProvider對象,因為GC回收不了,會造成內存溢出
    //只在第一次調用decrypt()方法時才new 對象
    public static boolean initialized = false;

    /**
     * 
     * @param originalContent
     * @param encryptKey
     * @param ivByte
     * @return
     */
    public byte[] encrypt(byte[] originalContent, byte[] encryptKey, byte[] ivByte) {
        initialize();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec skeySpec = new SecretKeySpec(encryptKey, "AES");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(ivByte));
            byte[] encrypted = cipher.doFinal(originalContent);
            return encrypted;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * AES解密
     * 填充模式AES/CBC/PKCS7Padding
     * 解密模式128
     * @param content
     *            目標密文
     * @return
     * @throws Exception 
     * @throws InvalidKeyException 
     * @throws NoSuchProviderException
     */
    public byte[] decrypt(byte[] content, byte[] aesKey, byte[] ivByte) {
        initialize();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            Key sKeySpec = new SecretKeySpec(aesKey, "AES");
            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**BouncyCastle作為安全提供,防止我們加密解密時候因為jdk內置的不支持改模式運行報錯。**/
    public static void initialize() {
        if (initialized)
            return;
        Security.addProvider(new BouncyCastleProvider());
        initialized = true;
    }

    // 生成iv
    public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
        AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
        params.init(new IvParameterSpec(iv));
        return params;
    }
}

 

 

 

另一種加密算法DES

DES算法的入口參數有三個:Key、Data、Mode。

其中Key為7個字節共56位,是DES算法的工作密鑰;

Data為8個字節64位,是要被加密或被解密的數據;

Mode為DES的工作方式,有兩種:加密或解密。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM