Cyber Security in Java Applications

Do not miss this exclusive book on Binary Tree Problems. Get it now for free.

In this OpenGenus article, we will look at the core concepts of Cyber Security, secure coding practices that must be implemented to ensure that our applications are secure. The illustrations are going to be done in Java.

Table of contents:

  1. What is Cyber Security
  2. Types of Cyber Security
  3. Key Components of Cyber Security
  4. Secure Coding Practices
  5. Authentication and Authorization
  6. Secure Communication Using HTTPS
  7. Cryptography
  8. Summary

What is Cyber Security

An act of protecting computer systems applications from threats that may take sensitive information and cause harm. Cyber security helps in preserving user privacy, protection of sensitive data and maintaining user trust. We are going to delve deeper into some aspects of Cyber Security and how we can apply them using Java.

Types of Cyber Security

There are many types of Cyber Security that are employed to protect systems from different threats. We are going to take a look on the few main ones:

  1. Application Security

    It is the practice of applying security features within applications to prevent threats such as data breaches, malware, and ransomware. In the context of Java development, ensuring strong application security involves, continous security testing using JUnit, following security standards in Java such as input validation, handling errors properly and secure data storage using encryption.
  2. Cloud Security

    Cloud Security is applying security features to protect data, applications and infrastructure which is stored in the cloud. Measures such as authorization, multi-factor authentication and use of Virtual Private Clouds (VPCs) can be implemented to enhance security of cloud resources.
  3. Network Security

    Network Security focuses on the procedures that are taken to protect network infrastructure from misuse or unauthorized access. Tools such as firewalls, intrusion detection and protection systems must be implemented to increase the security of the network. Using Java, we can implement secure communication between clients and servers using HTTPS instead of HTTP. There are libraries such as Apache HttpClient that we can utilize for us to make secure HTTP requests.
  4. Information Security

    It is the practice of protecting information from unauthorized access, alteration and disruption. Information security evolves around the "CIA" triad which stands for Confidentiality, Integrity and Availability. This means that information should only be accessible to individuals authorized, information must be accurate and reliable, and information must always be available and accessible to users when needed.

Key Components of Cyber Security

Confidentiality, Integrity, Availability (CIA triad)

CIA triad states that data should be private, only accessible to authorized users only. To achieve this, we utilize data encryption mechanisims by using Java's inbuilt cryptography libraries such as Cypher, MessageDigest and KeyGenerator (will be illustrated in Encryption below). Java has a set of cryptography libraries in the Java Cryptography Architecture(JCA) which developers can use classes such as Cipher to implement encyption mechanisms ensuring that data remains confidencial. Data must be accurate, meaning that it has to be free of errors, and inconsistencies. It has to match the real world entity it is supposed to represent. An entity is an object that we gather data about, for example a human. Availability means that data must always be available for access by authorized users any day, any time.

Authorization and Authentication

Authentication is a technique in which a user is identified to verify if they are allowed access to the system. This is done by prompting the user for user name and a unique password they would have created. If the credentials match, they will be given access. Authorization on the other hand is a technique that is used to give privileges to users who already have access to the system. Some privileges may include giving permission to read data only, while others can be given permissions to read and modify data. More on this will be explained in Secure Coding Practices section.

Secure Coding Practices

Secure coding practices are techniques that are done by developers that aim to make sure that the code written prevents vulnerabilities thereby enhancing the overall security of applications built. It helps to protect sensitive data from unauthorized access by implementing encryption, authentication and proper access control methods. Code that is written can either prevent attacks or become a gateway to attacks. Let us consider this example:

 public ResultSet getData(String userInput) throws SQLException {
    String query = "SELECT * FROM users WHERE username = '" + userInput + "'";
    Statement statementObject = connection.createStatement();
    ResultSet result = statementObject.executeQuery(query);
    return result;
}
  }

The above example illustrates a scenario where the user input can be directly concatenated in the SQL query and the user of the Statement object which is a bad coding practice since it makes the code vulnerable to SQL injection attacks due to the exposed userInput.

