[轉]AES加密遇到的問題


Java 環境下使用 AES 加密的特殊問題處理

 在 Java 環境下使用 AES 加密,在密鑰長度和字節填充方面有一些比較特殊的處理。

1. 密鑰長度問題

    默認 Java 中僅支持 128 位密鑰,當使用 256 位密鑰的時候,會報告密鑰長度錯誤

Invalid AES key length

   你需要下載一個支持更長密鑰的包。這個包叫做 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6,可以從這里下載,下載地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

   下載之后,解壓后,可以看到其中包含兩個包:

    local_policy.jar

    US_export_policy.jar

    看一下你的 JRE 環境,將 JRE 環境中 lib\lib\security 中的同名包替換掉。

2. Base64 問題

     Apache 提供了 Base64 的實現,可以從這里下載。

    下載地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi

     編碼

// 編碼 String asB64 = new Base64().encodeToString("some string".getBytes("utf-8")); System.out.println(asB64); // 輸出為: c29tZSBzdHJpbmc=

     解碼   

// 解碼 byte[] asBytes = new Base64().getDecoder().decode("c29tZSBzdHJpbmc="); System.out.println(new String(asBytes, "utf-8")); // 輸出為: some string

 

     如果你已經使用 Java 8,那么就不需要再選用第三方的實現了,在 java.util 包中已經包含了 Base64 的處理。

     編碼的方式

// 編碼 String asB64 = Base64.getEncoder().encodeToString("some string".getBytes("utf-8")); System.out.println(asB64); // 輸出為: c29tZSBzdHJpbmc=

     解碼處理

// 解碼 byte[] asBytes = Base64.getDecoder().decode("c29tZSBzdHJpbmc="); System.out.println(new String(asBytes, "utf-8")); // 輸出為: some string

 

3. 關於 PKCS5 和 PKCS7 填充問題

PKCS #7 填充字符串由一個字節序列組成,每個字節填充該填充字節序列的長度。

假定塊長度為 8,數據長度為 9,           數據: FF FF FF FF FF FF FF FF FF PKCS7 填充: FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07

簡單地說, PKCS5, PKCS7和SSL3, 以及CMS(Cryptographic Message Syntax)

有如下相同的特點: 1)填充的字節都是一個相同的字節 2)該字節的值,就是要填充的字節的個數

如果要填充8個字節,那么填充的字節的值就是0×8; 要填充7個字節,那么填入的值就是0×7;

如果只填充1個字節,那么填入的值就是0×1;

這種填充方法也叫PKCS5, 恰好8個字節時還要補8個字節的0×08

正是這種即使恰好是8個字節也需要再補充字節的規定,可以讓解密的數據很確定無誤的移除多余的字節。

 

在PKCS# Padding中說:

  1. 因為恢復的明文的最后一個字節 告訴你 存在多少個填充字節, 用PKCS#5 填充 的加密方法, 即使在輸入的明文長度 恰好是 塊大小(Block Size)整數倍 , 也會增加一個完整的填充塊. 否則,恢復出來的明文的最后一個字節可能是實際的消息字節.
  2. 因為第1個因素限制了 使用PKCS#填充的 對稱加密算法的 輸入塊大小(Block Size, 注意不是輸入的明文的總長度 total input length), 最大只能是256個字節.   因為大多數對稱塊加密算法 通常使用8字節或者16字節的塊, 所以,這不是一個問題
  3. 使用ECB模式填充可能會有安全問題.
  4. 使用PKCS#5填充 可以很方便地檢測明文中的錯誤.

標准

PKCS #7: Cryptographic Message Syntax

在 10.3節中講到了上面提到的填充算法,  對Block Size並沒有做規定

PKCS #5: Password-Based Cryptography Specification

在6.1.1 中對 填充做了說明 但是因為該標准 只討論了 8字節(64位) 塊的加密, 對其他塊大小沒有做說明 其 填充算法跟 PKCS7是一樣的

后來 AES 等算法, 把BlockSize擴充到 16個字節

比如, Java中 Cipher.getInstance(“AES/CBC/PKCS5Padding”) 這個加密模式 跟C#中的 RijndaelManaged cipher = new RijndaelManaged(); cipher.KeySize = 128; cipher.BlockSize = 128; cipher.Mode = CipherMode.CBC; cipher.Padding = PaddingMode.PKCS7; 的加密模式是一樣的

因為AES並沒有64位的塊, 如果采用PKCS5, 那么實質上就是采用PKCS7

 

參考資料:

對稱加密算法的PKCS5和PKCS7填充


免責聲明!

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



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