DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modern Digital Website Security: Prepare to face any form of malicious web activity and enable your sites to optimally serve your customers.

Containers Trend Report: Explore the current state of containers, containerization strategies, and modernizing architecture.

Low-Code Development: Learn the concepts of low code, features + use cases for professional devs, and the low-code implementation process.

E-Commerce Development Essentials: Considering starting or working on an e-commerce business? Learn how to create a backend that scales.

Related

  • 7 Crucial Questions About Quantum Computing and Cybersecurity
  • Exploring ML.NET Catalogs and Use Cases
  • Essential Security Measures for PDF Documents
  • Exploring the Role of Consensus Algorithms in Distributed System Design

Trending

  • The Guide to SRE Principles
  • Enhancing Observability With AI/ML
  • How to Do a Risk Analysis Service in a Software Project
  • What Is CI/CD? Beginner’s Guide To Continuous Integration and Deployments
  1. DZone
  2. Data Engineering
  3. AI/ML
  4. Encrypting Inside WSO2 ESB Using the AES Algorithm

Encrypting Inside WSO2 ESB Using the AES Algorithm

Encrypting a payload before sending it to storage is the simplest way to ensure security. Learn how to do so using the AES algorithm.

Priyashani Fernando user avatar by
Priyashani Fernando
·
Aug. 23, 17 · Tutorial
Like (4)
Save
Tweet
Share
6.7K Views

Join the DZone community and get the full member experience.

Join For Free

In integration development, you will come across instances where you need to hold a payload in an intermediate place before it reaches its final destination, such as a queue. The problem is that the payload could be readable while it's there, and if the particular container has less security, it's prone to hacking.

The simplest solution is encrypting it before we send it to the temporary storage.

This blog series focuses on a method to handle this problem inside WSO2 ESB. For this example, the AES algorithm will be used for encryption.

In terms of high-level design:

  • There will be an ESB template which the user needs to pass the payload to do the encryption, and for decryption, it needs the encrypted payload alone with the secret key and ivByte, which are the results of the encryption process.

  • Inside the template, a class mediator will be invoked to do the logic.
  • For encryption, a secret key is generated and an ivByte is created, which is the combination that is required to get the real info from the encrypted string. Later, this can be bit altered to pass a secret key for encryption.

Below is the simple design diagram of the final result.

wso2-encryptor : Design diagram

That's all for the description. Let's start with coding.

Since this is a WSO2 project, create each of below projects:

  1. ESB config project.
  2. Composite application project.

  3. Mediator project.

First, we will start with the Mediator project.

The encryption class (EncryptorAES.java) will have three main methods: encrypt(), decrypt(), and generateSecretKey(). The javax.crypto.Cipher class is used for encryption, and as you can see in decryption, an extra parameter is passed for the cipher.init() method. This is because, to decrypt it, we need extra information from the cipher instance after encryption. To understand the use of ivByte, encrypt a payload with the same encryption key few times; you will see that even though you keep the inputs the same, the encrypted result and ivByte are always different. This is because some information from the cipher is there in the ivByte, and that should be passed to the certain encrypted result. If you switch it with a different encrypted result of the same payload and encryption key, you will not get the correct decrypted payload, rather an error or jargon.

package encryptor.mediator;

import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidParameterSpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

public class EncryptorAES {

private static final String ALGORITHM = "AES";
private static final String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";
private static final String ENCODING = "UTF-8";
private byte[] ivBytes;
private SecretKey secretKey;

public String encrypt(String payload)
throws NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchPaddingException, UnsupportedEncodingException, InvalidParameterSpecException {
generateSecretKey();
Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
AlgorithmParameters params = cipher.getParameters();
ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(payload.getBytes(ENCODING));
return new String(new Base64().encode(encryptedTextBytes));
}

public String decrypt(String payload, String key, String bytes)
throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, InvalidAlgorithmParameterException, DecoderException {
setSecretKey(key);
setIVBytes(bytes);
byte[] encryptedTextBytes = Base64.decodeBase64(payload.getBytes());
Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(ivBytes));
byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
return new String(decryptedTextBytes);
}

private void generateSecretKey() throws NoSuchAlgorithmException {
KeyGenerator generator = KeyGenerator.getInstance(ALGORITHM);
generator.init(128);
secretKey = generator.generateKey();
}

