Open In App

Create a Simple Login Web Application with Encrypted Password in Java

Last Updated : 01 Jun, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Security is an important concept in any web application. We need to have the passwords stored in an encrypted way i.e. the passwords are not easily accessible by hackers or unauthorized users. Let’s see a small demo application in this article using MySQL, Java, Servlet, and JSP technology. 

Step by Step Implementation

Required MySQL Script

-- Here GEEKSFORGEEKS is the db name
create table GEEKSFORGEEKS.login_key (
  keyValue varchar(255)
  );

In this keyValue a random value has to be inserted. That value should be time inserted one and by using that we can play around with encryption and decryption. Code to have a random value insertion.

Java




public static final String AES = "AES";
// This method generates a random key and stores in
// login_key table In the full program, let us see whole
// connection details
private void oneTimeKeyGeneration()
{
    try {
        KeyGenerator keyGen = KeyGenerator.getInstance(AES);
        keyGen.init(128);
        SecretKey sk = keyGen.generateKey();
        String key = byteArrayToHexString(sk.getEncoded());
        System.out.println("key:" + key);
        getAndStoreLoginKey(key);
    }
    catch (Exception ex) {
        System.out.println(ex.getMessage());
    }
}
private static String byteArrayToHexString(byte[] b)
{
    StringBuffer sb = new StringBuffer(b.length * 2);
    for (int i = 0; i < b.length; i++) {
        int v = b[i] & 0xff;
        if (v < 16) {
            sb.append('0');
        }
        sb.append(Integer.toHexString(v));
    }
    return sb.toString().toUpperCase();
}
 
