Encrypted API Testing using JMeter

Share

 

The Problem Statement

While working on several projects, you come across performance tests for different API’s, which are unencrypted SOAP/REST payloads in XML/JSON formats. Occasionally, you might also encounter scenarios where few parameters in request body are being encrypted. Now, let’s imagine a scenario where one of our Test API is being completely encrypted for additional security. Then the ultimate question arises – will you be able to handle this encryption scenario and still perform the testing using JMeter? The answer is YES!!

What are the Possible Solutions?

Before proceeding with the solutions, there are few key data, which you must gather proactively in-order to arrive at the best feasible solution. The key data which you need are the encryption algorithm being used, Algorithm specific parameters (Block mode, Padding, Key length etc.) and the secret key. Based on this information, you can now dive into the options provided by JMeter, which are based on the request and encryption type:

1. Encoded Request / Parameters – This is not exactly encryption and not at all secure. Basically, the string is being encoded in Base64 format, which would mask the data in garbled format. If this is the case, then you can make use of base64Encode / base64Decode functions in JMeter.

E.g.: ${__base64Encode(test string)}, ${__base64Decode(dGVzdCBzdHJpbmc=)}

2. Hashed Request / Parameters – Again not exactly encryption but cryptographic hashing. This is where the request is being hashed using MD5 and better than encoding. If this is the case, then you can make use of MD5 function in JMeter.

E.g.: ${__MD5(test)}

3. MD / SHA encrypted Request / Parameters – Here, the request / parameters are encrypted via MD / SHA algorithms. The algorithm types could be MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512. If this is the case, then you can make use of __digest() in JMeter. The digest function returns an encrypted value in the specific hash algorithm with the optional salt, upper case and variable name.

E.g.: ${__digest(SHA-256,TestString,mysalt,)}

4. AES or Custom encrypted Request / Parameters– If you are dealing with API in SOAP protocol, then you might get lucky. You would be able to use the WS-Security third party plugin and handle the scenario. But if you are dealing with REST-JSON, then it is one of the corner cases where you don’t have any built-in functions or plugins to use.

Scenarios where you are not blessed with readymade JMeter functions or Third-party plug-ins, you can still make use of the Java language’s power to handle these corner cases.

This article serves as a guide on how to accomplish the encryption of API and why you must harness the power of Java.

Actual Requirement & the Solution

The requirement which is being mentioned in this article is as follows:

You have an API whose request body/payload is completely encrypted using AES-256 algorithm. You know the actual plain text JSON body, which you used to send earlier directly to the API endpoint. As discussed earlier, you have also, gathered the key decision making datapoints – Encryption type, Encryption parameters and the Secret key.

Since you are dealing with AES and don’t have any prebuilt solutions, you can make use of Java. Java offers build-in libraries for cryptography which you can use. The solution architecture is as below:

  • [INPUT] Plain text JSON in an HTTP Sampler request.
  • [LOGIC] Custom encryption logic in BeanShell Pre-Processor.
    1. Access the plain text JSON in HTTP Sampler using Context object.
    2. Encrypt the input JSON based on project encryption method.
    3. Once encrypted, assign the data back to the input HTTP Sampler using Context object.
  • [OUTPUT] Encrypted body is being set into same input HTTP Sampler request.

Note: BeanShell is one of the most advanced JMeter built-in components. It supports Java syntax and extends it with scripting features like loose types, commands, and method closures.

JMeter Sample Project Structure

  • Under Test plan, Create Thread group.
  • Under Thread group, Add a HTTP Sampler.
  • Under the HTTPSampler, Add a BeanShell Pre-processor.
  • Under Thread group, Add Listener – “View Result Tree”.

HTTP Request

BeanShell Pre-Processor

Logic – Code Walkthrough

Java Code

Import Java.Util.Zip.Gzipoutputstream;

Import Java.Security.Invalidalgorithmparameterexception;

Import Java.Security.Invalidkeyexception;

Import Java.Security.Nosuchalgorithmexception;

Import Java.Util.Base64;

Import Javax.Crypto.Cipher;

Import Javax.Crypto.Nosuchpaddingexception;

Import Javax.Crypto.Secretkey;

Import Javax.Crypto.Spec.Ivparameterspec;

Import Javax.Crypto.Spec.Secretkeyspec; 

Log.Info(“Beanshell Execution Commenced”); 

String Plaintext = Ctx.Getcurrentsampler().Getarguments().Getargument(0).Getvalue();

Log.Info(Plaintext); 

Cipher _Cipher;

Secretkey _Keyspec;

Ivparameterspec _Ivspec;

String _Key = “MySecretKey”; 

_Cipher = Cipher.Getinstance(“Aes/Cbc/Pkcs5padding”);

_Keyspec = New Secretkeyspec(_Key.Getbytes(), “Aes”);

_Ivspec = New Ivparameterspec(_Key.Getbytes());

_Cipher.Init(Cipher.Encrypt_Mode, _Keyspec, _Ivspec); 

Byte[] Ciphertext = _Cipher.Dofinal(Plaintext.Getbytes()); 

String Encryptedresponse = Base64.Getencoder().Encodetostring(Ciphertext); 

Vars.Put(“Encryptedresponse”,Encryptedresponse); 

Ctx.Getcurrentsampler().Getarguments().Getargument(0).Setvalue(Encryptedresponse); 

Log.Info(“Beanshell Execution Completed !!”);

JMeter Output

Conclusion

In this article, you get some ideas on how to encrypt the entire API request body in AED/CBC/PKCS5 Padding and Base64 encoding. AES encryption is touched upon in this article, but it should be noted that the Java crypto library is loaded with different Algorithms, Modes and Parameters, which should cater to all the encryption related needs.

As pointed out earlier, for simple encoding, hashing and MD/SHA encryptions, you have other easy readily available solutions. But for the uncommon requirements and implementations, which the JMeter pre-built components doesn’t support or makes it too complex, you can always harness the power of Java via BeanShell. BeanShell is a small, free, embeddable Java source interpreter with object scripting language features, written in Java. BeanShell dynamically executes standard Java syntax and extends it with common scripting conveniences such as loose types, commands, and method closures like those in Perl and JavaScript.

Another alternative for BeanShell is to use the JSR223 Pre-processor, if you are comfortable with any of these 5 languages – Groovy, JavaScript, JRuby, Jython, and Kotlin.

So next time when you end up with a scenario, where no pre-built components will rescue you, it’s time to brush up your Java or other supported programming language skills and nail down the problem. Happy Learning. Thanks!

By,

Renjith R Nair, Test Lead

LEAVE A COMMENT

How can we help you?