java加密解密AES筆記

加密技術可以分爲對稱與非對稱兩種.
對稱加密,解密,即加密與解密用的是同一把祕鑰,常用的對稱加密技術有DES,AES等
而非對稱技術,加密與解密用的是不同的祕鑰,常用的非對稱加密技術有RSA,ECDH等

爲什麼要有非對稱加密,解密技術呢?
假設這樣一種場景A要發送一段消息給B,但是又不想以明文發送,所以就需要對消息進行加密.如果採用對稱加密技術,那麼加密與解密用的是同一把祕鑰.除非B事先就知道A的祕鑰,並且保存好.這樣纔可以解密A發來的消息.
由於對稱技術只有一把祕鑰,所以祕鑰的管理是一個很麻煩的問題.而非對稱技術的誕生就解決了這個問題.非對稱加密與解密使用的是不同的祕鑰,並且祕鑰對是一一對應的,即用A的私鑰加密的密文只有用A的公鑰才能解密.
這樣的話,每個人都有兩把祕鑰,私鑰和公鑰,私鑰是隻有自己才知道的,不能告訴別人,而公鑰是公開的,大家都可以知道.這樣,當A想要發送消息給B的時候,只需要用B的公鑰對消息進行加密就可以了,由於B的私鑰只有B才擁有,所以A用B的公鑰加密的消息只有B才能解開.而B想更換自己的祕要時也很方便,只須把公鑰告訴大家就可以了.
那麼,既然非對稱加密如此之好,對稱加密就沒有存在的必要了啊,其實不然,由於非對稱加密算法的開銷很大,所以如果直接以非對稱技術來加密發送的消息效率會很差.那麼怎麼辦呢?解決的辦法也很簡單,就是把對稱加密技術與非對稱加密技術結合起來使用.

舉個栗子--A要發送一條消息給B.
對於A:
一,A先生成一個對稱祕鑰,這個祕鑰可以是隨機生成的,
二,A用B的公鑰對第一步生成的這個對稱祕鑰進行加密
三,A把這個加密過的對稱祕鑰發給B
四,A用第一步生成的對稱祕鑰加密實際要發送的消息
五,A把採用對稱祕鑰加密的消息發給B

對於B:
他先收到A發來的對稱祕鑰,這個祕鑰是用B的公鑰加密過的,所以B需要用自己的私鑰來解密這個祕鑰
然後B又收到A發來的密文,這時候用剛纔解密出來的祕鑰來解密密文

這樣子的整個過程既保證了安全(B解密時的密鑰是通過非對稱加密的),又保證了效率(加密的數據是通過對稱加密).



背景:加密算法由算法+模式+填充組成,故不同的填充算法會導致相同明文相同密鑰加密後出現密文不一致的情況。

1、模式:
JCE中AES支持五中模式:CBC,CFB,ECB,OFB,PCBC;

  CBC(密碼分組鏈接模式):是一種循環模式,前一個分組的密文和當前分組的明文異或操作後再加密,這樣做的目的是增強破解難度。
  ECB(電碼本模式):是一種基礎的加密方式,密文被分割成分組長度相等的塊(不足補齊),然後單獨一個個加密,一個個輸出組成密文。
  ECB和CBC的加密結果是不一樣的,兩者的模式不同,而且CBC會在第一個密碼塊運算時加入一個初始化向量。
CFB/OFB實際上是一種反饋模式,目的也是增強破解的難度。

2、填充方式
JCE支持三種填充:NoPadding,PKCS5Padding,ISO10126Padding。
不支持SSL3Padding。不支持“NONE”模式。
首先,不帶模式和填充來獲取AES算法的時候,其默認使用ECB/PKCS5Padding。

其次,java中原生是不支持採用AES加密算法PKCS7Padding來填充的,只支持PKCS5Padding。

如果要在在java端採用PKCS7Padding填充,需用到bouncycastle組件來實現,Bouncy Castle是一種用於java平臺的開放源碼的輕量級密碼術包,支持大量的密碼術算法。



AES各算法組合說明
算法/模式/填充 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

   

     可以看到,在原始數據長度爲16的整數倍時,假如原始數據長度等於16*n,則使用NoPadding時加密後數據長度等於16*n,其它情況下加密數據長度等於16*(n+1)。在不足16的整數倍的情況下,假如原始數據長度等於16*n+m[其中m小於16],除了NoPadding填充之外的任何方式,加密數據長度都等於16*(n+1);NoPadding填充情況下,CBC、ECB和PCBC三種模式是不支持的,CFB、OFB兩種模式下則加密數據長度等於原始數據長度。


關於AES加密中key的字節數

若出現類似 Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 6 bytes

原因:AES supports 128, 192 and 256 bit keys, so the number of bytes needs to be 16, 24, or 32. Note that the latter two may not be available in all circumstances (as the comment in the "kgen.init(128)" line mentions). 請檢查密鑰的長度是否爲16,24,或者32


關於 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填充 可以很方便地檢測明文中的錯誤.


參考:對稱加密和分組加密中的四種模式(ECB、CBC、CFB、OFB) :http://www.cnblogs.com/happyhippy/archive/2006/12/23/601353.html

發佈了55 篇原創文章 · 獲贊 7 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章