尝试解密基于AES的加密文本时出现BadPadding异常 [英] BadPadding exception when trying to decrypt AES based encrypted text
问题描述
问题场景::我正在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
并使用消息摘要算法(例如md5
,sha256
等).在上面的代码中,函数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屋!