I've got test plan :
Thread groups ( users 3, loop 2)
Random Variable
HTTP Request
I want variable to be changed only per loop, so under each iteration all three threads should send same value.
So I want something like this :
request where random var = X
request where random var = X
request where random var = X
request where random var = Y
request where random var = Y
request where random var = Y
I tried a lot of workounds but can't find proper solution.
P.S. I don't want to read variables from file. I need to generate them
No matter whatever you "want" the best option would be pre-generating random values somewhere in setUp Thread Group and writing it to the file and then using CSV Data Set Config in the "main" Thread Group to read the values.
However if this is still not something you "want" here is yet another "workaround", hopefully it's "proper" enough for you:
Add JSR223 PreProcessor as a child of the request which you "want" to parameterize with the random variable
Put the following code into "Script" area:
if (props.get('foo_' + vars.getIteration()) != null {
props.put('foo_' + vars.getIteration(), org.apache.commons.lang3.RandomUtils.nextInt(0, 100))
}
Refer the "generated" random value using the following __groovy() function where required:
${__groovy(props.get('foo_' + vars.getIteration()),)}
Demo:
(What I'm ultimately trying to accomplish is to look up individual products on Walmart.com using product codes, so if anyone has another way of doing that, that works too)
Walmart.io's Product Lookup API requires a header called "WM_SEC.AUTH_SIGNATURE", but I can't figure out how to generate it using Ruby. Some Java code is given here (I'm not sure about the legality of reproducing that code here) but I don't know Java so I don't understand what they're doing.
This SO question tries to explain the process, but again I'm not clear on exactly what's being done.
To get the digital signature using your own code, follow these steps:
Get the Consumer ID and your Base 64-encoded Private Key you generated
in Seller Center.
Get the full URL you wish to call, including any
path and query parameters.
Use the GET method to construct an input
for the digital signature.
Use the structure listed below: The
Consumer ID issued to you_ + "\n" + the URL of the API call you are
making + "\n" + the request method of the API call you are making in
all capitals + "\n" + the Unix Epoch timestamp now (in milliseconds
since Jan 01 1970 UTC) + "\n"
** Note: The order of the parameters and the line returns \n are important to generate the signature properly
Generate the byte array of the structured data listed in step 3 using
the following steps:
a. Decode the byte array with Base-64.
b. Encode the resulting value using PKCS#8 to represent your Private
Key. Libraries in various languages offer the ability to identify that
the Private Key is in PKCS#8 format and not in other conflicting
formats such as PKCS#1.
c. Use this byte representation of your
private key to sign the data using SHA-256 with RSA.
d. Encode the generated digital signature using Base-64.
Use the generated digital signature and the timestamp to make your API
call.
I've gotten as far as this:
time = DateTime.now.strftime('%Q')
customerid = "customerid"
link = "https://developer.api.walmart.com/api-proxy/service/affil/product/v2/items/4837473"
method = "POST"
uncoded = customerid + "\n" + link + "\n" + method + "\n" + time + "\n"
encoded = Base64.encode64(uncoded)
privatekey = "longrsakey"
But I don't know how to continue. Do I have to encode my privatekey into PKCS#8 and then use the result to encode my encoded? I can't even find a PKCS#8 encoder in Ruby.
Can anyone help?
Here is how you can create the signature needed to make the request, assuming you are trying to access the affiliate API:
version = 'YOUR VERSION'
consumer_id = "YOUR CONSUMER ID"
time_stamp = (Time.now.to_i * 1000).to_s
p_key = "YOUR PRIVATE KEY"
digest = OpenSSL::Digest.new('sha256')
data = consumer_id + "\n" + time_stamp + "\n" + version + "\n"
k = OpenSSL::PKey::RSA.new(p_key.to_s)
digest = OpenSSL::Digest::SHA256.new
signature = k.sign(digest,data)
signature = Base64.strict_encode64(signature)
headers = {
"WM_SEC.KEY_VERSION": version,
"WM_CONSUMER.ID": consumer_id,
"WM_CONSUMER.INTIMESTAMP": time_stamp,
"WM_SEC.AUTH_SIGNATURE": signature
}
puts HTTParty.get("https://developer.api.walmart.com/api-proxy/service/affil/product/v2/taxonomy", headers: headers).parsed_response
Need to pass 34 length value for a field in JMeter.
length of padding = 34-(len(itemcode)+1)
need to have space for padding as per above calculation.
total 34 length for this field= ItemCode+"N"+X ,
the "N" length = 34-len(ItemCode)-1
Item code need to fetch from previous response.
This can be achieved by JSR223 post-processor with below code.
log.info('${prod2name}');
var s= '${prod2name}';
var totallength=34;
var vallength=s.length;
var spacelength=totallength-parseInt(vallength)-1;
var finall=s;
for(i=1;i<=spacelength;i++){
finall=finall+" ";
}
var finall=finall+"X";
log.info(finall.length);
vars.put("z",finall);
I'm having trouble encrypting a value from a third party vendor I am using.
Their instructions are as follows:
1) Convert the encryption password to a byte array.
2) Convert the value to be encrypted to a byte array.
3) The entire length of the array is inserted as the first four bytes onto the front
of the first block of the resultant byte array before encryption.
4) Encrypt the value using AES with:
1. 256-bit key size,
2. 256-bit block size,
3. Encryption Mode ECB, and
4. an EMPTY initialization vector.
5) After encryption, you should now have a byte array that holds the encrypted value.
6) Convert each byte to a HEX format and string all the HEX values together.
7) The final result is a string of HEX values. This is the final encrypted value to be passed.
The length of the final value will always be an even number.
EXAMPLE:
Given the following input values:
plainText: 2017/02/07 22:46
secretKey: ABCD1234FGHI5678
The following string will be produced:
D6281D5BE6CD6E79BB41C039F4DD020FBEC9D290AD631B2598A6DFF55C68AD04
What I've tried so far...
plain_text = "2017/02/07 22:46"
secret_key = "ABCD1234FGHI5678"
plain_text_byte_array = plain_text.bytes
plain_text_byte_array.unshift(0).unshift(0).unshift(0).unshift(16) # I found a Java example in their documentation and this is what they do. They prepend their byte array with 16, 0, 0, 0
secret_byte_array = secret_key.bytes
secret_byte_array = secret_byte_array.concat([0, 0, 0,...]) # also from their java example, they append the secret_byte array with 16 0's in order to get its length to 32
cipher = OpenSSL::Cipher::AES256.new(:ECB)
cipher.key = secret_byte_array.pack("C*")
encrypted = cipher.update(plain_text_byte_array.pack("C*")) + cipher.final
p encrypted.unpack("H*").first.to_s.upcase
# Result is:
# "84A0E5DCA7D704C41332F86E707DDAC244A1A87C38A906145DE4060D2BC5C8F4"
As you can see my result is off from the actual result which should be
"D6281D5BE6CD6E79BB41C039F4DD020FBEC9D290AD631B2598A6DFF55C68AD04"
Does anyone know if I am missing something or doing something strange. Their instructions were difficult for me to parse through so maybe I'm missing something. Thank you for any help anyone can provide! (I've tried a ton of different variations on what you see above). I just need some guidance or at least someone to tell me I'm not crazy for not understanding their instructions.
I managed to reproduce their result - the process they've used is extremely convoluted and as far from elegant as it could possibly be. I've attached a far more descriptive explanation of the steps required to achieve their result, and the C# source code I used to do so.
Convert the password to a byte array. The byte array must be 32 bytes in length, and, if the password is not long enough, should be right-padded with 0 bytes. Thus their password, hex-encoded, becomes 4142434431323334464748493536373800000000000000000000000000000000.
Convert the value to be encrypted to a byte array. This one is simple enough, just encode with UTF-8.
The entire length of the array is inserted as the first four bytes onto the front of the first block of the resultant byte array before encryption. This is stupid and serves no purpose, but take the length of the byte array from step 2 as an unsigned 32-bit integer and convert to a little endian byte array. Prefix this to the array from step 2.
Encrypt the value using AES. Uhm. No don't do that. Encrypt the value with Rijndael, using a 256-bit block size, 256-bit key size, ECB mode and zero's for padding.
The rest is easy, just convert the result of encryption to hex.
The code I used to achieve this result is below, in C#. I don't know Ruby all that well sorry.
// 1. Convert the encryption password to a byte array.
byte[] passwordBytesOriginal = Encoding.UTF8.GetBytes("ABCD1234FGHI5678");
byte[] passwordBytes = new byte[32];
Array.Copy(passwordBytesOriginal, 0, passwordBytes, 0, passwordBytesOriginal.Length);
// 2. Convert the value to be encrypted to a byte array.
byte[] valueBytes = Encoding.UTF8.GetBytes("2017/02/07 22:46");
// 3. The entire length of the array is inserted as the first four bytes onto the front
// of the first block of the resultant byte array before encryption.
byte[] valueLengthAsBytes = BitConverter.GetBytes((uint)valueBytes.Length);
byte[] finalPlaintext = new byte[valueBytes.Length + valueLengthAsBytes.Length];
Array.Copy(valueLengthAsBytes, 0, finalPlaintext, 0, valueLengthAsBytes.Length);
Array.Copy(valueBytes, 0, finalPlaintext, valueLengthAsBytes.Length, valueBytes.Length);
// 4. Encrypt the value using AES...
byte[] ciphertext;
using (RijndaelManaged rijn = new RijndaelManaged())
{
rijn.BlockSize = 256;
rijn.KeySize = 256;
rijn.Key = passwordBytes;
rijn.Mode = CipherMode.ECB;
rijn.Padding = PaddingMode.Zeros;
var encryptor = rijn.CreateEncryptor();
ciphertext = encryptor.TransformFinalBlock(finalPlaintext, 0, finalPlaintext.Length);
}
// 5., 6., 7...
string result = BitConverter.ToString(ciphertext).Replace("-", "").ToUpper();
Console.WriteLine(result); // D6281D5BE6CD6E79BB41C039F4DD020FBEC9D290AD631B2598A6DFF55C68AD04
Based on Luke's excellent answer here is the Ruby version. I had to use the ruby-mcrypt gem and install the mcrypt library locally using brew install libmcrypt.
It is as Luke's answer points out that the secret key should be right padded with 0's. Here is my code:
plain_text = "2017/02/07 22:46"
secret_text = "ABCD1234FGHI5678"
answer = "D6281D5BE6CD6E79BB41C039F4DD020FBEC9D290AD631B2598A6DFF55C68AD04"
def format_byte_arrays(plain, secret)
zero_byte_array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
length_array = [16, 0, 0, 0]
plain_bytes = length_array.concat(plain.bytes)
secret_bytes = secret.bytes.concat(zero_byte_array)
[plain_bytes, secret_bytes]
end
plain_bytes, secret_bytes = format_byte_arrays(plain_text, secret_text)
final_plain, final_secret = [plain_bytes.pack("C*"), secret_bytes.pack("C*")]
cipher = Mcrypt.new("rijndael-256", :ecb, final_secret, nil, :zeros)
encrypted = cipher.encrypt(final_plain)
result = encrypted.unpack("H*").first.to_s.upcase
The result will be the correct answer.
So I have this pseudo code I need Installscript syntax for, for a Basic MSI installation I am creating with Installshield.
I need to call in a property previously set, [SERIAL] which is three digits long.
If the value is higher than 235 I need to subtract 235 from the value and save it as a string, and another string seperate as 2, otherwise 1. The two result strings then need to be set as new global properties for use later in the installation.
Pseudo code:
// call in the SERIAL property here.
if SERIAL > 235 then
string sIOVERSION = 2;
string sIOIP = "192.22." + (SERIAL - 235) + ".1";
else
string sIOVERSION = 1;
string sIOIP = "192.2." + SERIAL + ".1";
endif
// update properties [IOVER] and [IOIP] to the values of sIOVERSION and sIOIP
There are other approaches, but as a starting point for doing this in an InstallScript custom action, look for MsiGetProperty and MsiSetProperty, StrToNum, and Sprintf.