我有一个问题,当解密的数据,我从SQL在java中获得。
我要做的是发送加密的信息到SQL数据库,然后从数据库中获取并解密它,但我得到这个异常:
javax.crypto。BadPaddingException:给定的最终块不正确垫。如果在解密过程中使用了坏密钥,则可能出现此类问题。
可能是什么问题,我该如何解决它?我如何保存每个密码的密钥?
下面是我的代码:import java.sql.*;
import java.util.Base64;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.spec.*;
public class try_3 {
public static SecretKey getKeyFromPassword(String Mpass, String salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(Mpass.toCharArray(), salt.getBytes(), 65536, 256);
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return secret;
}
public static IvParameterSpec generateIv() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
public static String encryptPasswordBased(String plainText, SecretKey key, IvParameterSpec iv)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
return Base64.getEncoder()
.encodeToString(cipher.doFinal(plainText.getBytes()));
}
public static String decryptPasswordBased(String cipherText, SecretKey key, IvParameterSpec iv)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, key, iv);
return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)));
}
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException,
BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException, InvalidKeySpecException {
// TODO Auto-generated method stub
String plainText = "Hi";
String password = "Hi123";
String salt = "12345678";
IvParameterSpec ivParameterSpec = generateIv();
SecretKey key = getKeyFromPassword(password,salt);
///Encrypt///
String cipherText = encryptPasswordBased(plainText, key, ivParameterSpec);
try {
Connection myConn = DriverManager.getConnection("jdbc:mysql://localhost:8889/Account", "root", "root");
PreparedStatement st = myConn.prepareStatement("insert into Encryption");
st.executeUpdate("INSERT INTO Encryption (pass) VALUE ('"+cipherText+"')");
System.out.println("The Cipher Text has been insteld ");
st.close();
}
catch (Exception exc) {
exc.printStackTrace();
}
///Decrypt///
try {
Connection myConn = DriverManager.getConnection("jdbc:mysql://localhost:8889/Account", "root", "root");
Statement myStmt = myConn.createStatement();
int id= 12;
ResultSet myRs = myStmt.executeQuery("SELECT pass FROM Encryption WHERE ID = '" + id + "' ");
while (myRs.next()) {
String encreptedText= myRs.getString("pass");
String decryptedCipherText = decryptPasswordBased(encreptedText, key, ivParameterSpec);
System.out.println("The decrypted Cipher Text: "+decryptedCipherText);
}
}
catch (Exception exc) {
exc.printStackTrace();
}
}
}
注意:不发生此异常的唯一方法是在同一运行中加密和解密相同的密码(使用相同的密钥)。因此,我所做的是在解密时添加id(要添加的密码的id),以便它可以看到相同的密钥。我知道这是一个不方便的方法来解决这个问题,但我是一个新的安全,我不知道如何解决它。
如果您正在存储密码,如pass
列所示,那么通过使用单向散列函数进行密码存储,系统实际上更安全。如果您的应用程序可以读取密码,那么入侵该应用程序的黑客就可以读取用户的密码。哈希也比加密更容易实现。
如果您不存储密码,而是存储其他个人身份信息(PII),那么加密是有用的。在解码之前和之后检查原始二进制,确保字符串长度相同并且没有字节受到影响。