private void getAndStoreLoginKey(String key)
{
 
    try {
        Class.forName("com.mysql.cj.jdbc.Driver")
            .newInstance();
        // Class.forName("com.mysql.jdbc.Driver");
        conn = DriverManager.getConnection(
            "root", "admin");
 
        String sql
            = "INSERT INTO login_key(keyValue) VALUES(?)";
 
        PreparedStatement pst = conn.prepareStatement(sql);
 
        pst.setString(1, key);
        pst.executeUpdate();
    }
    catch (ClassNotFoundException ex) {
        Logger
            .getLogger(
                EncryptAndStorePassword.class.getName())
            .log(Level.SEVERE, null, ex);
    }
    catch (SQLException ex) {
        System.out.println("Exception.." + ex.getMessage());
    }
    catch (InstantiationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}


As the random key is inserted, we may be getting values like below

 

Let us create the ‘GEEKPORTALLOGIN’ table and create 2 entries into it

CREATE TABLE GEEKSFORGEEKS.GEEKPORTALLOGIN (id INT NOT NULL,
   loginName VARCHAR(20) default NULL,
   password VARCHAR(45) default NULL,
   PRIMARY KEY (id)
);
INSERT INTO GEEKSFORGEEKS.GEEKPORTALLOGIN VALUES(1,'GEEKA','GEEKA');
INSERT INTO GEEKSFORGEEKS.GEEKPORTALLOGIN VALUES(2,'GEEKB','GEEKB');

 

Using the key mentioned in “Key Image”, the password can be encrypted by using the code below

Java




import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
 
public class EncryptAndStorePassword {
    Connection conn = null;
    public static final String AES = "AES";
    String key = null;
    public Connection getConnection()
    {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver")
                .newInstance();
            conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/geeksforgeeks?useSSL=false",
                "root", "admin");
 
            Statement st;
 
            st = conn.createStatement();
            ResultSet rs = st.executeQuery(
                "select * from login_key");
            // Get the key value from login_key
            while (rs.next()) {
                key = rs.getString("keyValue");
            }
            System.out.println("key=" + key);
        }
        catch (ClassNotFoundException ex) {
            Logger
                .getLogger(
                    EncryptAndStorePassword.class.getName())
                .log(Level.SEVERE, null, ex);
        }
        catch (SQLException ex) {
            System.out.println("Exception.."
                               + ex.getMessage());
        }
        catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return conn;
    }
    private void closeConnection()
    {
        try {
            conn.close();
            conn = null;
        }
        catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    // Utility method taking input as byte array and giving
    // String as output
    private static String byteArrayToHexString(byte[] b)
    {
        StringBuffer sb = new StringBuffer(b.length * 2);
        for (int i = 0; i < b.length; i++) {
            int v = b[i] & 0xff;
            if (v < 16) {
                sb.append('0');
            }
            sb.append(Integer.toHexString(v));
        }
        return sb.toString().toUpperCase();
    }
    // Utility method taking input as String and giving byte
    // array as output
    private static byte[] hexStringToByteArray(String s)
    {
        byte[] b = new byte[s.length() / 2];
        for (int i = 0; i < b.length; i++) {
            int index = i * 2;
            int v = Integer.parseInt(
                s.substring(index, index + 2), 16);
            b[i] = (byte)v;
        }
        return b;
    }
 
    public EncryptAndStorePassword(String tableName)
    {
        getConnection();
        // oneTimeKeyGeneration();//This has to be done only
        // one time. Based on the key, password are getting
        // encrypted and using this key only decrypt will
        // happen and check for username and password
        // combination
        doSelectAndUpdate(tableName);
        closeConnection();
    }
 
    private void doSelectAndUpdate(String tableName)
    {
        doSelect("GEEKPORTALLOGIN");
        // Passing table name will be a good approach as it
        // can do for any table. Just change table name alone
    }
    // This is the one time approach of storing key value in
    // login_key
    private void getAndStoreLoginKey(String key)
    {
 
        try {
 
            String sql
                = "INSERT INTO login_key(keyValue) VALUES(?)";
 
            PreparedStatement pst
                = conn.prepareStatement(sql);
 
            pst.setString(1, key);
            pst.executeUpdate();
        }
        catch (SQLException ex) {
            System.out.println("SQLException.."
                               + ex.getMessage());
        }
    }
    // This is the one time approach of storing key value in
    // login_key
    private void oneTimeKeyGeneration()
    {
        try {
            KeyGenerator keyGen
                = KeyGenerator.getInstance(AES);
            keyGen.init(128);
            SecretKey sk = keyGen.generateKey();
            String key
                = byteArrayToHexString(sk.getEncoded());
            System.out.println("key:" + key);
            getAndStoreLoginKey(key);
        }
        catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }
    // Get the details from GEEKPORTALLOGIN and update
    // encrypted password
    private void doSelect(String tableName)
    {
        Statement st;
        String query = null, password = null,
               userName = null;
        query = "SELECT * FROM GEEKPORTALLOGIN";
 
        try {
            st = conn.createStatement();
            ResultSet rs = st.executeQuery(query);
            while (rs.next()) {
                userName = rs.getString("loginName");
 
                password = rs.getString("password");
                byte[] passwordByte
                    = hexStringToByteArray(key);
                System.out.println("keyValue.." + key);
                SecretKeySpec sks = new SecretKeySpec(
                    passwordByte,
                    EncryptAndStorePassword.AES);
                Cipher cipher = Cipher.getInstance(
                    EncryptAndStorePassword.AES);
                cipher.init(Cipher.ENCRYPT_MODE, sks,
                            cipher.getParameters());
                byte[] encrypted
                    = cipher.doFinal(password.getBytes());
                String encryptedpwd
                    = byteArrayToHexString(encrypted);
                // System.out.println("****************
                // Encrypted Password  ****************");
                System.out.println(encryptedpwd);
                // System.out.println("****************
                // Encrypted Password  ****************");
                doUpdate(encryptedpwd, userName,
                         "GEEKPORTALLOGIN");
            }
        }
        catch (SQLException ex) {
            Logger
                .getLogger(
                    EncryptAndStorePassword.class.getName())
                .log(Level.SEVERE, null, ex);
        }
        catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
    }
 
    // Updating encrypted password for the users
    private void doUpdate(String password, String userName,
                          String tableName)
    {
        System.out.print("\n[Performing UPDATE] ... ");
        try {
            Statement st = conn.createStatement();
            String sqlUpdate = null;
 
            sqlUpdate = "UPDATE GEEKPORTALLOGIN "
                        + "SET password = ? "
                        + "WHERE loginName = ?";
 
            PreparedStatement pstmt
                = conn.prepareStatement(sqlUpdate);
 
            pstmt.setString(1, password);
            pstmt.setString(2, userName);
 
            int rowAffected = pstmt.executeUpdate();
            System.out.println(String.format(
                "Row affected %d", rowAffected));
        }
        catch (SQLException ex) {
            System.err.println(ex.getMessage());
        }
    }
 
    public static void main(String args[])
        throws NoSuchAlgorithmException
    {
        EncryptAndStorePassword encryptAndStorePassword
            = null;
        // Open a connection
        try {
            encryptAndStorePassword
                = new EncryptAndStorePassword(
                    "GEEKPORTALLOGIN");
        }
        finally {
            // close connections
            // nullify variables etc.,
        }
    }
}


