Java: Simple AES Encryption Working Example

Post Visual Studio nowadays I am developing more dynamic web applications on Java. So again having a requirement to store passwords securely. After long research found the following piece of code which can be used to encrypt/decrypt secure data using random hash value (private key). This code uses Advanced Encryption Standards (AES) which is the symmetric algorithm.

The code uses basic java security jars and doesnt need any thirdparty base64 jar for encoding and decoding passwords.


AES Class 


import java.util.Arrays;
import java.util.Base64;
import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class AESEcryption {

private static byte[] key;
private static SecretKeySpec secretKeySpec;

 

public static void setKey(String inputKeyValue)
{
MessageDigest sha = null;
try {
key = inputKeyValue.getBytes(“UTF-8”);
sha = MessageDigest.getInstance(“SHA-1”);
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
secretKeySpec = new SecretKeySpec(key, “AES”);
}
catch (Exception e) {
e.printStackTrace();
}

}

public static String encrypt(String strToEncrypt, String secretKeyValue)
{
try
{
setKey(secretKeyValue);
Cipher cipher = Cipher.getInstance(“AES/ECB/PKCS5Padding”);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes(“UTF-8”)));
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}

public static String decrypt(String strToDecrypt, String secretKeyValue)
{
try
{
setKey(secretKeyValue);
Cipher cipher = Cipher.getInstance(“AES/ECB/PKCS5Padding”);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
}


Main Class for testing code


public static void main(String[] args)
{
           // private key
    final String privateKeyVal = "abcdEFGHijklmnOPqrstuvwxyz";
    
    String originalText = "thisisMainText";
    String encryptedData =AESEcryption.encrypt(originalText,privateKeyVal) ;
    String decryptedData =AESEcryption.decrypt(encryptedData,privateKeyVal) ;
    
            // printing all variable data
    System.out.println(originalText);
    System.out.println(encryptedData);
    System.out.println(decryptedData);
}

 

In the above example, longer private Key value gives better-encrypted text. Also, don’t forget to keep private key value isolated. This can be achieved by storing the private key into the read-only file on server-side which is having access to the application user only.
Thanks.
Advertisements

Java/Servlets : Use of JDBC for DB connection with bind parameters

Following is the simple program showing the implementation of connecting to Oracle DB using ODBC driver and fetching data with bind values.

Here DBUtilXE is the utility providing static connection to the Database and function to select data from Database. In below example, I am set fetch size to 1000 which can be lowered down to the smaller number when resultset is small. By default, this value is set t0 10, so in the case of higher return dataset application needs to make that many DB trips to get all data. Values highlighted in blue color are dummy values which need to be updated as per your environment setting.


public class DBUtilXE {

                private static Connection dbConn = null;

                private static PreparedStatement preparedStatement = null;

                private static ResultSet dbResultSet = null;

                private static String DBHost = “120.10.10.10“;

                private static String DBUser = “UserName“;

                private static String DBpass = “Password“;

                private static String DBSID = “XE“;

                private static String DBPort = “1521“;

                static {

                                try{

                                                Class.forName(“oracle.jdbc.driver.OracleDriver”);

                                                }catch(ClassNotFoundException e){

                                                                e.printStackTrace();

                                                }

                                try{

                                                dbConn=DriverManager.getConnection(“jdbc:oracle:thin:@”+ DBHost + “:” + DBPort +”:” + DBSID,DBUser,DBpass);

                                                }catch(SQLException e){

                                                                e.printStackTrace();

                                                }

                                }

                public static ResultSet selectDBRow(String sqlQuery, String[] inpSQLBindParameter ) {

                                try {

                                                if (sqlQuery != null) {

                                                                                  preparedStatement = dbConn.prepareStatement(sqlQuery);

                                                                                  preparedStatement.setFetchSize(1000);

                                                                                for (int i=0;i <inpSQLBindParameter.length;i++){

                                                                                ((PreparedStatement) preparedStatement).setString(i+1, inpSQLBindParameter[i]);

                                                                                }

                                                                                try {

                                                                                                dbResultSet = preparedStatement

                                                                                                                                .executeQuery();

                                                                                                return dbResultSet;

                                                                                } catch (Exception e) {

                                                                                                e.printStackTrace();

                                                                                                return null;

                                                                                }

                                                                } else {

                                                                                return null;

                                                                }

                                } catch (Exception e) {

                                                e.printStackTrace();

                                                return null;

                                }

                }

}


Further main class or any other class can use this class and fetch dataset from the Oracle DB for the given query. Here in the SQL Query I have used bind variables(?) which saves DB time in parsing and also help to hide input value during execution at Database.


,tring sqlQuery = null;

String[] strSQLBindVal ;

ResultSet resultSet = null;

strSQLBindVal = new String[2];

                                                                sqlQuery = “SELECT * FROM USERS WHERE USER_NAME = ? AND PASS_VAL = ? “;

                                                                strSQLBindVal[0] = “sushant“;

                                                                strSQLBindVal[1] = “passval“;

                                                                resultSet = DBUtilXE.selectDBRow(sqlQuery,strSQLBindVal);

                                                                try{

                                                                                if (resultSet != null ) {

                                                                                                while(resultSet.next() ){

                                                                                                                //Printing first column value for each record

                                                                                                                System.out.println(db2MFResuletSet.getString(1));

                                                                                                                //Printing second column value for each record

                                                                                                                System.out.println(db2MFResuletSet.getString(2));

                                                                                                                }

                                                                                                resultSet.close();

                                                                                                }

                                                                }catch(Exception e){

                                                                                e.printStackTrace();

                                                                }


In above explanation I am printing SQL output, this can also be stored into the Array Objects for application use.

Avoiding SQL Injection attacks in Coding

SQL Injection in one of the commonly seen of attacks nowadays. SQL injection means when attacker appends a piece of SQL code into the browser script or as part of the input parameter in order to gain access to the side. Most of the times we fail to put basic validations in the code leaving loopholes which can be easily targeted. Therefore when it comes to validation we should not be allowing any special characters which can be used as a valid SQL execution result in giving access to the attacker. But in some cases, it’s a mandate to allow special characters in the input field such as password field. In such scenario, we must ensure that we are taking complete input value as a text which is explained below.

Here we can see an example for login form where validations are not very good. In this case, the application is taking username/password field and checking whether combination exists at the  DB level and then allows access to the user. We can consider following SQL used to validate login form where both user and password data stored in login_user table.

sqlQuery = “SELECT count(1) FROM LOGIN_USER” +
” WHERE USER_ID =  ‘” + inputUserNameSring + “‘and password = ‘ ” + inputPasswordSring + “‘” ;

If I enter User Name = test and password = test assuming that the combination is not present at DB level. The login form will not provide me access to the main form.

sql_a

But what if I enter the following string in the password field “test’ or ‘1’ = ‘1“. Since we are not filtering password string completely to text field single quote and equal to is becoming part of SQL query. From SQL point of view, this will add another OR condition which is already true which means it will return the count of all rows from the DB as below.

sql_b

As a result, application will grant access to the main form without valid user and password combination. This type of injection is most commonly used to bypass validation forms. Therefore to avoid such bugs we must convert the entire input string into the text field. In the above case, I have now replaced every single quote to additional single quote which will then consider as text and not part of SQL query. Therefore  “test’ or ‘1’ = ‘1” is now changed to  “test” or ”1” = ”1” as below and when it will get executed at DB level will not return any output.

sql_c

As seen above now we have validated input value passed in password field exactly at Database avoiding SQL injections.

The example provided above is the most basic example to explain SQL injections. Hackers do use advanced level of injections, but if we ensure that all critical input parameters are getting validated without leaving any loopholes then such type of attacks can be easily avoided.