2017-05-23 46 views
-1

我想在JAVA中使用AES/CBC/NoPadding進行加密和解密。我使用(mcrypt)在JAVA和PHP中進行了加密,並使用相同的密鑰和iv獲得了相同的結果。但是,當我嘗試在JAVA中解密時,我正確地獲取了該詞,但始終使用了額外的字符。我讀了其他問題,發現我需要添加填充。所以我添加了Padding5,但得到了相同的結果。無論如何,我需要它沒有填充,因爲這是它如何在PHP中工作。任何幫助表示讚賞。我的代碼是下面,其結果是在這裏:result is in image[![][1]] 2AES CBC沒有填充在解密中給出額外的字符JAVA

public class RijndaelCrypt { 


    //private String key = "2a4e2471c77344b3bf1de28ab9aa492a444abc1379c3824e3162664a2c2b811d"; 
    private static String iv = "beadfacebadc0fee"; 
    private static String hashedKey = "6a2dad9f75b87f5bdd365c9de0b9c842"; 
    private static Cipher cipher; 


    public static String decrypt(String text) throws UnsupportedEncodingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException { 

    SecretKeySpec keyspec = new SecretKeySpec(hashedKey.getBytes("UTF-8"), "AES"); 
    IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes("UTF-8")); 
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
     cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); 

      byte[] decodedValue = Base64.decode(text.getBytes("UTF-8")); 
      byte[] decryptedVal = cipher.doFinal(decodedValue); 
      return new String(decryptedVal);    

    } 

     public static String encryptNew(String data) throws Exception { 

      cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
      int blockSize = cipher.getBlockSize(); 

      byte[] dataBytes = data.getBytes("UTF-8"); 
      int plaintextLength = dataBytes.length; 
      if (plaintextLength % blockSize != 0) { 
       plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize)); 
      } 

      byte[] plaintext = new byte[plaintextLength]; 
      System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length); 

      SecretKeySpec keyspec = new SecretKeySpec(hashedKey.getBytes("UTF-8"), "AES"); 
      IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes("UTF-8")); 

      cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); 
      byte[] encrypted = cipher.doFinal(plaintext); 

      return DatatypeConverter.printBase64Binary(encrypted); 

     } 

    public static void main (String [] args) throws Exception 
    { 
     Security.addProvider(new BouncyCastleProvider()); 
     String data = "Hello"; 


     System.out.println("New Decrypted: " + RijndaelCrypt.decrypt(RijndaelCrypt.encryptNew(data))); 
     System.out.println("New Encryption: " + RijndaelCrypt.encryptNew(data)); 
     } 

    } 
+0

你是說即使你指定沒有填充,在PHP中額外的字節被自動刪除?因爲只有在加密可被塊大小整除的數據時才需要填充,否則您需要以某種方式除去額外的字節。 – Kayaman

+0

我沒有在PHP中使用填充,它的工作原理沒有刪除任何額外的字節..也兩個加密結果是相同的PHP和JAVA –

+0

那麼它不應該工作,如果你真的使用無填充選項。填充需要知道哪些字節是「額外的」,所以更可能是您實際上在不知道的情況下使用PHP中的填充。 – Kayaman

回答

1

的PHP的mcrypt包裝物(或潛在的mcrypt庫)焊盤與零個字節到塊長度(0到15填充字節,如果圖16是密碼的塊大小)。之後,塊被密碼加密。

使用Java解密時,您需要在使用NoPadding進行解密之後手動從明文右側刪除任何零字節。當對已解密的明文進行十六進制編碼時,可以看到零值填充字節。但是,當輸出一個字符串時,零字節會被省略或轉換爲替換字符(取決於字符集和終端)。

請注意,PHP零填充有一個很大的缺點:如果明文以一個或多個零值字節結尾,則可以通過任何非壓縮例程從解密的明文中剝離。這就是爲什麼PKCS#7填充(填充1到16個字節)應該是首選。

另請注意,PHP實際上需要rtrim("\0")本身去除零字節; mcrypt只是將它們留在那裏,但它們通常不會被打印。


注意,充氣城堡加密庫也有ZeroPadding作爲選項。但是,這是1到16字節的零填充(即它總是填充/不填充),因此它是不兼容與由PHP mcrypt使用定義的填充並且可能會失敗,如果明文的大小可以除以塊的大小密碼。

相關問題