尝试解密基于AES的加密文本时出现BadPadding异常 [英] BadPadding exception when trying to decrypt AES based encrypted text

查看:123
本文介绍了尝试解密基于AES的加密文本时出现BadPadding异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题场景::我正在Ubuntu中使用OpenSSL AES-256-CBC模式创建一个加密文件.

Problem Scenario: I am creating an encrypted file using OpenSSL AES-256-CBC mode in Ubuntu.

openssl aes-256-cbc -a -in avengers.txt -out avengers.enc 
test
test
File Content: avengersAssemble
avengers.enc file content: U2FsdGVkX194TyUFrb4gOn86XYaKjKP98YdOlQDJz+t/76mvVmNKl+NyKKUnYwYH

To Decrypt: openssl aes-256-cbc -a -d -in avengers.enc

现在,我想使用Java代码解密此加密文件avengers.enc,即,我只存储此文件的内容和密码(在本例中为test)以对其进行解密.

Now I want to decrypt this encrypted file avengers.enc using java code i.e., I just store this file content and password (in this case test) to decrypt it.

我的目标:我想使用通过上述命令(128或192或256 cbc)加密的密码(对称加密)进行解密.

My Aim: I want to decrypt using a password (symmetric encryption), encrypted from above command (128 or 192 or 256 cbc).

请帮助.

我发现了代码,但显示BadPadding异常.请在链接中按@Maarten Bodewes引用答案.

I found this code but its showing BadPadding exception. Please refer answer post by @Maarten Bodewes in the link.

我从链接中找到的代码:

Code which I found from the link:

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.List;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.util.encoders.Base64;

public class OpenSSLDecryptor {
    private static final Charset ASCII = Charset.forName("ASCII");
    private static final int INDEX_KEY = 0;
    private static final int INDEX_IV = 1;
    private static final int ITERATIONS = 1;

    private static final int ARG_INDEX_FILENAME = 0;
    private static final int ARG_INDEX_PASSWORD = 1;

    private static final String file = 
    "D:\\Eclipse_Workspace\\Cryptography\\avengers.enc";
     private static final String password = "test";

    private static final int SALT_OFFSET = 8;
    private static final int SALT_SIZE = 8;
    private static final int CIPHERTEXT_OFFSET = SALT_OFFSET + SALT_SIZE;

    private static final int KEY_SIZE_BITS = 256;

    /**
     * Thanks go to Ola Bini for releasing this source on his blog.
     * The source was obtained from <a href="http://olabini.com/blog/tag/evp_bytestokey/">here</a> .
     */
    public static byte[][] EVP_BytesToKey(int key_len, int iv_len, MessageDigest md,
            byte[] salt, byte[] data, int count) {
        byte[][] both = new byte[2][];
        byte[] key = new byte[key_len];
        int key_ix = 0;
        byte[] iv = new byte[iv_len];
        int iv_ix = 0;
        both[0] = key;
        both[1] = iv;
        byte[] md_buf = null;
        int nkey = key_len;
        int niv = iv_len;
        int i = 0;
        if (data == null) {
            return both;
        }
        int addmd = 0;
        for (;;) {
            md.reset();
            if (addmd++ > 0) {
                md.update(md_buf);
            }
            md.update(data);
            if (null != salt) {
                md.update(salt, 0, 8);
            }
            md_buf = md.digest();
            for (i = 1; i < count; i++) {
                md.reset();
                md.update(md_buf);
                md_buf = md.digest();
            }
            i = 0;
            if (nkey > 0) {
                for (;;) {
                    if (nkey == 0)
                        break;
                    if (i == md_buf.length)
                        break;
                    key[key_ix++] = md_buf[i];
                    nkey--;
                    i++;
                }
            }
            if (niv > 0 && i != md_buf.length) {
                for (;;) {
                    if (niv == 0)
                        break;
                    if (i == md_buf.length)
                        break;
                    iv[iv_ix++] = md_buf[i];
                    niv--;
                    i++;
                }
            }
            if (nkey == 0 && niv == 0) {
                break;
            }
        }
        for (i = 0; i < md_buf.length; i++) {
            md_buf[i] = 0;
        }
        return both;
    }


