decrypting data from the SQL in java

780 Views Asked by At

I have a problem when decrypting the data that I get from the SQL in java.

What I am trying to do is sending the encrypted info to the SQL database then getting it from the database and decrypting it, but I get this exception:

javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.

What might be the problem, how can I solve it? And how do I save the key for each password?

Here is my code:

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();
              }
            
    }
            



}

Note: The only way this exception doesn’t occur is when encrypting and decrypting the same password in the same run (which use the same key). So, what I did is adding the id (of the password to be added) at the decryption time so it can see the same key. I know that this is an inconvenient way to solve this problem, but I am new to security and I have no idea how to solve it.

1

There are 1 best solutions below

2
On

If you are storing passwords, as indicated by the pass column, then the system is substantially more secure by using a one way hash function for password storage. If your application can read the passwords, then a hacker who has breached the application can read the user's passwords. Hashing is also a lot easier to implement than encryption.

If you aren't storing passwords, and you are storing other personally identifiable information (PII) then encryption is useful. Check the raw binary before and after decoding, make sure the string length is identical and that no bytes were affected.