![](/img/trans.png)
[英]BadPadding exception when trying to decrypt AES based encrypted text
[英]Tag Mismatch when trying to decrypt encrypted data
我正在為我的Java編程類創建一個項目以創建密碼管理器,並且正在對密碼進行加密和解密。
我的加密程序工作正常,但我不斷收到javax.crypto.AEADBadTagException:標記不匹配! 錯誤。
這是完整的錯誤:
線程“主”中的異常javax.crypto.AEADBadTagException:標記不匹配! 在java.base / com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1116)在java.base / com.sun.crypto.provider.GaloisCounterMode.decryptFinal(GaloisCounterMode.java:580) /com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1053)在java.base / com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)在java.base / com.sun java.base / javax.crypto.Cipher.doFinal(Cipher.java:2202)上的.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)在PasswordVault.Decrypt(PasswordVault.java:89)在PasswordVault.main( PasswordVault.java:27)
我一直在嘗試通過在這里進行研究來自行找出此錯誤,但是我沒有太多運氣或對問題的了解。
這是我的主要課程:
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.ArrayList;
import java.util.Scanner;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.util.Base64;
public class PasswordVault {
private static ArrayList<Password> passwordVault;
public Scanner keyboard = new Scanner(System.in);
public String website;
public String username;
private String password;
private SecretKey key;
public static void main(String[] args) throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException, NoSuchProviderException, InvalidAlgorithmParameterException {
passwordVault = new ArrayList<>();
addPassword();
System.out.println(passwordVault);
//byte [] passwordByte = passwordVault.get(0).getPassword().getBytes();
System.out.println(Decrypt(passwordVault.get(0).getPassword(),generateKey()));
}
public static void addPassword() throws NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, UnsupportedEncodingException, InvalidKeyException, NoSuchProviderException, InvalidAlgorithmParameterException {
Scanner keyboard = new Scanner(System.in);
String website;
String username;
String password;
SecretKey key = null;
System.out.println("Please enter in the website that you would like to store a password:");
website = keyboard.nextLine();
System.out.println("Please enter your username");
username = keyboard.nextLine();
System.out.println("Please enter your password");
password = keyboard.nextLine();
key = generateKey();
savePassword(website,username,password,key);
}
private static ArrayList<Password>savePassword(String website, String username, String password, SecretKey key) throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException, NoSuchProviderException, InvalidAlgorithmParameterException {
String encryptedPassword;
encryptedPassword = Encrypt(password,key);
String stringEncryptedPassword = new String(encryptedPassword);
Password savePass = new Password(website, username, stringEncryptedPassword);
passwordVault.add(savePass);
return passwordVault;
}
public static SecretKey generateKey() throws NoSuchPaddingException, NoSuchAlgorithmException {
SecureRandom random = SecureRandom.getInstanceStrong();
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128, random);
SecretKey key = keyGen.generateKey();
return key;
}
private static String Encrypt(String password, SecretKey key) throws UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchProviderException {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
byte[] iv = new byte[12];
SecureRandom random = SecureRandom.getInstanceStrong();
random.nextBytes(iv);
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte [] bytePassword = password.getBytes("UTF-8");
byte [] encryptedPassword = cipher.doFinal(bytePassword);
/*Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte [] bytePassword = password.getBytes("UTF-8");
byte [] encryptedPassword = cipher.doFinal(bytePassword);
return Base64.getEncoder().encodeToString(encryptedPassword);*/
//return encryptedPassword;
return Base64.getEncoder().encodeToString(encryptedPassword);
}
private static String Decrypt(String password, SecretKey key) throws UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, NoSuchProviderException, InvalidAlgorithmParameterException {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
byte[] iv = new byte[12];
SecureRandom random = SecureRandom.getInstanceStrong();
random.nextBytes(iv);
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, key, spec);
return new String(cipher.doFinal(Base64.getDecoder().decode(password)));
}
//byte [] byteDecryptPassword = cipher.doFinal(password);
// String newPassword = new String(password, "UTF-8");
//Cipher cipher = null;
//cipher = Cipher.getInstance("AES/GCM/NoPadding");
//cipher.init(Cipher.DECRYPT_MODE, key);
/*byte [] bytePassword = new byte[0];
bytePassword = password.getBytes("UTF-8");
byte [] encryptedPassword = new byte[0];
encryptedPassword = cipher.doFinal(bytePassword);*/
}
這是我的密碼對象:
public class Password {
String website;
String login;
String password;
public Password(String website, String login, String password) {
this.website = website;
this.login = login;
this.password = password;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString(){
return "Website: " + website + " Login: " + login + " Password: " + password;
}
}
我現在希望通過測試獲得的是我輸入的密碼的解密純文本版本。現在,我只是一直遇到這個BadTag問題。
任何幫助是極大的贊賞。
只是為了給您一些有關如何編程的想法,讓我們為您展示一個新的PasswordVault
。
當然,您自己的新代碼片段也可以使用,目前避開了所需的密碼存儲設計; 這是一個通用的GCM示例,其中不存儲IV,不具有文件庫等(如果您無法使GCM正常工作,那么這可能是一個好主意)。
請注意,以下代碼片段仍不是安全的保險庫文件,但它顯示了如何以OO方式對故障進行編程。
import static java.nio.charset.StandardCharsets.UTF_8;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Scanner;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
public class PasswordVault {
private static final int KEY_SIZE_BITS = 128;
private static final int GCM_TAG_SIZE_BITS = 128;
private static final int GCM_IV_SIZE_BYTES = 12;
private ArrayList<PasswordEntry> vaultBoxes;
private SecretKey key;
public PasswordVault() throws NoSuchAlgorithmException {
vaultBoxes = new ArrayList<>();
key = generateKey();
}
public void encryptAndStorePasswordEntry(PasswordEntry passwordEntry) throws GeneralSecurityException {
String encryptedPassword = encrypt(passwordEntry.getPassword(), key);
PasswordEntry savePass = new PasswordEntry(passwordEntry.getWebsite(), passwordEntry.getLogin(),
encryptedPassword);
vaultBoxes.add(savePass);
}
public PasswordEntry retrieveAndDecryptPasswordEntry() throws GeneralSecurityException {
// TODO think of a way to retrieve the password for a specific entry
PasswordEntry encryptedPasswordEntry = vaultBoxes.get(0);
String password = decrypt(encryptedPasswordEntry.getPassword(), key);
return new PasswordEntry(encryptedPasswordEntry.getWebsite(), encryptedPasswordEntry.getLogin(), password);
}
public static SecretKey generateKey() throws NoSuchAlgorithmException {
SecureRandom random = SecureRandom.getInstanceStrong();
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(KEY_SIZE_BITS, random);
return keyGen.generateKey();
}
public static String encrypt(String password, SecretKey key) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] iv = generateRandomIV();
GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_SIZE_BITS, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte[] bytePassword = password.getBytes(UTF_8);
byte[] ivCTAndTag = new byte[GCM_IV_SIZE_BYTES + cipher.getOutputSize(bytePassword.length)];
System.arraycopy(iv, 0, ivCTAndTag, 0, GCM_IV_SIZE_BYTES);
cipher.doFinal(bytePassword, 0, bytePassword.length, ivCTAndTag, GCM_IV_SIZE_BYTES);
return Base64.getEncoder().encodeToString(ivCTAndTag);
}
private static byte[] generateRandomIV() {
byte[] iv = new byte[GCM_IV_SIZE_BYTES];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
return iv;
}
public static String decrypt(String encryptedPassword, SecretKey key) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] ivAndCTWithTag = Base64.getDecoder().decode(encryptedPassword);
GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_SIZE_BITS, ivAndCTWithTag, 0, GCM_IV_SIZE_BYTES);
cipher.init(Cipher.DECRYPT_MODE, key, spec);
byte[] plaintext = cipher.doFinal(ivAndCTWithTag, GCM_IV_SIZE_BYTES, ivAndCTWithTag.length - GCM_IV_SIZE_BYTES);
return new String(plaintext, UTF_8);
}
public static void main(String[] args) throws Exception {
PasswordVault vault = new PasswordVault();
PasswordEntry passwordEntry = readPlainPasswordEntry();
vault.encryptAndStorePasswordEntry(passwordEntry);
System.out.println(vault.vaultBoxes);
PasswordEntry decryptedPasswordEntry = vault.retrieveAndDecryptPasswordEntry();
System.out.println(decryptedPasswordEntry);
}
public static PasswordEntry readPlainPasswordEntry() {
try (Scanner keyboard = new Scanner(System.in)) {
System.out.println("Please enter in the website that you would like to store a password:");
String website = keyboard.nextLine();
System.out.println("Please enter your username");
String login = keyboard.nextLine();
System.out.println("Please enter your password");
String password = keyboard.nextLine();
return new PasswordEntry(website, login, password);
}
}
}
如您所見,我還重命名了很多變量,並引入了多個常量。 我已使Vault具有狀態的一個對象,其中包含密鑰和安全條目。
當然,最后,您需要序列化保管庫以存儲沒有密鑰的加密值,該密鑰必須從其他地方存儲/檢索/派生。 您不想混合檢索密碼和存儲密碼條目(我已經重命名了,因為網站和登錄名不是密碼的一部分)。
我還簡化了異常處理和String
處理(如果您曾經執行過new String(string)
則可能會驚訝地發現它內部由return string;
組成)。 為了很好地處理加密異常,請看一下我的答案 。
好的,希望這對您有所幫助。 祝你好運。
我實際上找到了我程序的解決方案。 我不得不結束重構工作,因為我認為我一直在重置iv,這會導致類型不匹配。
這是我完成的工作代碼:
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.ArrayList;
import java.util.Scanner;
public class TestPasswordVault {
private static ArrayList<Password> passwordVault;
public Scanner keyboard = new Scanner(System.in);
public String website;
public String username;
private String password;
private static SecretKey key;
public static void main(String[] args) throws UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchProviderException {
String test = "kittens";
SecureRandom random = SecureRandom.getInstanceStrong();
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128, random);
SecretKey key = keyGen.generateKey();
byte[] iv = new byte[12];
random.nextBytes(iv);
System.out.println(test);
byte [] newTest = doEncrypt(test,iv,random,key);
System.out.println(newTest);
System.out.println(doDecrypt(newTest,iv,random,key));
}
public static byte [] doEncrypt(String password, byte [] iv, SecureRandom random, SecretKey key) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte [] encryptPassword = password.getBytes("UTF-8");
byte[] cipherText = cipher.doFinal(encryptPassword);
return cipherText;
}
public static String doDecrypt(byte [] encrypted, byte [] iv, SecureRandom random, SecretKey key)throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, key, spec);
byte[] plainText = cipher.doFinal(encrypted);
return new String(plainText);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.