2

首先,我已经查看了论坛上的所有条目,但我仍然找不到解决问题的方法。我必须测量使用 DES 对文本进行编码和解码所需的时间,并与其他算法进行比较。

当我运行代码时,我有这个错误:BadPaddingException: pad block corrupted。当我调试时,代码在这一行失败:

  字节 [] 明文 = cipher.doFinal (cipherBytes);

我使用 Base64 类来编码/解码 String <--> byte[]

任何想法?

谢谢

private static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
private static int KEY_LENGTH = 64;

 public static SecretKey deriveKeyDES() {
        try {
            long start = System.currentTimeMillis();

            KeyGenerator kgen = KeyGenerator.getInstance("DES");
            kgen.init(KEY_LENGTH);
            SecretKey result = kgen.generateKey();

            long elapsed = System.currentTimeMillis() - start;
            return result;

        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        } 
    }


    public static String encrypt(String plaintext, SecretKey key) {
        try {

            long start = System.currentTimeMillis();
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding")

            cipher.init(Cipher.ENCRYPT_MODE, key);

            byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));

            long elapsed = System.currentTimeMillis() - start;

            return toBase64(cipherText);

        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String toBase64(byte[] bytes) {
        return Base64.encodeToString(bytes, Base64.NO_WRAP).trim();
    }


    public static String decrypt(String ciphertext, SecretKey key) {
        try {
            byte[] cipherBytes = fromBase64(ciphertext);

                long start = System.currentTimeMillis();
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

            cipher.init(Cipher.DECRYPT_MODE, key);
            cipher.update(cipherBytes);

             // This is where I get exception
            byte[] plaintext = cipher.doFinal(cipherBytes);

            String plainrStr = new String(plaintext, "UTF-8").trim();
            long elapsed = System.currentTimeMillis() - start;

            return plainrStr;
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] fromBase64(String base64) {
        return Base64.decode(base64, Base64.NO_WRAP);
    }
4

3 回答 3

1
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

cipher.init(Cipher.DECRYPT_MODE, key);
cipher.update(cipherBytes);

// byte[] plaintext = cipher.doFinal(cipherBytes);
//                                   ^-- You shouldn't pass cipherBytes twice.
//                                   v-- instead use the parameter-less method:
byte[] plaintext    = cipher.doFinal();
于 2012-08-24T16:05:48.190 回答
1

当最后一个密文块没有计算为有效的纯文本时,会发生填充异常。如果最后一个密文块损坏或密钥不正确,就会发生这种情况。对于 CBC 模式,如果倒数第二个密文被更改(但您使用的是 ECB 模式加密),也会发生这种情况。

在您的情况下,deriveKeyDES()总是生成一个随机密钥。尽管我们没有得到对安全方法的实际调用,但我认为您使用不同的密钥进行加密和解密。在这种情况下,生成的纯文本很可能不包含有效的填充字节。

Rasmus 的回答肯定指向您的代码中的错误,它会搞砸您的时间并返回纯文本两次,但不会删除BadPaddingException.

于 2012-08-25T11:08:05.273 回答
0

我在一个源代码中遇到了同样的问题,在另一个源代码中遇到了 IllegalBlockSizeException。通过返回编码数据解决了这两个问题,例如:

 public String encrypt(String input) {
    try {
        byte[] inputBytes = input.getBytes("UTF-8");
        byte[] enc = encryptCipher.doFinal(inputBytes);
        // and problem was in return encoding. That's how i fixed it 
        return Base64.encodeToString(enc,Base64.DEFAULT);
        .....
          }
        }

给 ua 解密代码:

 public String decrypt(String input) {
    try {
        byte[] dec = Base64.decode(input.getBytes(), Base64.DEFAULT);
        //here had exception
        byte[] utf8 = decryptCipher.doFinal(dec);
        return new String(utf8,"UTF8");
    } catch (IOException | BadPaddingException | IllegalBlockSizeException e) {
        e.printStackTrace();
    }
    return null;
}

我应该提交,只有在解密方法中才有 BadPaddingException 和 IllegalBlockSizeException byte[] utf8 = decryptCipher.doFinal(dec); (你在同一个地方有例外:byte[] plaintext = cipher.doFinal(cipherBytes);),但真正的错误在于加密方法(返回值)

这就是为什么我建议你在加密方法中使用该代码:

return Base64.encodeToString(enc,Base64.DEFAULT);

PS试图对您的问题给出完整的答案。

于 2017-05-26T23:45:03.910 回答