Encrypted API Testing using JMeter



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();


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); 



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

JMeter Output


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!


Renjith R Nair, Test Lead


  1. I am currently working on testing the REST API and need to send some request in JSON format to a server which I am testing through JMeter.So, how can I send the encrypted request by AES encryption instead of the plain text transmission using JMeter? I have the key and IV

  2. Vikas says:

    Hi Team,

    Scenario Desc – In my application whatever value I will pass as a parameter, It is getting converted to some token value which JMeter is capturing at run time.

    But If I rerun the recorded script it won’t work since those token value might have changed. After having a conversation with Dev team – They have provided me a code for Encryption and Decryption which I tried to implement in my JMX using JSR223 PreProcessor

    But after using that as well, I am not getting the correct response due to which I am stuck. I am giving you one CSV which contains a username and password. I need to pass that in form of JSON in my code and get encrypted.

  3. Hi Vikas,

    Could you please try with the below code changes and let me know the result. The issue was with the case-sensitiveness of the functions. Now I am able to generate and send the Login body with the encrypted text. Modified JMX is also emailed.
    String plainText = ctx.getCurrentSampler().getArguments().getArgument(0).getValue();

    String encryptedText = new OpenSSLEncryptDecrypt().encrypt(plainText);

    // Directly set to Request body.

    // Store to variable and then set to Request body.
    def my_var = vars.get(“ENCRYPTED_BODY”);

  4. Vikas says:

    Thank you so much. It is working as expected!!

  5. Dhanush VM says:

    I have successfully encrypted the Request and decrypted the response also but I want put back the response body with decrypted data can you help on this.

  6. Renjith says:

    Hi User (Stop Hurting.Com),

    To cater to your requirement, We need to use pre-processor (where we can use Java libraries) to encrypt the data and then use post-processor to decrypt the server response if that is also encrypted. You can use the BeanShell or JSR223 pre-processor to AES encrypt your JSON. The step by step walkthrough is available in this blog which uses BeanShell. Please refer and let me know if you have any questions. Thanks!

  7. Renjith says:

    Hi Dhanush,

    Please add a BeanShell PostProcessor as the child of the HTTP sampler and use the following statement in the BeanShell script >> prev.setResponseData( decryptedString);

    Please note that:-

    1) “prev” is default JMeter script variable and “setResponseData()” is a supported function to overwrite the response.
    2) decryptedString will be the custom variable or the variable to which you are storing the decrypted response via BeanShell PostProcessor.

    Let me know how it goes. Thanks!

  8. Jay says:

    I have tried above code but I’m getting “Secretkey not found in namespace” tried so many things but couldn’t figure it out. Could you please help?

    2020-08-11 20:13:02,551 ERROR o.a.j.u.BeanShellInterpreter: Error invoking bsh method: eval Sourced file: inline evaluation of: “debug(); import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax . . . ” : Typed variable declaration : Class: Secretkey not found in namespace

    2020-08-11 20:13:02,551 WARN o.a.j.m.BeanShellPreProcessor: Problem in BeanShell script. org.apache.jorphan.util.JMeterException: Error invoking bsh method: eval Sourced file: inline evaluation of: “debug(); import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax . . . ” : Typed variable declaration : Class: Secretkey not found in namespace

  9. Renjith says:

    Hi Jay,

    The issue seems to be related to the case sensitive nature of BeanShell script. Could you please try with below Pre-processor code. I am also sending you the sample encryption JMX file. Let me know how it goes. Thanks!

    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();

    Cipher _Cipher;
    SecretKey _KeySpec;
    IvParameterSpec _IvSpec;
    String _Key = “MySecretKey”;

    Cipher _Cipher;
    SecretKey _KeySpec;
    IvParameterSpec _IvSpec;
    String _Key = “W2sf9kkAlHXxJRWx”;

    _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);
    log.info(“BeanShell execution completed !!”);

  10. Jay says:

    Hi Renjith,

    yes you are right, thanks a lot for the support and jmx file!

Please Share Your Thoughts & Comments Below.

How can we help you?