10

我的应用程序在 Windows 中工作,但在 Linux 中失败,但有Given final block not properly padded异常。

配置:

  • JDK版本:1.6
  • 视窗:版本 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

我该如何解决这个问题?

4

3 回答 3

2

答案在于SecureRandom特定运行时的播种可能不同。大多数时候你会得到"SHA1PRNG",它不会立即播种。相反,您可以setSeed()在请求任何随机之前调用,在这种情况下,种子被用作熵的唯一来源。在这种情况下,您的密钥将始终相同。

问题是没有定义SecureRandom返回哪个。您可能会得到一个完全不同的、特定于平台的实现,但上述情况并不适用。如果另一个提供商优先,您可能无法获得其中一个 Sun 提供商。

然后是种子的问题。种子seedStr在调用getBytes(). 由于编码可能不同,种子可能不同,因此结果也会不同。

尝试使用 PBKDF2 等函数来代替密钥推导;关于如何进行,stackoverflow 上有足够的内容。

于 2012-09-20T20:45:18.150 回答
1

如下:我不得不修改内容。

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) {
}

}

有用!!谢谢!!!

于 2012-10-09T06:21:12.917 回答
0

错误似乎是因为编码数据,BASE64Decoder 将返回 4 的倍数,而 Cipher 期望为 8 的倍数。

于 2012-09-30T11:35:00.547 回答