On execution of this plain java program, we can see the output as

 

At the same time, we can able to see MySQL output as

 

Now let us have a small web application that has a simple login form. There we will be providing credentials as GEEKA/GEEKA only. But still, the application can able to Login.

 

Let us see the bean, DAO, and servlet files now

LoginBean.java

Java




import java.io.Serializable;
 
public class LoginBean implements Serializable {
 
    private static final long serialVersionUID = 1L;
    // equivalent to GEEKPORTALLOGIN, specifiers are given
    // and corresponding getter and setter
    private String loginName;
    private String password;
 
    public String getLoginName() { return loginName; }
 
    public void setLoginName(String loginName)
    {
        this.loginName = loginName;
    }
 
    public String getPassword() { return password; }
 
    public void setPassword(String password)
    {
        this.password = password;
    }
}


LoginDao.java

Java




import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import net.gfg.login.bean.LoginBean;
 
public class LoginDao {
 
    public boolean validate(LoginBean loginBean)
        throws ClassNotFoundException
    {
        boolean status = false;
 
        Class.forName("com.mysql.jdbc.Driver");
 
        try {
            Connection connection = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/geeksforgeeks?useSSL=false",
                "root", "admin");
            String key = null;
            Statement st;
 
            st = connection.createStatement();
            ResultSet rs = st.executeQuery(
                "select * from login_key");
            while (rs.next()) {
                key = rs.getString("keyValue");
            }
            System.out.println(
                "key.." + key); // This value is a one time
                                // generated one
            // As encryption occurred using this key,
            // decryption also should occur with this key.
 
            // Step 2:Create a statement using connection
            // object
            PreparedStatement preparedStatement
                = connection.prepareStatement(
                    "select * from GEEKPORTALLOGIN where loginName = ?");
            preparedStatement.setString(
                1, loginBean.getLoginName());
 
            // For the logged in username, get the password
            rs = preparedStatement.executeQuery();
            String encryptedPassword = null;
            while (rs.next()) {
                // As it is taken from db, we will get
                // encrypted one only
                encryptedPassword
                    = rs.getString("password");
            }
            // Here we need to get the decrypted password
            String decrypptedPassword
                = decryptPassword(key, encryptedPassword);
            // check the decrypted password and the user
            // entered password are same. it should match and
            // then we can say login is success
            if (decrypptedPassword != null
                && decrypptedPassword.equalsIgnoreCase(
                    loginBean.getPassword())) {
                status = true;
            }
        }
        catch (SQLException e) {
            // process sql exception
            displaySQLException(e);
        }
        return status;
    }
    public byte[] hexStringToByteArray(String s)
    {
        byte[] b = new byte[s.length() / 2];
        for (int i = 0; i < b.length; i++) {
            int index = i * 2;
            int v = Integer.parseInt(
                s.substring(index, index + 2), 16);
            b[i] = (byte)v;
        }
        return b;
    }
 
    public String decryptPassword(String key,
                                  String encryptedPassword)
    {
        String decryptedPassword = null;
        try {
 
            byte[] bytekey = hexStringToByteArray(key);
            SecretKeySpec sks
                = new SecretKeySpec(bytekey, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, sks);
            byte[] decrypted = cipher.doFinal(
                hexStringToByteArray(encryptedPassword));
            decryptedPassword = new String(decrypted);
        }
        catch (NoSuchAlgorithmException ex) {
            System.out.println(ex.getMessage());
        }
        catch (NoSuchPaddingException ex) {
            System.out.println(ex.getMessage());
        }
        catch (InvalidKeyException ex) {
            System.out.println(ex.getMessage());
        }
        catch (IllegalBlockSizeException ex) {
            System.out.println(ex.getMessage());
        }
        catch (BadPaddingException ex) {
            System.out.println(ex.getMessage());
        }
        return decryptedPassword;
    }
 
    private void displaySQLException(SQLException ex)
    {
        // for (Throwable e : ex) {
        if (ex instanceof SQLException) {
            ex.printStackTrace(System.err);
            System.err.println(
                "SQLState: "
                + ((SQLException)ex).getSQLState());
            System.err.println(
                "Error Code: "
                + ((SQLException)ex).getErrorCode());
            System.err.println("Message: "
                               + ex.getMessage());
            Throwable t = ex.getCause();
            while (t != null) {
                System.out.println("Cause: " + t);
                t = t.getCause();
            }
        }
        //}
    }
}


