I am using OpenSSL HMAC SHA256 method to sign all my requests to the server generating a HASH using a private key. My requests look like:
www.myserver.com/url/to/resource?par1=val1&par2=val2&par3=val3&hash=GENERATEDHASH
So my server calculates a hash using the parameters and the same key, if the hashes match he considers that the request is OK.
I want to sign the responses (using a HTTP header maybe) too. My idea is to calculate the hash using the content of the response and add that hash to the header, so my other side can validate that response before processing it.
Any ideas on how to do that?
You might want to emulate Amazon's way of doing it?
http://docs.aws.amazon.com/AWSECommerceService/latest/DG/rest-signature.html
Related
Setting up my first Slack slash command. I built it out originally using the deprecated verification token but, for posterity, have decided to use signed secrets authentication.
Reading through the signed secrets documentation, I've had no issue validating requests that come in from the initial slash command. However, interaction requests have a completely different body structure and the method for calculating a secret hash do not produce a valid result (because the request body is different).
Here is a snippet from the docs on validating signed secrets.
slack_signing_secret = 'MY_SLACK_SIGNING_SECRET' // Set this as an environment variable
>>> 8f742231b10e8888abcd99yyyzzz85a5
request_body = request.body()
>>> token=xyzz0WbapA4vBCDEFasx0q6G&team_id=T1DC2JH3J&team_domain=testteamnow&channel_id=G8PSS9T3V&channel_name=foobar&user_id=U2CERLKJA&user_name=roadrunner&command=%2Fwebhook-collect&text=&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%2FT1DC2JH3J%2F397700885554%2F96rGlfmibIGlgcZRskXaIFfN&trigger_id=398738663015.47445629121.803a0bc887a14d10d2c447fce8b6703c
On invocation of the slash command this works as intended - the request body matches the structure in the example above. When the user interacts with the message, the response body uses the blocks api - which is completely different
If I'm not supposed to use the verification token and the request body from the interactive blocks api does not allow me to compute a valid hash, how am I supposed to validate interaction requests? I must be missing something while combing through the docs.
We have one URL parameter as "code_challenge" which gets generated at run time, this value we need to extract so that from next runs it can be handled. However since this code value is not captured in any previous requests/responses and need to extract at run time, unable to understand how to achieve.
Tried Regular Extractor choosing URL radio button, but it captures the value from recorded script.
Steps followed:
Record script using Blazmeter (Browse URL xx.com>Click Login)
Redirected to URL(s) in which one of the url has "code_Challenge" parameter with run time value)
First URL is: accounts-xx.com/oauth2/oidcdiscovery/.well-known/openid-configuration> The response doesn't have any parameter values
Second URL is:
https://accounts-xx.com/oauth2/authorize?response_type=code&client_id=zzzz&scope=ituytutut&redirect_uri=xx.com/callBack&code_challenge_method=ooo&**code_challenge=dsfsdlfhl**
In above 3rd point url, Code_challenge value is generated at run time when executed steps from browser.
However If replayed the recorded script which would have already generated code value hence other requests would fail. Due to this, need to get the code value fetched.
The code_challenge is generated from WS02 service.
Jmeter version: 5.3
Please suggest, or should we need to use Selenium webdriver integration.
Regular expression which would extract the value from recorded script:
As per Mitigating Authorization Code Interception Attacks article:
code_challenge The client creates and records a secret cryptographically random string (the code_verifier), which is then encoded using URL safe base64 encoding to transform it into the code_challenge.
As per PKCE in WSO2 IS server article:
1.Plain:
If a code_challenge method is mention as plain or not mention at all it will take this plain value. Then code_challenge will like:
code_challenge = code_verifier
2. SHA256:
To have the code_challenge as SHA256, we should mention this in request otherwise plain value will be assumed.For SHA256 code challenge will be like
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
Here base64url is same as base64encoding(used so that all machine can identify as same value) but trailing “=” will be removed and “+” & “/” are placed by “-” & “_” to avoid unnecessary length in URL.(otherwise ‘+’ becomes ‘%2B’, ‘/’ becomes ‘%2F’ and ‘=’ becomes ‘%3D in URL)
As much as possible, it is better to select the code challenge method as SHA256 then the flow will become more secure and hard to guess(if someone try to brute force it)
So I think you need to add JSR223 PreProcessor and calculate/generate the code_challenge using the algorithm used by your server in Groovy language, store the value into a JMeter Variable and use it in the request.
You can leave the field value empty and then its value gets updated once the request is sent. But you won't see the value in the request.
I had a similar issue, it worked in my case.
This is what I am having trouble understanding and doing.
I need to add a header called sign with the query's POST data signed by my key's "secret" according to the HMAC-SHA512 method. What is my query's post data? And how can I find it so that I can encrypt it and send it as a header.
These are my parameters: "command" => "returnBalances", "nonce" => Time.now.to_i
Please let me know:
How do I find my post request data.
How do I use the HMAC-SHA512 method to encrypt this data so that I can send it in a header. (using Ruby)
Thank you people let me know.
I answered your question more completely here, in the context of the Poloniex exchange:
Ruby Http Post Parameters
To answer your specific questions from this post:
How do I find my post request data?
POST data simply means the body of your request. This could be JSON, plain text, form data, etc. In cases where a specific format (i.e. JSON) isn't mentioned, POST data probably refers to POST form data (Content-Type: application/x-www-form-urlencoded). This is how data submitted from a web form is formatted and indeed that appears to be what Poloniex is looking for.
x-www-form-urlencoded data can be produced like this in Ruby:
form_data = URI.encode_www_form({:command => 'returnBalances', :nonce => Time.now.to_i * 1000 })
puts form_data
command=returnBalances&nonce=1447537613000
Mozilla Developer's Network link on POST form data.
How do I use the HMAC-SHA512 method to encrypt this data so that I can send it in a header? (using Ruby)
HMAC digest produces a unique string based on a secret key and the data provided. In Ruby, you can produce an HMAC digest like so:
OpenSSL::HMAC.hexdigest( 'sha512', secret, form_data)
I'm using codeigniter2.1.4.my problem is when i use
$this->encrypt->encode($row['service_id'])
in my view page ,it generates such a key that is not permitted url and i also want short encrypt key bcoz current encrypt key too big.Any solution?Thanks
A simple solution would be to send the encrypted key as a POST parameter instead of GET parameter. In case you do not want to do that, look into
$config['permitted_uri_chars']
in application/config/config.php. Add the characters that you want to send in URL. Remember. THIS IS A SECURITY COMPROMISE.
You can always change to another cipher algorithm using
$this->encrypt->set_cipher();
This is known to mess up your sessions as sessions are encrypted using the default algorithm. So if you set session, change cipher and again try modify or set session, it wont work. You need to make sure you set back the cipher to default after your encryption is done.
Check and try to understand system/libraries/Session.php, especially around the line
$cookie_data = $this->CI->encrypt->encode($cookie_data);
If you are interested in finding answer to "WHY"
Lets say I have a origin server which through the act of a redirect with particular query string params needs to provide details to a target server. However, I need to ensure those details came from my origin server only.
Also I can't sure the integrity of the target server. Or specifically, the target server might be compromised so any encryption keys might have been read by a malicious party.
I'm thinking I could sign the query string using some form of public/private keypair. The origin server uses a private key to sign the string, and the target server uses a public key to verify it came from my origin server, and the message hasn't been tampered with.
I'm far from a cryptography expert or anything, so any assumption here I've made might be wrong, please correct me if so :)
I'm basically after a (hopefully) simple way to do this in Ruby.
Probably, the easiest form of signing the query data (in your case a redirection URL) is by using an HMAC. Your origin and destination server would need to share a common key in this case - HMACs are not a form of public/private key cryptography, but rather a form of keyed hashing.
The module you're looking for is ruby-hmac, and your source and destination server would have to do something like:
require 'hmac-md5'
HMAC::MD5.new("<your shared key>").update("<your URL to check>").hexdigest
and compare on the destination side that the digest computed by the HMAC on the source side is equivalent: both sides thus do the same computation. The hexdigest of the HMAC can simply be transported by an additional query parameter from source to destination.