Concatenate variables and create MD5 - jmeter

Using JMeter, I would like to take values from CSV file, concatenate the values and do a MD5 hash on them and then send the value as part of HTTP request using HTTP Request Sampler.
I tried the following but did not get the correct result:
created CSV Data Set Config and added the variables csvVal1,csvVal2,csvVal3;
in the jp#gc-Dummy Sampler i added the following:
${__MD5(${csvval1}+${csvval2}+${csvval3})}
This did not work, what is the right way?

I ended up using BeanShell Preporcessor and used the following script
import java.security.MessageDigest;
String val1 = vars.get("csv_val1");
String val2 = vars.get("csv_val2");
String val3 = vars.get("csv_val3");
String totalString = val1+val2+val3;
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] md5hash = new byte[32];
md.update(totalString.getBytes("utf-8"), 0, totalString.length());
md5hash = md.digest();
StringBuffer sb = new StringBuffer();
for (int i=0;i<md5hash.length;i++) {
String sval = Integer.toHexString((int) md5hash[i] & 0xFF);
if(sval.length()== 1)
{
sval = "0"+sval;
}
sb.append(sval);
}
log.info("tktest: "+ sb);
vars.putObject("MD5Signature", sb.toString());

There's a new function __digest, currently in nightly builds
In your case to save in MD5Signature variable the result of 3 variable use the following:
${__digest(MD5,${csv_val1}${csv_val2}${csv_val3},,,MD5Signature)}

Related

How to replace the value inside a file that was located in local using javascript?

I have a scenario where after reading the file, it needs the value inside that file to be replaced.
We have this script from our JMeter where we based our script from. (Please refer to the code below)
def file = new File('C:/Peak2020/China/${__time(YMMdd)}-085644-336_000101-plant 8956.xml')
def newConfig = file.text.replace('596791365558876095', '000101')
file.text = newConfig
def newConfig2 = file.text.replace('C6D-CN-NBB2829A', 'C7D-CN-NBB$4568792B')
file.text = newConfig2
def sku = file.text.replace('323094-01', '45903-01')
file.text = sku
I tried doing it in the Neoload, using the replace() but it's not working. It does copy the file from sourcefolder to destinationfolder but the value was not changed. (Please refer to the code below)
var file = new java.io.BufferedReader(new java.io.FileReader("C:\\Peak2020\\China\\testSource1.xml"));
var line = file.readLine();
var id = line.replace(new RegExp("596791365558876095", "12345678"), "");
var destFile = line;
var writer = new java.io.FileWriter("C:\\Peak2020\\Teemp\\TestDestination3.xml",true);
writer.write(destFile);
writer.close();
Does anyone knows what right javascript code to use? Thank you.
String is immutable in Javascript and Java you are replacing it in
var id = line.replace(new RegExp("596791365558876095", "12345678"), "");
but then you use the var line again for the new variable.
var destFile = line;
it should be
var destFile = id;
because replace will return a new string with the replaced value.

Why does this ADO.NET query return no results?

