【问题标题】:Java AES String decrypting "given final block not properly padded"Java AES字符串解密“给定的最终块未正确填充”
【发布时间】:2014-07-26 19:54:31
【问题描述】:

对于所有仇恨者,我阅读了许多类似的主题,但没有一个是有帮助的。

例如。这里javax.crypto.BadPaddingException: Given final block not properly padded error while decryption或这里Given final block not properly padded

我想加密然后解密字符串。阅读许多关于 “给定最终块未正确填充”异常,但这些解决方案均无效。

我的班级:

package aes;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.JOptionPane;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class EncryptionExample {

private static SecretKeySpec    key;
private static IvParameterSpec  ivSpec;
private static Cipher           cipher; 
private static byte[]           keyBytes;
private static byte[]           ivBytes;
private static int              enc_len;

public static void generateKey() throws Exception
        {
        
            String complex = new String ("9#82jdkeo!2DcASg");
            keyBytes = complex.getBytes();
            key = new SecretKeySpec(keyBytes, "AES");

            complex = new String("@o9kjbhylK8(kJh7"); //just some randoms, for now
            ivBytes = complex.getBytes();
            ivSpec = new IvParameterSpec(ivBytes);

            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        }
        
        public static String encrypt(String packet) throws Exception
        {
            byte[] packet2 = packet.getBytes();
            cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
            byte[] encrypted = new byte[cipher.getOutputSize(packet2.length)];
            enc_len = cipher.update(packet2, 0, packet2.length, encrypted, 0);
            enc_len += cipher.doFinal(encrypted, enc_len);
            
            return packet = new String(encrypted);
        }
        
        public static String decrypt(String packet) throws Exception
        {
            byte[] packet2 = packet.getBytes();
            cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
            byte[] decrypted = new byte[cipher.getOutputSize(enc_len)];
            int dec_len = cipher.update(packet2, 0, enc_len, decrypted, 0);
HERE EXCEPTION>>>>> dec_len += cipher.doFinal(decrypted, dec_len);  <<<<<<<<<
            
            return packet = new String(decrypted);
        }
        
        
        // and display the results
    public static void main (String[] args) throws Exception 
    {
        
          // get the text to encrypt
        generateKey();
        String inputText = JOptionPane.showInputDialog("Input your message: ");
        
        String encrypted = encrypt(inputText);
        String decrypted = decrypt(encrypted);            
                
        JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
                    "Encrypted:  " + new String(encrypted) + "\n"
                      +  "Decrypted: : " + new String(decrypted));
          .exit(0);
    }
}

问题是,当我解密字符串时(大约 4/10 的镜头),我得到了这个异常:

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:479)
at javax.crypto.Cipher.doFinal(Cipher.java:2068)
at aes.EncryptionExample.deszyfrujBez(EncryptionExample.java:HERE tag)
at aes.EncryptionExample.main(EncryptionExample.java:Main starting)

有人知道要在这里更改什么(键?*.doFinal() 方法?)以使其工作吗?

@ 对于那些好奇的人 - 方法必须是静态的,因为这是更大的东西的一部分;)

【问题讨论】:

标签: java encryption aes badpaddingexception


【解决方案1】:

加密的结果是二进制数据。在大多数情况下,它不能被解释为有效的字符串编码。因此,对new String(encrypted) 的调用很可能会扭曲加密的字节,并且在执行packet.getBytes() 之后,您最终会得到一个具有不同内容的字节数组。

现在解密失败,因为密码文本已更改。填充字节未正确恢复,无法删除。

要解决这个问题,不要将密码文本转换为字符串,保留字节数组。

【讨论】:

  • 我不能保留字节数组,这就是重点;(而且字符串也保留了填充字节。当我想打印它时,它会打印出类似“printed_text_[][][ ][][][][]" 其中 [] 是一个填充字节(在控制台中只是一个正方形)
  • 如果您必须将字节数组转换为字符串,请使用可以恢复二进制内容的编码,例如 base64。
  • 不幸的是,base 64 不支持 Â 符号等,AES 使用它们:(我应该搜索这样的编码;)
  • Base64 确实支持 'Â'。如果你 Base64 编码扩展的 ASCII 0xC2 'Â' 你会得到“w4I =”。您将明文的字节数组加密为密文的字节数组,然后 Base64 对密文进行编码以携带它。对密文进行解码,将密文的字节数组解密为明文的字节数组。
【解决方案2】:

当您使用byte[] packet2 = packet.getBytes() 时,您将根据默认编码转换字符串,例如可能是UTF-8。没关系。但是随后您将密文转换回这样的字符串:return packet = new String(encrypted),如果稍后在解密()中与另一个 byte[] packet2 = packet.getBytes() 之间没有往返到同一个字节数组,这可能会给您带来麻烦。

试试这个:return packet = new String(encrypted, "ISO-8859-1")byte[] packet2 = packet.getBytes("ISO-8859-1")——这不是我想要的,但它应该往返字节数组。

【讨论】:

    猜你喜欢
    • 2015-05-22
    • 2015-03-31
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    • 2014-01-22
    • 1970-01-01
    相关资源
    最近更新 更多