AES Encryption Decryption in webMethods

AES Encryption Decryption

This post describes how to implement AES encryption decryption in webMethods. This post is divided into different portions.

  1. Java Cryptography Extension (JCE)
  2. Information about AES Encryption Decryption
  3. Java service inputs
  4. Java Service for KeyGeneration
  5. Java Service to Decrypt
  6. Java Service to Encrypt
  7. Shared Code

Java Cryptography Extension (JCE)

Wikipedia define JCE as The Java Cryptography Extension (JCE) is an officially released Standard Extension to the Java Platform and part of Java Cryptography Architecture. JCE provides a framework and implementation for encryption, key generation and key agreement, and Message Authentication Code (MAC) algorithms. JCE supplements the Java platform, which already includes interfaces and implementations of message digests and digital signatures. Installation is specific to the version of the Java Platform being used, with downloads available for Java 6, Java 7, and Java 8

For AES encryption decryption java code provided in this post to work and to generate keys of 128bit and greater you need to install Unlimited Strength Jurisdiction Policy Files in your environment. Policy files can be downloaded from Oracle website at link

Information about AES Encryption Decryption

Wikipedia defines AES as –

The Advanced Encryption Standard (AES), also known as Rijndael (its original name), is a specification for the encryption of electronic data established by the U.S. National Institute of Standards and Technology (NIST) in 2001.

AES is based on the Rijndael cipher developed by two Belgian cryptographers, Joan Daemen and Vincent Rijmen, who submitted a proposal to NIST during the AES selection process. Rijndael is a family of ciphers with different key and block sizes. More can be read about AES at wikipedia link

AES encryption decryption Java Services provided in this post provides support to generate keys for different block sizes and different message digest algorithm. however we tested entire code only with cipher “AES/CBC/PKCS5Padding”, encryption algorithm “AES” and key block size of 128 and 256 bits. Please test and change code as it suits you.

Java Service Inputs

there are bunch of inputs which are passed to services. for ease and avoid redundancy, i am explaining common one here.

  • cipher – a cipher (or cypher) is an algorithm for performing encryption or decryption. Depending on what Cipher Algorithm and mode you want to use value can be different. for our testing purpose we used AES algorithm, CBC mode and PKCS5Padding. value looked like “AES/CBC/PKCS5Padding” Set of values supported by Java 8 can be found here
  • keyAlgorithm – Key algorithm refers to the encryption algorithm for generating keys. In current code implementation it doesn’t have any impact other than being a place holder for algorithm. SecretKeySpec class constructor does not check if the given bytes indeed specify a secret key of the specified algorithm. Read more here
  • messageDigest MessageDigest class provides applications the functionality of a message digest algorithm, such as SHA-1 or SHA-256. Message digests are secure one-way hash functions that take arbitrary-sized data and output a fixed-length hash value. Set of values supported by Java 8 can be found here
  • encoding – Encoding refers to Character Encoding. default is set to “UTF-8”
  • password – Password is choice of alphanumeric string which can be used to generateKey. this can be of any length and it is a mandatory field.
  • keySizekey size or key length is the number of bits in a key used by a cryptographic algorithm. Input accepts number of bytes and default is 32bytes (256bits).

Java Service for KeyGeneration

This service generate encryption key and initialization vector in base64 encoded format. Initialization Vector is set to generate only 16bytes (128bits) value. Screenshot below shows inputs and output for service.

generateKey service signatures - AES Encryption Decryption
generateKey service signatures

JavaCode for generateKey

Below is java code which needs to be put in java service for generation of key. you can create java service name of your own choice and copy paste below code to the body. Code refers to a common class AES which is provided in section of shared code and needed to copied to shared code area of java service.

