2016-10-14 28 views
0

我想內聯我的IV,這樣我就可以在不知道最初的IV的情況下解密我的消息,只需要密鑰。帶有內聯安全隨機IV的Java AES CBC - 生成相同的密文文本?

我生成我的密鑰。 我用SecureRandom生成我的IV 我randominze IV字節數組。 (我用iv +消息創建消息) 最後,我用獨特的IV加密消息。

正如所料,如果我在接收端刪除了IV,我可以解密該消息。 但是,生成的密文始終是相同的。

我不知道爲什麼這樣,還沒有找到解決方案在線。

下面是我的代碼和輸出。

任何人都可以幫助我理解這是爲什麼?

enter code 
    String mssg = "Hello hellow hello"; 
     byte[] key = "kljhn1234512345abcde123451234512".getBytes(); 
     SecretKeySpec spec = new SecretKeySpec(key, "AES"); 

     SecureRandom rand = new SecureRandom(); 
     for (int i = 0; i < 5; i++) { 

      // 
      //initialzize empty byte array for random IV 

      byte[] iv = new byte[16]; 
      System.out.println("IV pre rand: " + Arrays.toString(iv)); 
      rand.nextBytes(iv); //RANDOMIZE 
      System.out.println("IV POST rand: " + Arrays.toString(iv)); 

      //CONCATENTATE IV TO FRONT OF MESSAGE TO ENCRYPT 
      //CONCATENATE MESSAGE TO END OF IV 

      ByteArrayOutputStream bout = new ByteArrayOutputStream(); 
      try { 
       bout.write(iv); 
       bout.write(mssg.getBytes()); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

      byte[] message = bout.toByteArray(); 

      try { 

       //ENCRYPT USING RANDIMIZED IV.. THIS SHOULD RESULT IN NON EQUAL CIPHER TEXT FOR SAME MESSAGE. 
       Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
       cipher.init(Cipher.ENCRYPT_MODE, spec, new IvParameterSpec(iv)); 
       byte[] ct = cipher.doFinal(message); 
       System.out.println("CIPHER TEXT: " + Arrays.toString(ct)); 

       //DECRYPT. AND USING A WRONG IV. 
       cipher.init(Cipher.DECRYPT_MODE, spec, new IvParameterSpec(new byte[16])); 
       System.out.println("DECRYPTED: " + new String(cipher.doFinal(ct))); 

      } catch (NoSuchAlgorithmException e) { 
       e.printStackTrace(); 
      } catch (NoSuchPaddingException e) { 
       e.printStackTrace(); 
      } catch (InvalidAlgorithmParameterException e) { 
       e.printStackTrace(); 
      } catch (InvalidKeyException e) { 
       e.printStackTrace(); 
      } catch (BadPaddingException e) { 
       e.printStackTrace(); 
      } catch (IllegalBlockSizeException e) { 
       e.printStackTrace(); 
      } 


     } 

這裏

和輸出:

迭代1 IV預蘭特:[0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0]

IV POST rand:[13,68,83,113,86,48,50,-71,-75,-25,56,100,-25,34 ,-27,-23]

CIPHER TEXT:[ - 102,-52,-21,-92,-85,119,-10,-18,-52,0,-39,-19,11 ,-83,70, 44,101,-92,-93,-60,4,73,-17,73,-58,119,81,66,-114,54,-107,-83,11,42,-92,121 ,-15,-61,92,83,24,10,89,-21,110,100,116,119]

DECRYPTED:你好hellow你好

迭代2: IV預蘭特:[0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0]

IV POST rand:[90,115,91,124,27,-80,-32,-46,-66,-50,-85 ,43,34,-18,-74,-3]

密文:[-102,-52,-21,-92,-8 5,119,-10,-18,-52,0,-39,-19,11,-83,70,44,101,-92,-93,-60,4,73,-17,73, -58,119,81,66,-114,54,-107,-83,11,42,-92,121,-15,-61,92,83,24,10,89, 100,116,119]

解密: 你好,你好,你好

ITERATION 3

IV預蘭特:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

IV POST蘭特:[113,112,圖9,47,-125,-4,80,10,-97,44,42,90,-58,-44,-46,17]

密文:[-102,-52,-21,-92,-85,119,-10,-18,-52,0,-39,-19,11,-83,70%,44 ,101,-92,-93,-60,4,73,-17,73,-58,119,81,66,-114,54,-107,-83,11,42,-92,121, -15,-61,92,83,24,10,89,-21,110,100,116,119]

DECRYPTED: 你好,你好,

+0

你似乎不知道如何處理安全相關的異常,你可能想看看[這裏](http://stackoverflow.com/q/15709421/589259)。另外看看GCM模式,CBC正在變老 - 認證加密是99%的時間。 –

+0

非常感謝你指點好方向。 :) – JoshuaTree

回答

5

如果你看看the nice picture in Wikipedia of how CBC works你會發現,通過將IV放在CBC明文的開頭,實際上是取消了IV並破壞它旨在提供的語義安全性。具體而言,CBC加密的作用:

  • XOR與第一明文塊的IV和加密的第一密文塊。由於您將第一個明文塊創建爲IV的副本,因此每次都會對零塊進行加密併產生相同的結果。

  • 將第一個密文塊與第二個明文塊(這裏是你擰緊之前的實際明文)進行異或並將其加密到第二個密文塊中。由於您將第一個密文塊設爲固定值,並且在您的測試中實際的明文是相同的,所以每次都會產生相同的結果。

  • 等等等等

你應該做的:

  • 加密實際明文用(祕密)密鑰和(隨機)IV,然後用密文結合IV對於傳輸;級聯是一種簡單的方法,但不是唯一的方法

  • 上接收分割或分離從密文的IV,並且與(祕密)密鑰和(隨機的,但可見)IV解密密文

+0

感謝您的評論。你說的是有道理的。 但是,我認爲我出錯的地方是因爲某種原因,在傳輸過程中需要保密。 – JoshuaTree

+0

IV不需要保密嗎? – JoshuaTree

+0

@ Enjoy87不;正如維基百科的文章所說,** IV不需要是祕密**,只有獨特的(所有模式)和不可預知的(包括CBC在內的某些模式)。你不能加密傳輸它,因爲你在解密之前需要IV,但是在獲得IV之前需要解密,這是不可能的。有些方案使用不可預知但未傳輸的值,例如同步計數器的祕密密鑰散列(無論如何都需要一些傳輸方案,因此節省一點空間),但它們很少。 –