public String getSecretKey() {
return Hex.encodeHexString(secretKey.getEncoded());
}

public String getIVBytes() {
return Hex.encodeHexString(ivBytes);
}

private void setIVBytes(String ivBytes) throws DecoderException {
this.ivBytes = Hex.decodeHex(ivBytes.toCharArray());
}

private void setSecretKey(String secretKey) throws DecoderException {
byte[] byteArray = Hex.decodeHex(secretKey.toCharArray());
this.secretKey = new SecretKeySpec(byteArray, 0, byteArray.length, ALGORITHM);
}
}

This is the code of the mediator class:

package encryptor.mediator;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidParameterSpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.apache.commons.codec.DecoderException;
import org.apache.synapse.MessageContext; 
import org.apache.synapse.mediators.AbstractMediator;

public class EncryptorMediator extends AbstractMediator { 

public boolean mediate(MessageContext context) { 

String payload = getPayload(context);
if(payload == null || payload.length() < 1){
System.out.println("1st condition");
return completeProcess(context, "Payload is empty.");
}else{
String key = getSecretKey(context);
String bytes = getIVByteString(context);
process(context, payload, key, bytes);
}
return true;
}

private boolean process(MessageContext ctx, String payload, String key, String bytes){
String respondPayload = "";
String encryptionKey = "";
String ivbyteString = "";
try {
EncryptorAES encryptor = new EncryptorAES();
if(bytes == "NULL"){
respondPayload = encryptor.encrypt(payload);
encryptionKey = encryptor.getSecretKey();
ivbyteString = encryptor.getIVBytes();
}else{
if(key != null && !key.equals("NULL") && bytes != null){
respondPayload = encryptor.decrypt(payload, key, bytes);
}else{
return completeProcess(ctx,"Encryption key or IVByte String is invalid.");
}
}
return completeProcess(ctx, respondPayload, encryptionKey, ivbyteString);
} catch (InvalidKeyException e) {
return completeProcess(ctx,e.getMessage());
} catch (NoSuchAlgorithmException e) {
return completeProcess(ctx,e.getMessage());
} catch (IllegalBlockSizeException e) {
return completeProcess(ctx,e.getMessage());
} catch (BadPaddingException e) {
return completeProcess(ctx,e.getMessage());
} catch (NoSuchPaddingException e) {
return completeProcess(ctx,e.getMessage());
} catch (UnsupportedEncodingException e) {
return completeProcess(ctx,e.getMessage());
} catch (InvalidParameterSpecException e) {
return completeProcess(ctx,e.getMessage());
} catch (InvalidAlgorithmParameterException e) {
return completeProcess(ctx,e.getMessage());
} catch (DecoderException e) {
return completeProcess(ctx,e.getMessage());
}
}

private String getPayload(MessageContext context){
return context.getProperty("Paylod").toString();
}

private String getSecretKey(MessageContext context){
return context.getProperty("SecretKey").toString();
}

private String getIVByteString(MessageContext context){
return context.getProperty("IVByteString").toString();
}

private boolean completeProcess(MessageContext context,String payload, String key, String bytes){
setResultPayload(context,payload);
setEncryptionKey(context,key);
setIVByteString(context,bytes);
setSuccess(context, "true");
setErrorMessage(context, "");
return true;
}

private boolean completeProcess(MessageContext context,String error){
 setSuccess(context, "false");
 setErrorMessage(context, error);
 return true;
}

private void setSuccess(MessageContext context, String success){
context.setProperty("success", success);
}

private void setResultPayload(MessageContext context, String respondPayload){
context.setProperty("resultPayload", respondPayload);
}

private void setEncryptionKey(MessageContext context, String encryptionKey){
context.setProperty("encyptionKey", encryptionKey);
}

private void setErrorMessage(MessageContext context, String errorMessage){
context.setProperty("errorMessage", errorMessage);
}

private void setIVByteString(MessageContext context, String ivbyteString){
context.setProperty("ivByteString", ivbyteString);
}
}

I have also created a class to test the logic in the EncryptorAES class and a class for Exception handling. You can check those in the Git repo.

Next is the implementation of the template and test API. Note that implementing a template is not necessary; you can use the class directly with the class mediator after setting the required properties.

Below is the template and API:

