(Update: still stuck after changes made from John's comment)
I am hoping for somebody to kindly try to explain in layman's terms how the signature is generated in the following example? I am pretty much stuck at this point.. I get the same result in an online hash generator (see picture below) and in my own code; but it differs from the example in the website (also pictured below).
https://www.gate.io/docs/apiv4/en/#authentication
edit: website seems only reachable through google search, direct link gives 404? So I attached the page as image, see below
Request: List all orders
GET /api/v4/futures/orders?contract=BTC_USD&status=finished&limit=50
HTTP/1.1
secret:
secret
resulting signature string (edit: updated, thanks #John Glenn):
GET\n/api/v4/futures/orders\ncontract=BTC_USD&status=finished&limit=50\ncf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e\n1541993715
(note that in the example on the website, there are line breaks for readability)
Signature generated according to the example:
eae42da914a590ddf727473aff25fc87d50b64783941061f47a3fdb92742541fc4c2c14017581b4199a1418d54471c269c03a38d788d802e2c306c37636389f0
Explanation from the website:
Signature generation method is HexEncode(HMAC_SHA512(secret,
signature_string)), i.e., the hexadecimal digest output of HMAC-SHA512
with APIv4 secret as secret and signature string as message.
But if I put it into a HMAC-SHA512 generator (e.g., https://www.javainuse.com/hmac), the value I get is:
58000238bf5eef226028e108df259184f14bf3021eb27c324a808334d187da42c38f4510b30215ee9b0c05d6352396e99f67fa920079746bb4dfd70506592f6d
I suspect I am missing a very essential point but I am quite lost at this time..
thank you very much for your help!
Your resulting signature string is incorrect. According the to website, this is how you should build it, with each element separated by \n.
request verb
request URL
plain text query string from the URL
hash of the request body, which is an empty string in this case
the Unix timestamp in seconds
For your example, the resulting signature string values should be:
GET (but you have POST)
/api/v4/futures/orders
contract=BTC_USD&status=finished&limit=50 (MISSING from your string)
just use the empty string hash value from the example
use the Unix timestamp from the example
Solved!
The "\n" were not regular expressions but actual newlines in the example. In other words, the newlines should be entered as ascii newline character.
Then I got the same result in the generator as from the website.
Related
I am investigating the CyberSource REST API and want to test the JSON Web Token Authentication method as documented here: https://developer.cybersource.com/api/developer-guides/dita-gettingstarted/authentication/GenerateHeader/jwtTokenAuthentication.html
I am unable to replicate the sha256 hash of the JSON payload described in the JWT Payload/Claim Set section.
{
"clientReferenceInformation" : {
"code" : "TC50171_3"
},
"orderInformation" : {
"amountDetails" : {
"totalAmount" : "102.21",
"currency" : "USD"
}
}
}
I've attempted to use the sha256sum command in binary and text format on a file containing the payload example. I've also attempted running this command on different permutations of this payload, such as without whitespace or newlines.
I expect to get the example hash of
2b4fee10da8c5e1feaad32b014021e079fe4afcf06af223004af944011a7cb65c
but instead get
f710ef58876f83e36b80a83c8ec7da75c8c1640d77d598c470a3dd85ae1458d3 and other dissimilar hashes.
What am I doing wrong?
Since the alleged "example" hash contains 33 hex characters one can see that it is not a possible valid output of SHA256. So there is nothing you can do to make your example match theirs.
There is also a base64 example in that discussion, but it is also not valid base64. By adding an extra padding character '=' to the base64 it can be made valid, and decoding it reveals that it mostly matches the alleged SHA256 hash.
My guess is that the values on that page are just examples of what values look like to the human eye rather than test vectors you are supposed to match exactly.
Probably you are not doing anything wrong. Hash functions have a avalanche effect, wherein any different bit in the input changes a lot the output hash. If the site's original example used a different encoding, or had a different order for the JSON elements, or even had more or less tabs, spaces, line breaks, or any other "trash" character, you'll have a hard time to find a fitting message for the hash showed in the site.
Usually, cryptographic solutions use canonicalizations to avoid this kind of problem (different hash values for semantically equal messages). However, the JWT specification doesn't specify any type of canonicalization for JSON.
In short, I think you don't have to worry about this. Your JWT implementation will be correct as long you use a valid (correctly implemented) hash function.
Also, I noticed that the JWT specification doesn't specify a "Digest" field for the JWT payload. So, you may not even need to use this field. Unless CyberSource REST API makes it mandatory.
Basic question but couldn't find an answer to this.
There is fake API testing tool located here
https://jsonplaceholder.typicode.com/todos
When I add a query like this
https://jsonplaceholder.typicode.com/todos?userId=4
I get a response
When I change the query to this
https://jsonplaceholder.typicode.com/todos?userId<4
it returns null
How would I query in the url userId that is less than 4?
You need to encode the '<' sign as a special character with its hexadecimal code ('<' is 3c) so your query becomes:
https://jsonplaceholder.typicode.com/todos?userId%3c4
Any special character in a url can be coded as % followed by its two-digit hexadecimal code.
EDIT: After trying the URL with my change, I was able to get the '<' sign decoded as I mentioned above. However, it doesn't seem to provide the expected return (all user IDs less than 4). It returns more user IDs than this. Maybe need to check the API docs to make sure that 'userId<4' is a correct field definition.
I have implemented this http://jacob.jkrall.net/totp/ in vbscript.
My code given the same hex gives the right 6-digit otp, so that part is working.
I've also verified the HMAC-SHA-1. encoding against an online generator, http://www.freeformatter.com/hmac-generator.html#ad-output, same input gives same output.
My time is the same as http://www.currenttimestamp.com/
I've generated a qrcode at http://www.qr-koder.dk/ with the string otpauth://totp/$LABEL?secret=$SECRET and the google authenticator app reads the code and starts outputting the 6 digit code changing every 30 seconds.
BUT THE CODES FROM THE APP DOES NOT MATCH THE 6-DIGIT CODE THE VBSCRIPT GENERATES!
I've even tried trunc(time/30) +/-7500 steps to see if it was a timezone/daylight saving problem, to no avail.
As the other parts of the routine to generate the 6 digits seem to work I've come to the conclusion I don't understand this:
the url on the qr-code is
otpauth://totp/$LABEL?secret=$SECRET
with the explanation
LABEL can be used to describe the key in your app, while SECRET is the
16-character base32-encoded shared secret, which is now known to both
the client and the server.
So when I calculate HMAC-SHA-1(SECRET, time()/30)
should the SECRET be the same string given to both the app and the calculation?
If I select a secret of 1234567890, the base32 is GEZDGNBVGY3TQOJQ according to http://emn178.github.io/online-tools/base32_encode.html.
Should I then take
HMAC-SHA-1("1234567890", time()/30)
or
HMAC-SHA-1("GEZDGNBVGY3TQOJQ", time()/30)
?
I believe I've tried both, and neither works.
The system unix time is correct.
I guess the problem might be with the secret in your HMAC-SHA-1 function. It very much depends on what the HMAC-SHA-1 expects.
Your string "123456790" might be a binary string. Is it an ascii representation or utf8? I.e. is this string 10 bytes or 20 bytes long?
I recommend getting the input string in your VBScript right.
On the other hand, instead of writing your own VBScript, you can also use a ready made solution like the privacyIDEA authentication server, which is open source and also comes with TOTP.
Web.HttpUtility.UrlEncode method in my project. When I am encoding name in English language then I got correct result. For example,
string temp = System.Web.HttpUtility.UrlEncode("Jewelry");
then I got exact result in temp variable. But if I wrote name in Russian language then I got different result.
string temp = System.Web.HttpUtility.UrlEncode("ювелирные изделия");
then I got value in temp variable like "%d1%8e%d0%b2%d0%b5%d0%bb%d0%b8%d1%80%d0%bd%d1%8b%d0%b5+%d0%b8%d0%b7%d0%b4%d0%b5%d0%bb%d0%b8%d1%8f"
Can anyone help me how to achieve exact name as per language?
Thank you!
Actually, the method has "done the right thing" for you!
It encodes non-ASCII characters so that it can be valid in all of the cases and transmit over the Internet. If you put your temp variable in an URL as a parameter, you will get your correct result at server side. That's what UrlEncode means for. Here your question is not a problem at all.
So please have a look at this link for further reading to understand about URL Encoding: http://www.w3schools.com/tags/ref_urlencode.asp
If you input that Russian word to the "URL Encoding Functions" part in the page I have given, it will return the same result as Web.HttpUtility.UrlEncode method does.
Can anyone help me how to achieve exact name as per language?
In short: not with that method, but it might depend on what is your exact goal.
In details:
In general URIs as defined by RFC 3986 (see Section 2: Characters) may contain any of the following characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]#!$&'()*+,;=. Any other character needs to be encoded with the percent-encoding (%hh).
This is why UrlEncode produces
UrlEncode("Jewelry") -> "Jewelry"
UrlEncode("ювелирные изделия") -> "%d1%8e%d0%b2%d0%b5%d0%bb%d0%b8%d1%80%d0%bd%d1%8b%d0%b5+%d0%b8%d0%b7%d0%b4%d0%b5%d0%bb%d0%b8%d1%8f"
The string of "ювелирные изделия" contains characters that are not allowed in a URL as per RFC 3986.
Today, modern browsers could work with UTF-8 in URL it might be not necessary to use UrlEncode(). See example: http://jsfiddle.net/ybgt96ms/
I'm using a 64base data encryption function to Encrypt and Decrypt emil addresses sent in links and back in QueryString using :
Encrypt(txtEmail.Text).ToString
// Which generate something like this " pqM/rgLD9PSrE+Ofm4pt4kg86+1RChHD "
Decrypt(Request("email").ToString
But the Decrypt didn't work fine and returned an error "Invalid length for a Base-64 char array" until I fond that I may solve it using :
Decrypt(Request("email").Replace(" ", "+").ToString)
Since the plus sign "+" character was generating a space when call from a URL.
I also tried UrlEncode but didn't help
Decrypt(Server.UrlEncode(Request("email")))
Now my questions is:
Is this the only problem may I face with the encrypted strings?
Is there another way to solve the problem more effective than I used with replace function?
Thank you all in advance
This would happen if you don't generate the URL properly.
The ASP.Net Request accessors will automatically decode the data that you access.
However, you need to URL-data-encode your string before putting it in the querystring in the first place.