    public static void main(String[] args) {
        try {
            // --- read base 64 encoded file ---

            //File f = new File(args[ARG_INDEX_FILENAME]);
            File f = new File(file);
            List<String> lines = Files.readAllLines(f.toPath(), ASCII);
            StringBuilder sb = new StringBuilder();
            for (String line : lines) {
                sb.append(line.trim());
            }
            String dataBase64 = sb.toString();
            byte[] headerSaltAndCipherText = Base64.decode(dataBase64);

            // --- extract salt & encrypted ---

            // header is "Salted__", ASCII encoded, if salt is being used (the default)
            byte[] salt = Arrays.copyOfRange(
                    headerSaltAndCipherText, SALT_OFFSET, SALT_OFFSET + SALT_SIZE);
            byte[] encrypted = Arrays.copyOfRange(
                    headerSaltAndCipherText, CIPHERTEXT_OFFSET, headerSaltAndCipherText.length);

            // --- specify cipher and digest for EVP_BytesToKey method ---

            Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
            MessageDigest md5 = MessageDigest.getInstance("MD5");

            // --- create key and IV  ---

            // the IV is useless, OpenSSL might as well have use zero's
            final byte[][] keyAndIV = EVP_BytesToKey(
                    KEY_SIZE_BITS / Byte.SIZE,
                    aesCBC.getBlockSize(),
                    md5,
                    salt,
                    password.getBytes(ASCII),
                    ITERATIONS); //args[ARG_INDEX_PASSWORD]
            SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES");
            IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]);

            // --- initialize cipher instance and decrypt ---

            aesCBC.init(Cipher.DECRYPT_MODE, key, iv);
            byte[] decrypted = aesCBC.doFinal(encrypted);

            String answer = new String(decrypted, ASCII);
            System.out.println(answer);
        } catch (BadPaddingException e) {
            // AKA "something went wrong"
            throw new IllegalStateException(
                    "Bad password, algorithm, mode or padding;" +
                    " no salt, wrong number of iterations or corrupted ciphertext.");
        } catch (IllegalBlockSizeException e) {
            throw new IllegalStateException(
                    "Bad algorithm, mode or corrupted (resized) ciphertext.");
        } catch (GeneralSecurityException e) {
            throw new IllegalStateException(e);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }        
}

例外:

javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:991)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
    at javax.crypto.Cipher.doFinal(Cipher.java:2164)
    at symmetric.main(symmetric.java:146)

推荐答案

OpenSSL使用EVP_BytesToKey并使用消息摘要算法(例如md5sha256等).在上面的代码中,函数EVP_ByteToKey具有MD5传递给的MessageDigest参数,但加密时未在OpenSSL命令中添加MD5.因此,以下是与消息摘要算法(即MD5)一起使用的实际命令.

OpenSSL uses EVP_BytesToKey with uses Message Digest Algorithms like md5, sha256, etc. In the above code the function, EVP_ByteToKey has a MessageDigest parameter to which MD5 is passed but MD5 was not added in the OpenSSL command while encryption. So below is the actual command to be used with the message digest algorithm i.e., MD5.

openssl aes-256-cbc -a -in avengers.txt -out avengers.enc -md md5
 openssl aes-256-cbc -a -d -in avengers.enc -md md5 

要使用任何其他消息摘要算法,只需在MessageDigest md5 = MessageDigest.getInstance("SHA-256");中传递该算法即可.请参考链接.另外,必须在命令中传递-md sha256.请参考手册页获取openSSL

To use any other message digest algorithm just pass that algoriyhm in MessageDigest md5 = MessageDigest.getInstance("SHA-256"); Refer link under MessageDigest Algoritms. Also, have to pass -md sha256 in command. Refer man page for openSSL

这篇关于尝试解密基于AES的加密文本时出现BadPadding异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