2017-05-27 410 views
0

我想了解更多關於AES加密的信息。 AES加密使用密鑰和IV進行加密,但由於每個IV都不同,AES如何解密密文並返回明文?AES如何解密不同的IV?

http://www.moserware.com/2009/09/stick-figure-guide-to-advanced.html https://www.securecoding.cert.org/confluence/display/java/MSC61-J.+Do+not+use+insecure+or+weak+cryptographic+algorithms

public static byte[] encrypt_cbc(SecretKey skey, String plaintext) { 
     /* Precond: skey is valid; otherwise IllegalStateException will be thrown. */ 
     try { 
      byte[] ciphertext = null; 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");   
      final int blockSize = cipher.getBlockSize(); 
      byte[] initVector = new byte[blockSize]; 
      (new SecureRandom()).nextBytes(initVector); 
      IvParameterSpec ivSpec = new IvParameterSpec(initVector); 
      cipher.init(Cipher.ENCRYPT_MODE, skey, ivSpec); 
      byte[] encoded = plaintext.getBytes(java.nio.charset.StandardCharsets.UTF_8); 
      ciphertext = new byte[initVector.length + cipher.getOutputSize(encoded.length)]; 
      for (int i=0; i < initVector.length; i++) { 
       ciphertext[i] = initVector[i]; 
      } 
      // Perform encryption 
      cipher.doFinal(encoded, 0, encoded.length, ciphertext, initVector.length); 
      return ciphertext; 
     } catch (NoSuchPaddingException | InvalidAlgorithmParameterException | ShortBufferException | 
      BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException e) 
     { 
      /* None of these exceptions should be possible if precond is met. */ 
      throw new IllegalStateException(e.toString()); 
     } 
    } 

    public static String decrypt_cbc(SecretKey skey, byte[] ciphertext) 
     throws BadPaddingException, IllegalBlockSizeException /* these indicate corrupt or malicious ciphertext */ 
    { 
     try { 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");   
      final int blockSize = cipher.getBlockSize(); 
      byte[] initVector = Arrays.copyOfRange(ciphertext, 0, blockSize); 
      IvParameterSpec ivSpec = new IvParameterSpec(initVector); 
      cipher.init(Cipher.DECRYPT_MODE, skey, ivSpec); 
      byte[] plaintext = cipher.doFinal(ciphertext, blockSize, ciphertext.length - blockSize); 
      return new String(plaintext); 
     } catch (NoSuchPaddingException | InvalidAlgorithmParameterException | 
      InvalidKeyException | NoSuchAlgorithmException e) 
     { 
      /* None of these exceptions should be possible if precond is met. */ 
      throw new IllegalStateException(e.toString()); 
     } 
    } 
+1

嗯,我認識到我的異常處理,我認爲,但我絕不會在我的方法名稱中使用下劃線或刪除catch塊中的整個堆棧跟蹤。或者現在然後使用'final'。或者給密文分配'null'。或者仍然使用CBC。關於代碼實踐,這並不是一個很好的例子。雖然可能會惡化很多! –

+0

@youcanlearnanything *「AES如何用**不同的** IV解密?」* - 你能舉一個你看過這個的例子嗎? IV對於一個加密/解密週期 –

+0

@ ArtjomB必須相同。如果這意味着什麼,那麼可能是因爲純運氣或者IV僅部分不同(它與明文異或,所以),前16個字節有點意義。如果IV不同,只有第一個塊受到影響。 –

回答

1

通常隨機IV - CBC需要不可預知 IV - 解密之前被前綴到密文和 「刪除」。我已經刪除了引號,因爲刪除它可能會被複制並在之後跳過。原則上它可以放在密文的任何地方。 CBC模式的IV等於底層密碼的塊大小(Cipher#getBlockSize()),即AES的16個字節,所以預先知道大小。

IV不需要被攻擊者保密。

一般來說,IV的類型和安全性取決於加密模式。對於CBC,它需要是不可預知的,對於CTR(計數器模式),它不應該與另一個計數器值重疊,對於GCM,它需要是12個字節的隨機數。

還有其他共享IV的方式。對於CBC來說,例如可以在雙方都保留一個計數器並加密該計數器以形成一個IV(當然,在將其編碼爲16個字節之後)。這樣,IV不需要包含在密文中。

+0

我沒有得到的是,你已經顯示的代碼片段實際上已經在IV前綴,什麼給了? –

+0

我一直在閱讀有關IV和密鑰之間的區別。一般來說,如果將相同的密鑰重新用於加密,則建議使用不同的IV。那麼如何使用不同的IV有助於防止密文被破譯? – youcanlearnanything

+0

一般不會。 IV主要是爲了使密碼不確定;如果你要重複(部分)消息,你不想擁有與泄露信息相同的密文。重複的消息很常見。一個可能的例外是SIV(合成IV)模式,其中IV兼作身份驗證標籤。因此,即使不解密密文,重複使用IV也會泄漏信息。 –