I have the following code that executes a SQL statement and looks for a result.
var sql = #"select BOQ_IMPORT_ID "
+ "from ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER "
+ "where PROJECT_ID = :Projectid "
+ "order by CREATED_ON desc "
+ "fetch first 1 row only";
using (var conn = new OracleConnection(ApplicationSettings.ConnectionString))
using (var cmd = new OracleCommand(sql, conn))
{
conn.Open();
cmd.Parameters.Add(LocalCreateParameterRaw("ProjectId", projectId));
var reader = cmd.ExecuteReader();
if (reader.Read())
{
byte[] buffer = new byte[16];
reader.GetBytes(0, 0, buffer, 0, 16);
var boqId = new Guid(buffer);
return boqId;
}
return null;
}
Where LocalCreateParameterRaw is declared as:
public static OracleParameter LocalCreateParameterRaw(string name, object value)
{
OracleParameter oracleParameter = new OracleParameter();
oracleParameter.ParameterName = name;
oracleParameter.OracleDbType = OracleDbType.Raw;
oracleParameter.Size = 16;
oracleParameter.Value = value;
return oracleParameter;
}
The underlying type for 'projectId' is 'Guid'.
The if (reader.Read()) always evaluates to false, despite there being exactly one row in the table. It normally should return only one row.
Using GI Oracle Profiler I can catch the SQL sent to the db, but only once did the profiler provide a value for the :ProjectId parameter, and it was in lower case. Like that it returned no results, but as soon as I applied UPPER to that value, I get a result.
It looks like I somehow have to get my parameter into uppercase for the query to work, but I have no idea how. Yet if I do a ToString().ToUpper() on the projectId GUID, I get a parameter binding error.
VERY IMPORTANT:
I have tried removing the where clause altogether, and no longer add a parameter, so all rows in the table should be returned, yet still no results.
I don't know how, but making the SQL string a verbatim string (prefixed with #) causes the proc to work. So, it doesn't work with:
var sql = #"SELECT BOQ_IMPORT_ID "
+ "FROM ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER "
+ "WHERE PROJECT_ID = :projectid "
+ "ORDER BY CREATED_ON DESC "
+ "FETCH FIRST ROW ONLY";
Yet the same command string in SQL Developer executes and returns results. When I make my SQL string verbatim, as below, I get results.
var sql = #"select BOQ_IMPORT_ID
from ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER
where PROJECT_ID = :ProjectId
order by CREATED_ON desc
fetch first 1 row only";
Using a more general approach, try the following
var sql = "SELECT BOQ_IMPORT_ID "
+ "FROM ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER "
+ "WHERE PROJECT_ID = :projectid "
+ "ORDER BY CREATED_ON DESC "
+ "FETCH FIRST ROW ONLY";
using (DbConnection conn = new OracleConnection(ApplicationSettings.ConnectionString))
using (DbCommand cmd = conn.CreateCommand()) {
DbParameter parameter = cmd.CreateParameter();
parameter.ParameterName = "projectid";
parameter.Value = projectId.ToString("N").ToUpper(); //<-- NOTE FORMAT USED
cmd.Parameters.Add(parameter);
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;
conn.Open();
var reader = cmd.ExecuteReader();
if (reader.Read()) {
var boqId = new Guid((byte[])reader[0]);
return boqId;
}
return null;
}
It looks like I somehow have to get my parameter into uppercase for the query to work, but I have no idea how. Yet if I do a ToString().ToUpper() on the projectId GUID, I get a parameter binding error.
Reference Guid.ToString Method
Specifier N formats it to 32 digits: 00000000000000000000000000000000
When no format is provided the default format is D which would include 32 digits separated by hyphens.
00000000-0000-0000-0000-000000000000
That would explain your binding error.

How to encode protobuf map in python?

I am using protobuf and grpc as interface between a client and server.
The server is written in C and the client uses python to communicate to the server.
I have a message created in protobuf like below.
message value_obj {
uint32 code = 1;
uint32 value = 2;
}
message list_of_maps {
map<uint32, value_obj> mapObj1 = 1;
map<uint32, value_obj> mapObj2 = 2;
}
I tried creating objects in Python like below:
obj = list_of_maps()
mapObjToStore = value_obj()
mapObjToStore.code = 10
obj.mapObj1[1].CopyFrom(mapObjToStore)
When I try to receive the message in server, I get wrong values (huge numbers!).
Any help on this will be greatly appreciated.
You can try using python dictionary for that:
map1 = {}
obj1 = value_obj()
map1[1] = obj1
map2 = {}
listOfMaps = list_of_maps(mapObj1=map1, mapObj2=map2)

Can't decrypt Ruby encrypted string in Scala

