1

解密从 java 中的 SQL 获得的数据时遇到问题。

我想要做的是将加密信息发送到 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(要添加的密码),以便它可以看到相同的密钥。我知道这是解决这个问题的一种不方便的方法,但我是安全新手,我不知道如何解决它。

4

1 回答 1

0

如果您正在存储密码,如pass列所示,那么系统通过使用单向散列函数来存储密码会大大提高安全性。如果您的应用程序可以读取密码,那么入侵该应用程序的黑客就可以读取用户的密码。散列也比加密更容易实现。

如果您不存储密码,而是存储其他个人身份信息 (PII),则加密很有用。在解码之前和之后检查原始二进制文件,确保字符串长度相同并且没有字节受到影响。

于 2021-02-13T22:15:44.797 回答