JMETER, Problem in JSR223 script, JSR223 PreProcessor javax.script.ScriptException

292 Views Asked by At

I'm trying to do a login test into a website via JMeter. I'm informed that they are using SHA 256 hashing and AES encryption for security. SHA for frontend side, and I'm expected to compare that with db side of the password, then I need to do AES encryption on the hashed passwrod

I'm passing my user info (username, password) over CSV file. I am able to retrieve them without any problem.

The thing is with my script. I'm not confident with my writing skills. So I need help with my script.

I tried the following script;

    import java.security.MessageDigest;
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import org.apache.commons.codec.binary.Base64;



    String plaintextPassword = vars.get("PASSWORD");


    try {
        // Step 1: SHA-256 Hashing
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(plaintextPassword.getBytes());
        byte[] digest = md.digest();

        StringBuilder sha256Hash = new StringBuilder();
        for (byte b : digest) {
        ** sha256Hash.append(String.format("%02x", b));** **Line 17**
        }

        String _Key = "____"; // I came to conclusion that I need random key to be able to perform my AES       encryption. That's why "_Key" is here...

        // Step 2: AES Encryption
        Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  
        // Generate SecretKeySpec from Base64 encoded key
        SecretKeySpec secretKey = new SecretKeySpec(Base64.decodeBase64(_Key), "AES");

        _Cipher.init(Cipher.ENCRYPT_MODE, secretKey);

       byte[] encryptedBytes = _Cipher.doFinal(sha256Hash.toString().getBytes());

       // Convert the encrypted bytes to a Base64-encoded string
       String encryptedPassword = Base64.encodeBase64String(encryptedBytes);

       vars.put("encryptedPassword", encryptedPassword);

    } catch (Exception e) {
        log.error("Error occurred: " + e.getMessage());
        throw new RuntimeException(e);
    }

and expect to do both SHA and AES. However when I run my script, I get the following error on JMeter

ERROR o.a.j.m.JSR223PreProcessor: Problem in JSR223 script, JSR223 PreProcessor
javax.script.ScriptException: Sourced file: inline evaluation of: ``import java.security.MessageDigest; import javax.crypto.Cipher; import javax.cry . . . '' : Error in method invocation: Static method format( java.lang.String, byte ) not found in class'java.lang.String' : at **Line: 17** : in file: inline evaluation of: ``import java.security.MessageDigest; import javax.crypto.Cipher; import javax.cry . . . '' : String .format ( "%02x" , b ) 
 in inline evaluation of: ``import java.security.MessageDigest; import javax.crypto.Cipher; import javax.cry . . . '' at line number 17
    at bsh.engine.BshScriptEngine.evalSource(BshScriptEngine.java:93) ~[bsh-2.0b6.jar:2.0b6 2016-02-05 05:16:19]
    at bsh.engine.BshScriptEngine.eval(BshScriptEngine.java:46) ~[bsh-2.0b6.jar:2.0b6 2016-02-05 05:16:19]
    at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:231) ~[java.scripting:?]
    at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:232) ~[ApacheJMeter_core.jar:5.6.2]
    at org.apache.jmeter.modifiers.JSR223PreProcessor.process(JSR223PreProcessor.java:45) ~[ApacheJMeter_components.jar:5.6.2]
    at org.apache.jmeter.threads.JMeterThread.runPreProcessors(JMeterThread.java:983) ~[ApacheJMeter_core.jar:5.6.2]
    at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:561) ~[ApacheJMeter_core.jar:5.6.2]
    at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:501) ~[ApacheJMeter_core.jar:5.6.2]
    at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:268) ~[ApacheJMeter_core.jar:5.6.2]
    at java.lang.Thread.run(Thread.java:1623) [?:?] 

I cant seem to find the exact solution for the error I'm getting. To be honest, I dont know If my script is even correct or not. I'm running my script as Java script.

1

There are 1 best solutions below

1
Dmitri T On
  1. Don't use Beanshell as it's not fully compatible with Java and it has performance issues, especially when it comes to cryptographic operations. More information: Beanshell vs. JSR223 vs. Java For JMeter: Complete Showdown

  2. Your code can be amended to look like:

    def secretKey = 'your-secret-key-here'
    
    def plaintextPassword = vars.get("PASSWORD");
    
    def sha = MessageDigest.getInstance("SHA-256")
    byte[] keyBytes = secretKey.getBytes("UTF-8")
    keyBytes = sha.digest(keyBytes)
    
    def key = Arrays.copyOf(keyBytes, 16)
    def secretKeySpec = new SecretKeySpec(key, "AES")
    
    def cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec)
    
    def encrypted = cipher.doFinal(plaintextPassword.getBytes("UTF-8"))
    
    def encryptedPassword = new String(encrypted.encodeBase64().toString())
    
    vars.put("encryptedPassword", encryptedPassword)
    

More information: Encryption and decryption with Groovy