I'm using ActiveSupport::MessageEncryptor to encrypt a string in Ruby as follows:
salt = SecureRandom.random_bytes(64)
// => "s\x90L\xB8\xEF\x8BBp\xB6\xF5A\x95\xA8]+\x94\xF3\xA7\x9A\x84+jC\xBF\xB0\x15\xEF*\x8C\xDD.\xE5\xC7Y\xCE\xE1\xAA\xA4I/%.\x9E\x14\xC1\xA8\x9E\x122\xE0\x19.\x19\xD8\xB6\xE8\x83\xE1\xFE\x16\xB5\x11N\x18"
key = ActiveSupport::KeyGenerator.new('password').generate_key(salt)
// => "\x12\xBD1\xA0Q\xBF)\\\x89\xDF\x95\xD0\f\x03\x17P'\x87\xAD\x92b\xB5%\xC7X\x01\x9Ar\xCB\xC9\x1A\x10'\xC4\x95w\xBF\xED]\x17\xEB\x9F#\xC6\xEE8S\xE1^\x18\xE2^\x85Z\rJ\x9A\xEE\xA5\xEC|\xA2\xA9\x8E"
crypt = ActiveSupport::MessageEncryptor.new(key)
encrypted_username = crypt.encrypt_and_sign("daniel")
// => "N0dHcFM3MnQrcW1HUk9UTGwxeUJsZmlCNzcwUGhrdUdtbE9YWnUxamZFST0tLUVUcUlIU2k1ZHIvTmlDRUgzM2FsS0E9PQ==--1ede80eb2b498ddf5133f8f3a45a82db2476c740"
Then in Scala I'm trying to decrypt like so:
var encrypted_str = "N0dHcFM3MnQrcW1HUk9UTGwxeUJsZmlCNzcwUGhrdUdtbE9YWnUxamZFST0tLUVUcUlIU2k1ZHIvTmlDRUgzM2FsS0E9PQ==--1ede80eb2b498ddf5133f8f3a45a82db2476c740"
val parts = encrypted_str.split("--");
val encryptedData = Base64.decodeBase64(parts(0))
val iv = Base64.decodeBase64(parts(1))
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, aesKey, new IvParameterSpec(iv.take(16)));
val result = cipher.doFinal(encryptedData);
println(new String(result, "UTF-8"))
But I run into this error:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
I think the problem might be here:
val iv = Base64.decodeBase64(parts(1))
The second part of your message is 1ede80eb2b498ddf5133f8f3a45a82db2476c740 which is not a base 64 encoded string, it's a hex encoded string. Try this instead:
Hex.decodeHex(parts(1))

Is it possible to generate UUID v1 with JMeter?

I read JMeter's manual and saw that there is __uuid() function for JMeter. It allows to generate UUID type 4 for JMeter tests. Is it possible to generate UUIDv1 in JMeter or maybe some plugin exists.
I would recommend taking the following steps:
Download Jug library (for example from here) and drop the .jar somewhere to JMeter Classpath
Restart JMeter to pick the .jar up
Once done you should be able to generate UUIDv1 using JSR223 Test Elements and Groovy language like:
import com.fasterxml.uuid.EthernetAddress
import com.fasterxml.uuid.Generators
import com.fasterxml.uuid.impl.TimeBasedGenerator
def addr = EthernetAddress.fromInterface()
def gen = Generators.timeBasedGenerator(addr)
def v1uuid = gen.generate()
log.info(v1uuid.toString())
Demo:
References:
Generating version 1 UUIDs
Groovy is the New Black
In jmeter you can add JSR 223 Sampler choose Java language and execute java code for UUID version 1:
String timeuuid = com.datastax.driver.core.utils.UUIDs.timeBased().toString();
And then add it to Jmeter variable:
vars.put("myUUID", timeuuid);
First, we'll generate the 64 least and most significant bits as long values:
private static long get64LeastSignificantBitsForVersion1() {
Random random = new Random();
long random63BitLong = random.nextLong() & 0x3FFFFFFFFFFFFFFFL;
long variant3BitFlag = 0x8000000000000000L;
return random63BitLong + variant3BitFlag;
}
private static long get64MostSignificantBitsForVersion1() {
LocalDateTime start = LocalDateTime.of(1582, 10, 15, 0, 0, 0);
Duration duration = Duration.between(start, LocalDateTime.now());
long seconds = duration.getSeconds();
long nanos = duration.getNano();
long timeForUuidIn100Nanos = seconds * 10000000 + nanos * 100;
long least12SignificatBitOfTime = (timeForUuidIn100Nanos & 0x000000000000FFFFL) >> 4;
long version = 1 << 12;
return
(timeForUuidIn100Nanos & 0xFFFFFFFFFFFF0000L) + version + least12SignificatBitOfTime;
}
We can then pass these two values to the constructor of the UUID:
public static UUID generateType1UUID() {
long most64SigBits = get64MostSignificantBitsForVersion1();
long least64SigBits = get64LeastSignificantBitsForVersion1();
return new UUID(most64SigBits, least64SigBits);
}

Resources