// pipeline
IDataCursor pipelineCursor = pipeline.getCursor();
String messageDigest = IDataUtil.getString( pipelineCursor, "messageDigest" );
String keyAlgorithm = IDataUtil.getString( pipelineCursor, "keyAlgorithm" );
String encoding = IDataUtil.getString( pipelineCursor, "encoding" );
final String password = IDataUtil.getString( pipelineCursor, "password" );
Integer keySize = Integer.parseInt(IDataUtil.getString( pipelineCursor, "keySize" ));

if(messageDigest == null || messageDigest.equals(""))
messageDigest = "SHA-256";
if(keyAlgorithm == null || keyAlgorithm.equals(""))
keyAlgorithm = "AES";
if(encoding == null || encoding.equals(""))
encoding = "UTF-8";
if(keySize == null || keySize.equals("")){
keySize = 32;
System.out.println("inside integer check");
}

//Call key generation function
AES.setKey(password, messageDigest, keyAlgorithm, encoding, keySize);

IDataUtil.put( pipelineCursor, "generatedKey", AES.getGeneratedKey());
IDataUtil.put( pipelineCursor, "generatedKeyBase64", Base64.getEncoder().encodeToString(AES.getGeneratedKey()) );
IDataUtil.put( pipelineCursor, "ivKey", AES.getIV());
IDataUtil.put( pipelineCursor, "ivKeyBase64", Base64.getEncoder().encodeToString(AES.getIV()) );

//Remove input pipeline variable from pipeline
IDataUtil.remove(pipelineCursor, "messageDigest");
IDataUtil.remove(pipelineCursor, "keyAlgorithm");
IDataUtil.remove(pipelineCursor, "encoding");
IDataUtil.remove(pipelineCursor, "password");
IDataUtil.remove(pipelineCursor, "keySize");

pipelineCursor.destroy();

Java Service to Decrypt

This service decrypt encrypted text. it accepts encrypted string, encryption key in base64 format and initialization vector in base64 format. Screenshot below shows inputs and output for service.

decryptString service signature - AES Encryption Decryption
decryptString service signature

JavaCode for decrypt Service

Below is java code which needs to be put in java service for decryption. you can create java service name of your own choice and copy paste below code to the body. Code refers to a common class AES which is provided in section of shared code and needed to copied to shared code area of java service.

// pipeline
IDataCursor pipelineCursor = pipeline.getCursor();
    final String strToDecrypt = IDataUtil.getString( pipelineCursor, "strToDecrypt" );
    final byte[] strKey = Base64.getDecoder().decode(IDataUtil.getString( pipelineCursor, "strKey" ));
    final byte[] ivBytes = Base64.getDecoder().decode(IDataUtil.getString( pipelineCursor, "ivKey" ));
    String inputCipher = IDataUtil.getString( pipelineCursor, "cipher" );
    String keyAlgorithm = IDataUtil.getString( pipelineCursor, "keyAlgorithm" );
    
    //Perform check on inputs
    if(strToDecrypt == null || strToDecrypt.equals(""))
        throw new ServiceException("strToDecrypt field can not be empty");
    if(strKey == null || strKey.equals(""))
        throw new ServiceException("strKey - Encryption Key field can not be empty");
    if(ivBytes == null || ivBytes.equals(""))
        throw new ServiceException("Initialization Vector field can not be empty");
    if(keyAlgorithm == null || keyAlgorithm.equals(""))
        keyAlgorithm = "AES";
    if(inputCipher == null || inputCipher.equals(""))
        inputCipher = "AES/CBC/PKCS5Padding";
    
    //Call common Decrypt function
    AES.decrypt(strToDecrypt.trim(), inputCipher, keyAlgorithm, strKey, ivBytes);

IDataUtil.put( pipelineCursor, "decryptedStr", AES.getDecryptedString() );

//Remove input pipeline variable from pipeline
IDataUtil.remove(pipelineCursor, "strToDecrypt");
IDataUtil.remove(pipelineCursor, "strKey");
IDataUtil.remove(pipelineCursor, "ivKey");
IDataUtil.remove(pipelineCursor, "cipher");
IDataUtil.remove(pipelineCursor, "keyAlgorithm");

pipelineCursor.destroy();

Java Service to Encrypt

This service encrypt text. it accepts string which needs encryption, encryption key in base64 format and initialization vector in base64 format. Screenshot below shows inputs and output for service.

encryptString Signature - AES Encryption Decryption
encryptString Signature

JavaCode for encrypt Service

Below is java code which needs to be put in java service for encryption. you can create java service name of your own choice and copy paste below code to the body. Code refers to a common class AES which is provided in section of shared code and needed to copied to shared code area of java service.

// pipeline
IDataCursor pipelineCursor = pipeline.getCursor();
final String strToEncrypt = IDataUtil.getString( pipelineCursor, "strToEncrypt" );
final byte[] strKey = Base64.getDecoder().decode(IDataUtil.getString( pipelineCursor, "strKey" ));
final byte[] ivBytes = Base64.getDecoder().decode(IDataUtil.getString( pipelineCursor, "ivKey" ));
String inputCipher = IDataUtil.getString( pipelineCursor, "cipher" );
String keyAlgorithm = IDataUtil.getString( pipelineCursor, "keyAlgorithm" );

//Perform check on inputs
if(strToEncrypt == null || strToEncrypt.equals(""))
    throw new ServiceException("strToDecrypt field can not be empty");
if(strKey == null || strKey.equals(""))
    throw new ServiceException("strKey - Encryption Key field can not be empty");
if(ivBytes == null || ivBytes.equals(""))
    throw new ServiceException("Initialization Vector field can not be empty");
if(keyAlgorithm == null || keyAlgorithm.equals(""))
    keyAlgorithm = "AES";
if(inputCipher == null || inputCipher.equals(""))
    inputCipher = "AES/CBC/PKCS5Padding";

//Call common encrypt function
AES.encrypt(strToEncrypt.trim(), inputCipher, keyAlgorithm, strKey, ivBytes );
                    
IDataUtil.put( pipelineCursor, "encryptedStr", AES.getEncryptedString());

//Remove input pipeline variable from pipeline
IDataUtil.remove(pipelineCursor, "strToEncrypt");
IDataUtil.remove(pipelineCursor, "strKey");
IDataUtil.remove(pipelineCursor, "ivKey");
IDataUtil.remove(pipelineCursor, "cipher");
IDataUtil.remove(pipelineCursor, "keyAlgorithm");
pipelineCursor.destroy();

Shared Code for AES Encryption Decryption

Below code needs to be placed in IS Shared code area. methods in this shared code are called by java service in order to perform aes encryption decryption

Please import below classes in your java service for js to compile without issue.


import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

AES Encryption Decryption common Class Code


// --- <<IS-BEGIN-SHARED-SOURCE-AREA>> ---