<?xml version="1.0" encoding="UTF-8"?>
<template name="encryptor-template" xmlns="http://ws.apache.org/ns/synapse">
    <parameter name="payload"/>
    <parameter name="key"/>
    <parameter name="bytestring"/>
    <sequence>
        <property expression="$func:payload" name="Paylod" scope="default" type="STRING"/>
        <property expression="$func:key" name="SecretKey" scope="default" type="STRING"/>
        <property expression="$func:bytestring" name="IVByteString" scope="default" type="STRING"/>
        <class description="" name="encryptor.mediator.EncryptorMediator"/>
    </sequence>
</template>
<?xml version="1.0" encoding="UTF-8"?>
<api context="/message" name="encryptor-api" xmlns="http://ws.apache.org/ns/synapse">
    <resource methods="POST" protocol="https" uri-template="/encrypt">
        <inSequence>
            <log level="full">
                <property name="Encrypt" value="Encrypting message"/>
            </log>
            <enrich description="">
                <source clone="true" type="body"/>
                <target property="PAYLOAD" type="property"/>
            </enrich>
            <call-template description="Call: encryptor-template" target="encryptor-template">
                <with-param name="payload" value="{get-property('PAYLOAD')}"/>
                <with-param name="key" value="NULL"/>
                <with-param name="bytestring" value="NULL"/>
            </call-template>
            <payloadFactory description="Build Test Response" media-type="xml">
                <format>
                    <payload xmlns="">
                        <success>$1</success>
                        <errorMessage>$2</errorMessage>
                        <encryptedPayload>$3</encryptedPayload>
                        <secretKey>$4</secretKey>
                        <ivByteString>$5</ivByteString>
                    </payload>
                </format>
                <args>
                    <arg evaluator="xml" expression="get-property('success')"/>
                    <arg evaluator="xml" expression="get-property('errorMessage')"/>
                    <arg evaluator="xml" expression="get-property('resultPayload')"/>
                    <arg evaluator="xml" expression="get-property('encyptionKey')"/>
                    <arg evaluator="xml" expression="get-property('ivByteString')"/>
                </args>
            </payloadFactory>
            <respond/>
        </inSequence>
        <outSequence/>
        <faultSequence/>
    </resource>
    <resource methods="POST" protocol="https" uri-template="/decrypt">
        <inSequence>
            <log level="full">
                <property name="Decrypt" value="Decrypting message."/>
            </log>
            <enrich description="">
                <source clone="true" type="body"/>
                <target property="PAYLOAD" type="property"/>
            </enrich>
            <property description="Set: SECRET_KEY" expression="$trp:SecretKey" name="SECRET_KEY" scope="default" type="STRING"/>
            <property description="Set: BYTE_STRING" expression="$trp:ByteString" name="BYTE_STRING" scope="default" type="STRING"/>
            <call-template description="Call: encryptor-template" target="encryptor-v1encryptor-template">
                <with-param name="payload" value="{get-property('PAYLOAD')}"/>
                <with-param name="key" value="{get-property('SECRET_KEY')}"/>
                <with-param name="bytestring" value="{get-property('BYTE_STRING')}"/>
            </call-template>
            <payloadFactory description="Build Test Response" media-type="xml">
                <format>
                    <payload xmlns="">
                        <success>$1</success>
                        <errorMessage>$2</errorMessage>
                        <decryptedPayload>$3</decryptedPayload>
                    </payload>
                </format>
                <args>
                    <arg evaluator="xml" expression="get-property('success')"/>
                    <arg evaluator="xml" expression="get-property('errorMessage')"/>
                    <arg evaluator="xml" expression="get-property('resultPayload')"/>
                </args>
            </payloadFactory>
            <respond/>
        </inSequence>
        <outSequence/>
        <faultSequence/>
    </resource>
</api>

Next, create a composite application project and select the template, API, and mediator artifacts. Deploy the cApp in the ESB and test it from Postman.

Enterprise service bus Advanced Encryption Standard Algorithm

Published at DZone with permission of Priyashani Fernando. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • 7 Crucial Questions About Quantum Computing and Cybersecurity
  • Exploring ML.NET Catalogs and Use Cases
  • Essential Security Measures for PDF Documents
  • Exploring the Role of Consensus Algorithms in Distributed System Design

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: