Testing secured web service methods with SOAP UI 25Feb, 2016

OVERVIEW
Securing Web Service methods to protect them from malicious attackers, has been an indispensable part of SOA and web services for mobile applications. However, it also makes testing the web methods equally hard and unmanageable. I have been using SOAP UI for testing the web services of one of our mobile applications, where the web team has secured the REST web methods (PHP) using headers with encrypted values using HMAC hash and AES-256 algorithms.

Here, I’ll share how we can use a groovy script (essentially Java code, for those who are not familiar with groovy) and property transfers in our SOAP UI test cases, automate test the secured web methods or anywhere you need to send the encrypted values in web services.

A little background on the web service methods. Our web methods (essentially REST) are set up in a style where they expect some header values in the request, encrypted with 256 bit AES encryption. To set this up in our SOAP UI Test Case, we can add a groovy Test Step to write the script (using Java), for encrypting the values and transmit the encrypted values in the next Step (REST Test Request), using Property Transfers of SOAP UI.

SET UP
To set this up, I added a new TestCase to my TestSuite of the project. After adding the TestCase, right click on the TestCase name and select Add Step and choose groovy Step. A new empty step will be added to the Test Case, where you can now write the groovy script for encryption.
For a Key based 256 bit AES Encryption, I am using the Java Crypto Library (code added below). This code is written for our specific needs where the final encrypted value was changed over to Hex value. If you need to convert it to Base 64 or any other format you can use the appropriate method of the DataTypeConverter class.

Also, once this script runs, you will need to transfer the encrypted value to the next step. As mentioned earlier, you can practice this using Property as well. Here, I have created a TestCase level Custom Property. You can name this property appropriately. I am using the name “PropertyName” in the code, for the sake of brevity. You can then access this property in your groovy script and put its value using

testRunner.testCase.setPropertyValue("propertyName", AESInputString);

Here is the full groovy script

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter ;

public class Encryptor {
    public static String encrypt(String key, String initVector, String value) {
        try {
               //Set up the Initialization Vector. Convert the String Value to Bytes
	       IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
           	//Set up the Pass Key. Essentially it needs to be either 128, 192 or 256 bit. I used 256 
	        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
	
	//Using No Padding for a reason. I have already converted the value to a block, 	
        //multiple of 16 bytes, by padding it with trailing ""
           	Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            	cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            	byte[] encrypted = cipher.doFinal(value.getBytes("UTF-8"));
            	//Convert the encrypted bytes to Hex Value
			String encryptedString = DatatypeConverter.printHexBinary(encrypted).toLowerCase();
            	return encryptedString;
        } catch (Exception ex) {
               //returning exception message to log 
	 return ex.toString();
        }
    }
	//Used for padding the input string with trailing "" so that the input string can be 	//made symmetric with a value which is multiple of 16 bytes
    	public static String PadStringFor16Bytes(String inputString)
    {
        int length = inputString.length();
        int mod = length % 16;
        int padCount = 16 - mod;
        for(int counter = 1; counter<= padCount; counter++)
        {
            inputString += "";
        }
        return inputString;
    }
}

String inputString = "Some Value to Pass in Header";
String paddedString = Encryptor.PadStringFor16Bytes(inputString );
String InitializationVector = "16ByteInitVector";
String Key = "256BitKeyForEncryption1234567890";
String AESInputString = Encryptor.encrypt(Key, InitializationVector, paddedString );
testRunner.testCase.setPropertyValue("propertyName", AESInputString);
log.info("AES" + AEStimeStamp);  

CODE DETAILS
The encrypt method is really straightforward and does what it is supposed to do – Encrypt the input string using an AES / CBC algorithm, with passed 128 bit Initialization Vector and 256 Bit Key. Please make sure that the passed Key should be either 128, 192 or 256 bits in length, else, the script will not work and throw the “Invalid Key Length” exception.

Padding the input string- although, there are certain Padding schemes/formats made available by Java Crypto Library like PKCS5Padding and others, I have used “NoPadding” to instruct the code NOT to pad the string as I am already padding the input string to make it a multiple of 16 bytes by adding trailing “”. This is done by the method PadStringfor 16Bytes. This is specifically required to match the format of strings encrypted in a PHP script using “mcrypt” library.

INVALID KEY LENGTH EXCEPTION
Some of you may already be using correct 256 byte Key but still getting Java. security. InvalidKeyException: Invalid AES key length exception. This is something related to the Unlimited Strength Jurisdiction Policy of JRE which is not default, for SOAP UI. If you face this exception while using this script for 256 bit key, here are the steps to resolve this:

You need to download the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files. For the SOAP UI 5.2.1 that I am using (using JRE 1.7), you can download this file from this link
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
After extracting the two files local_policy.jar and US_export_policy.jar, you need to replace the files with the same names at the location C:Program FilesSmartBearSoapUI-5.2.1jrelibsecurity
Please make sure to take the backup of the original files before replacing.

USING THE TEST CASE PROPERTY
After running this script, we should have the value of the Test Case property set to the appropriate value. Now we can use this property in our next test steps. I need to use this as one of the headers in a call to the web method. So, I add a new REST Test Step after the gravy step. In this new test step, I added a request Header and used
$ {#TestCase#PropertyName}

As the value for the Header that will correctly transfer the value from the property to the header.

THAT’S ALL FOLKS
So, this is essentially all the necessary steps you need to follow in SOAP UI to set up a basic groovy script step for writing custom code and transferring the values between Test Steps. I hope the details above make sense and will be helpful.

Posted by: Amritpal Singh / In: Testing and Tagged , ,
Cam

Leave a Reply

Your email address will not be published.