public static class AES
{
private static SecretKeySpec secretKey ;
private static byte[] key ;
private static byte[] ivGeneratedKey ;

private static String decryptedString;
private static String encryptedString;

public static byte[] setKey(String myKey, String messageDigest, String keyAlgorithm, String encoding, int keySize){

MessageDigest sha = null;
try {
key = myKey.getBytes(encoding);
sha = MessageDigest.getInstance(messageDigest);
key = sha.digest(key);
secretKey = new SecretKeySpec(key, 0, keySize, keyAlgorithm); // KeySize as per input
setGeneratedKey(secretKey.getEncoded());

// Initialize a secure random number generator
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
//Calling nextBytes method to generate Random Bytes
ivGeneratedKey = new byte[16];
secureRandom.nextBytes(ivGeneratedKey);
setIV(ivGeneratedKey);

} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}

public static String getDecryptedString() {
return decryptedString;
}

public static void setDecryptedString(String decryptedString) {
AES.decryptedString = decryptedString;
}

public static byte[] getGeneratedKey() {
return key;
}

public static void setGeneratedKey(byte[] key) {
AES.key = key;
}

public static byte[] getIV() {
return ivGeneratedKey;
}

public static void setIV(byte[] ivGeneratedKey) {
AES.ivGeneratedKey = ivGeneratedKey;
}

public static String getEncryptedString() {
return encryptedString;
}

public static void setEncryptedString(String encryptedString) {
AES.encryptedString = encryptedString;
}

public static String encrypt(String strToEncrypt, String inputCipher, String keyAlgorithm, byte[] secretKey, byte[] ivBytes)
{
try
{
Cipher cipher = Cipher.getInstance(inputCipher);
SecretKeySpec encryptKey = new SecretKeySpec(secretKey, keyAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, encryptKey, new IvParameterSpec(ivBytes));
setEncryptedString(Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8"))));

}
catch (Exception e)
{

System.out.println("Error while encrypting: "+e.toString());
}
return null;

}

public static String decrypt(String strToDecrypt, String inputCipher, String keyAlgorithm, byte[] secretKey, byte[] ivBytes)
{
try
{
Cipher cipher = Cipher.getInstance(inputCipher);

SecretKeySpec decryptKey = new SecretKeySpec(secretKey, keyAlgorithm);
cipher.init(Cipher.DECRYPT_MODE, decryptKey, new IvParameterSpec(ivBytes));
setDecryptedString(new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt))));

}
catch (Exception e)
{

System.out.println("Error while decrypting: "+e.toString());

}
return null;
}
}

// --- <<IS-END-SHARED-SOURCE-AREA>> ---

Creating above mentioned java services should get you going with AES encryption decryption in webMethods Integration Server.

Hope this post will be of some help to you. If you have any questions\comments, please leave a comment below or use Contact Us page to send email. Please also let me know if there is some information which you find wrong. it will help me to improve quality of this post and help more people.

Disclaimer

  1. This code for AES Encryption Decryption was originally posted at AESEncryption website. Please contact me through Contact Us, If you are owner of code and i will update post with proper credits. The code posted in this link is converted and changed to use it in webMethods as java service.
  2. Sample Code was tested in 9.8 Integration server, JDK 1.8 and only with AES Encryption Decryption mode, Cipher Mode CBC, key Size of 128\256 bits and Initialization Vector with 16 bytes. Code is generic and open to accept any encryption mode, cipher mode. please Test it thoroughly before integrating in your code base.

Credits

  1. http://aesencryption.net/#Java-aes-encryption-example
  2. https://www.owasp.org/index.php/Using_the_Java_Cryptographic_Extensions#AES_Encryption_and_Decryption
  3. http://docs.oracle.com/javase/8/docs/api/index.html

Comments

5 responses to “AES Encryption Decryption in webMethods”

  1. Sanchit Sharma Avatar
    Sanchit Sharma

    Thank you Mangat for sharing this post, it works as a charm.

    Regards,
    Sanchit Sharma

  2. Sakshi Gupta Avatar
    Sakshi Gupta

    For me “AES.encrypt(strToEncrypt.trim(), inputCipher, keyAlgorithm, strKey, ivBytes );” is returning null.
    Values passed as below:
    keyAlgorithm : — AES_256
    inputCipher : — AES_256
    ivBytes : — [B@5c36955f
    strKey : — [B@19e21fb1
    strToEncrypt : — 1003712|5296512|105.0

    Please help me.

    1. MANGAT RAI Avatar
      MANGAT RAI

      would you be able to send screenshot of your code? it seems like something is missing. probably check spellings etc or any compile errors.

    2. MANGAT RAI Avatar
      MANGAT RAI

      you can email me at mangat@quest4apps.com

      1. Sakshi Gupta Avatar
        Sakshi Gupta

        Mangat Rai, thanks for the response.
        I have shared the code on the email id you shared.
        It will a great help for me.

Questions? Comments? Suggestions? Let us know!! Like / Subscribe / Follow for more updates.