To mitigate this, we can use the PreparedStatement object which does not allow us to concatenate the user input directly but instead allows us to use a placeholder "?", then use the setString method which helps us bind the userInput to the placeholder "?":

public class getData(String userInput) {
   private int rowsAffected;
   String query ="SELECT * FROM users WHERE username = ?";
   try(PreparedStatement statement = connection.prepareStatement(query)) {
   statement.setString(1,userInput);
   rowsAffected = statement.executeUpdate();
       } catch(SQLException e) {
   e.printStackTrace();
     }
   }

The above code is a much better version of the first one because this practice prevents SQL injection attacks. Unlike the Statement object that concatenates user input into SQL queries, which can lead to SQL injection attacks, PreparedStatement automatically sanitizes inputs. This prevents malicious SQL injection attacks.

Authentication and Authorization

  1. Authentication:
    It is the process of identifying a user trying to log in and checking if they are allowed to access a resource or system. This ensures that the identity of the user is confirmed and the are trusted to gain access to the system.
    The process usually goes like this:
  • The user provides their credentials i.e. username and password.
  • The system checks the credentials provided and verifies with the stored credentials to confirm the identity of the user.
  • If the credentials match, the user is granted access to the requested resource.

Example:

import java.util.Scanner;
    public class UserLogin{
    public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    System.out.println("Username: );
    String username = scanner.nextLine();
    System.out.println("Password: );
    String password = scanner.nextLine();
    if (userAuthentication(username, password)) {
    System.out.println("Access granted, welcome " + username);
   } else {
   System.out.println("Access Denied");
   }
       }
   }

The above example simulates the core concept of user authentication. the user is asked to input their username and password. When the fields are entered, a method called userAuthentication is called, this method is supposed to verify the credentials given by the user with those in the database.

  1. Authorization:
    Authorization is done after authentication once the user has been granted access. Authorization determines what actions and resources that the user is allowed to access.
    The process of authorization goes like this:
  • Users are assigned specific roles with different permissions. For example a user with admin rights might be granted all permissions than a regular user.
  • Each time a user tries to preform an action, the system verifies whether they have the required permissions to perform that action.

Let us consider this example:

public class Authorize {
    public static void main(String[] args) {
        //defined user roles
        String[] userRoles = {"ROLE_USER", "ROLE_ADMIN"};

        // Here we check if the user has admin privileges
        if (hasAdminPrivileges(userRoles)) {
            System.out.println("You can access this resource.");
        } else {
            System.out.println("You cannot access this resource. Insufficient privileges.");
        }
    }

    static boolean hasAdminPrivileges(String[] userRoles) {
        // checking if the user has admin roles
        for (String role : userRoles) {
            if (role.equals("ROLE_ADMIN")) {
                return true;
            }
        }
        return false;
    }
}

The above example illustrates how we can add user roles to particular users within a system, checks if a particular logged in user has specific priviledges admin stored in the userRoles array. The hasAdminPrivileges method checks if the user has ROLE_ADMIN role then returns true. The main method then verifies and gives access to the user if they posses the ROLE_ADMIN role.

Secure Connection Using HTTPS

Hyper Text Transfer Protocol Secure is the secure version of HTTP, which is the protocol that is used to sent data over the internet. The difference between HTTPS and HTTP is the security layer that was added to HTTPS. HTTPS secures data ensuring that sensitive information is hidden from the outside world whilst being sent over the internet. This prevents unauthorized individuals from intercepting the data.

The following snippet illustrates how we can implement HTTPS connections using java.

URL url = new URL("https://mysite.com/api/data");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

The code above established a connection to the URL given and then interacts with the remote server using HttpsURLConnection object.

Cryptography

Cryptography is a method in which data is secured (encrypted), ensuring that the person who is supposed to access the data is the only one who can decrypt it using a key. There are 2 main concepts in cryptography namely Encryption and Decryption.

The main objective of Cryptography revolves around:

  1. Confidentiality
    The rightful owner of the data is the one who is supposed to see it. This means that the key to decrypt the data must only be in possession of the owner of the data.
  2. Integrity:
    We should be able to verify that data is accurate, it must not be altered or deleted without the consent of the owner.
  3. Authentication
    Verifying the identity of the user(s) during login and the communication between the 2 parties

Encryption

It is a process of converting plain text into cipher text by using a predefined algorithm and a key. Any easy example of encryption method is the Caesar Cipher. This was done in a way such that every letter n the alphabet was rotated (added) 3 times forward meaning the E would become H and Z would become C. Here is an illustration of Ceasar Cipher:

public class CaesarCipher {
    public static String encrypt(String plaintext, int shift) {
        StringBuilder ciphertext = new StringBuilder();

        // Iterating through each character in the plaintext string
        for (char character : plaintext.toCharArray()) {
            // Checking if the character is a letter or not
            if (Character.isLetter(character)) {
                // Determining the base if the character is either uppercase or lowercase. the base is either a or A
                char base = Character.isLowerCase(character) ? 'a' : 'A';

                // shifting characters, 26 represents all letters in the alphabet
                ciphertext.append((char) ((character - base + shift) % 26 + base));
            } else {
                // if the character is not alphabetic, it is unchanged
                ciphertext.append(character);
            }
        }
        // we then return the encrypted text
        return ciphertext.toString();
    }
    }

Main Class:

 public static void main(String[] args) {
        String text = "Encryption in Java!";
        int shift = 3;

        // Encrypting the text
        String encryptedText = encrypt(text, shift);

        System.out.println("Encrypted Text: " + encryptedText);
    }

Output:

Encrypted Text: Hqfubswlrq lq Mdyd!

The above program is an example of the Caesar Cipher, it takes a string, loops through each character in the string, extracts each character from the string, checks if each character is uppercase or lowercase, if it is lowercase the base character is set to 'a' and if it is lowercase, it is set to 'A'. Then characters are then shifted by subtracting the base plus the shift index we want and everything divided by 26 (which represents the number of letters in the alphabet). When the process is done, we return the new characters and then print them to the screen.

This illustrates the basic steps in encrypting data for our programs. Though it is not recommended to use the Ceasar Cipher for encrypting data, it gives the basic understanding of how encryption should be done. Nowadays much more secure algorithms are now being used. These are:

  1. Advanced Encryption Standard (AES)
  2. Rivest-Shamir-Adleman (RSA)

Java is a bit handy when it comes to encryption. It provides a robust framework specifically for cryptography through what is known as the Java Cryptography Architecture (JCA). This architecture contains everything needed for encryption and decryption. It also contains API's such as javax.cypto package which contains classes meant for encryption and decryption. The classes are: Cipher, KeyGenerator, SecretKey, StandarCharsets among others.

Decryption

Decryption is now the opposite of encryption, instead of encoding the data, the algorithm does the reverse (decoding) using a specified key that was given during the encryption process. In the context of the Caesar Cipher, the key which was provided is the shift value applied during encryption. Here is how the process works:

  1. Get the encrypted data
  2. Apply the decryption algorithm
  3. Use the decryption key
  4. Reverse the character transformation

The characters were shifted forward by 3 positions during the encryption process, now they are shifted backward by 3 positions during decryption. Here is a code snippet that could be used. Note that most of the code remains the same except for using a negative shift value in place of the positive one.

public static String decrypt(String encryptedMessage, int shift) {
// Decryption code is the same as the encryption on except of a negative shift
        return encrypt(encryptedMessage, -shift);
        }

Summary

We have looked at different aspects of Cyber Security and how we can safeguard the applications we code, networks and protecting data whilst following guidelines that make our data safe. Secure coding practices should become our point of defence against vulnerabilities and attacks. Encrypting data before it is stored is crucial to prevent unauthorized access data. We learned about giving user based roles through authorization and only allowing access to data to authorized individuals by authenticating them first. Also using HTTPS can ensure that all communications are secured by encrypting data before it is sent.

Sign up for FREE 3 months of Amazon Music. YOU MUST NOT MISS.