2012-09-20 28 views
9

我的應用程序在Windows中工作,但在Linux中出現故障,出現Given final block not properly padded異常。例外:在Linux中「給定最終塊未正確填充」,但它在Windows中工作

配置:

  • JDK版本:1.6
  • 的Windows:版本7
  • 的Linux:CentOS的5.8 64位

我的代碼如下:

import java.io.IOException; 
import java.io.UnsupportedEncodingException; 
import java.security.InvalidKeyException; 
import java.security.Key; 
import java.security.NoSuchAlgorithmException; 
import java.security.SecureRandom; 

import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.KeyGenerator; 
import javax.crypto.NoSuchPaddingException; 

import sun.misc.BASE64Decoder; 
import sun.misc.BASE64Encoder; 

public class SecurityKey { 
    private static Key key = null; 
    private static String encode = "UTF-8"; 
    private static String cipherKey = "DES/ECB/PKCS5Padding"; 

    static { 
     try { 
      KeyGenerator generator = KeyGenerator.getInstance("DES"); 
      String seedStr = "test"; 
      generator.init(new SecureRandom(seedStr.getBytes())); 
      key = generator.generateKey(); 
     } catch(Exception e) { 
     } 
    } 

    // SecurityKey.decodeKey("password") 
    public static String decodeKey(String str) throws Exception { 
     if(str == null) 
      return str; 

     Cipher cipher = null; 
     byte[] raw = null; 
     BASE64Decoder decoder = new BASE64Decoder(); 
     String result = null; 
     cipher = Cipher.getInstance(cipherKey); 
     cipher.init(Cipher.DECRYPT_MODE, key); 
     raw = decoder.decodeBuffer(str); 
     byte[] stringBytes = null; 
     stringBytes = cipher.doFinal(raw); // Exception!!!! 
     result = new String(stringBytes, encode); 

     return result; 
    } 
} 

在該行:

ciper.doFilnal(raw); 

以下異常被拋出:

javax.crypto.BadPaddingException: Given final block not properly padded 

我怎樣才能解決這個問題?

+1

我希望你不要在乎安全。 DES和ECB都是一個可疑的選擇。 – CodesInChaos

+0

您假定'SecureRandom'在所有平臺上的行爲方式都是相同的。 Java保證嗎?使用KDF來派生密鑰,而不是PRNG。 – CodesInChaos

+0

你確定'raw'在兩個平臺上都包含相同的數據嗎?在將數據傳遞給'decodeKey()'之前,我會懷疑一些錯誤的編碼蓋度,儘管使用base64的可能性不大。 – axtavt

回答

2

答案在於SecureRandom種子在特定運行時可能會有所不同。大多數時間你會得到"SHA1PRNG",這將不會立即播種。相反,在請求任意隨機數之前,您可以調用setSeed(),在這種情況下,該種子僅用作熵的來源。在這種情況下,你的鑰匙將永遠是一樣的。

問題是沒有定義哪個SecureRandom被返回。您可能會得到一個完全不同的,特定於平臺的實現,但上述情況並非如此。如果另一個提供者優先,您可能不會獲得Sun提供者之一。

然後就是種子的問題。在呼叫getBytes()期間,種子使用了seedStr變量的平臺默認編碼。由於編碼可能不同,種子可能會有所不同,因此結果也會有所不同。

嘗試使用諸如PBKDF2之類的函數來代替密鑰;關於如何處理,在stackoverflow上已經足夠了。似乎因爲編碼數據的

+1

有沒有人?這有幫助嗎?你解決了你的問題嗎?請回報! –

+0

它的工作原理!謝謝!! – user1685364

+0

偉大的,這解決了你的問題,這將是很好,如果你會接受答案。 –

0

錯誤,BASE64Decoder將返回4的倍數和密碼期待的8

0

倍數如下:我不得不修改的內容。

static{ 
    try { 
    KeyGenerator generator = KeyGenerator.getInstance("DES"); 
    String seedStr = "test"; 
    SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); 
    random.setSeed(seedStr.getBytes()); 
    generator.init(random); 
    key = generator.generateKey(); 
} catch(Exception e) { 
} 

}

它的工作的!謝謝!!!

+0

神奇,但不要抱怨隨機數發生器實際上產生隨機數。 –

相關問題