LoginServlet.java

Java




import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.gfg.login.bean.LoginBean;
import net.gfg.login.database.LoginDao;
 
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private LoginDao loginDao;
 
    public void init() { loginDao = new LoginDao(); }
 
    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response)
        throws ServletException, IOException
    {
 
        String loginName
            = request.getParameter("loginName");
        String password = request.getParameter("password");
        LoginBean loginBean = new LoginBean();
        loginBean.setLoginName(loginName);
        // Here we need to write the decryption logic
        // GEEKSFORGEEKS.login_key should be the medium for
        // encryption as well as decryption
        loginBean.setPassword(password);
        // Inside validate, user entered password should
        // match with the password available in db. db
        // password is in encrypted mode. It has to undergo
        // decryption techniques and we should get the
        // password back
        try {
            if (loginDao.validate(loginBean)) {
                response.sendRedirect("loginsuccess.jsp");
            }
            else {
                // HttpSession session =
                // request.getSession();
            }
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}


Login.jsp

Java




<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Login Form by using Encrypted password</title>
</head>
<body>
    <div align="center">
        <h1>Login Form</h1>
        <form action="<%=request.getContextPath()%>/login" method="post">
            <table style="with: 100%">
                <tr>
                    <td>Login</td>
                    <td><input type="text" name="loginName" /></td>
                </tr>
                <tr>
                    <td>Password</td>
                    <td><input type="password" name="password" /></td>
                </tr>
 
            </table>
            <input type="submit" value="Submit" />
        </form>
    </div>
</body>
</html>


loginsuccess.jsp

Java




<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@page import="net.gfg.login.database.*"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
    <div align="center">
        <h1>You have logged in successfully</h1>
    </div>
</body>
</html>


Program Execution

Need to give GEEKA/GEEKA. As we are following the decryption technique inside the project, the user can able to login successfully.

 

 

We can able to successfully log in

 

Inside the validate method, 

  • For the given login, the password (encrypted one) is fetched from DB
  • Decryption is happening for the retrieved password
  • Then the user-entered password is matched with the decrypted password and if they match, the login is successful.
  • The main important thing is the login_key.keyValue should be generated one Time only and with that, any kind of password can be encrypted and decrypted easily.


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads