2012-09-20 33 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

神奇,但不要抱怨随机数发生器实际上产生随机数。 –

相关问题