Play Integrity API Decryption Key: Bad base-64, with Base64.DEFAULT - kotlin

I have checked about this answer:
java.lang.IllegalArgumentException: bad base-64
However, the String format is definitely different in my project.
val key = "XX0XXxXXXXXxX/XXXXXX0XXX00X/0XX0xXXXX0Xxx0="
val bytes = Base64.decode(key, Base64.DEFAULT)
I referred to the official document:
https://developer.android.com/google/play/integrity/verdict, in which the Verification Key is decoded properly with the same method.
Please let me know if the key might be incorrect for some reasons.
Thank you.

The phrase I used to create the public.key contains an "#", which is not a legal Base64.
This might not be the main reason which it failed to decode, but it was solved after removing the "#".

Related

please explain? api signature example

(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.

How to replicate sha256 hash example from CyberSource REST API documentation?

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.

QueryString Encryption and Related Characters Problems

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.

Caucho Resin Digest Authentication with CustomAuthenticator, someone please enlighten me

Ok after experimenting a little bit I found out that resin was calling my AbstractAuthenticator implementation "authenticate" method that takes an HttpDigestCredentials object instead of DigestCredentials (still don't know when is called each one of them) the problem is that HttpDigestCredentials doesn't have a getDigest() method, instead it has a getResponse() method which doesn't return a hash or at least not a comparable one.
After creating my own hash of [[user:realmassword] [nonce] [method:uri]] the hash is very different, in fact I think getResponse() does not return the digest but maybe the server response to the browser?.
Any way this is my debugging log :
USER:user:PASSWORD:password:REALM:resin:METHOD:GET:URI/appe/appe.html:NONCE:HsJzN+j+GQD:CNONCE:b1ad4fa1ba857cac88c202e64528bc0c:CLIENTDIGEST:[B#5dcd8bf7:SERVERDIGEST:I4DkRCh21YG2Mk14iTe+hg==
as you can see both the supposed client nonce is very very different from the server generated nonce, in fact the client nonce doesn't look like a MD5 hash at all.
Please has someone does this before? is there something missing in the HttpDigestCredentials? I know digest is barely used.
Please, I know about SSL but I can't have an SSL certificate just yet so don't tell me "Why don't you use SSL". ;)
Update:
Not sure if was the right thing to do but, as I read before Resin uses base64 format for hashes so I used apache commons-codec-1.6 to use encodeBase64String() method and now the hashes look alike but they are no the same.
I tried both passwordDigest.getPasswordDigest(a1+':'+nonce+':'+a2); passwordDigest.getPasswordDigest(a1+':'+nonce+':'+ncount+':'+cnonce+':'+qop+':'+a2);
and none of them gives the same hash as the one from HttpDigestCredentials.
Ok I finally made it . Weird subject Huh, only two views?
First, digest authentication makes use of user, password, realm, nonce, client_nonce, nonce_count, method, qop, and uri. Basically it uses the full digest spec. So in order to calculate the hash one must calculate it with all the whistles. Is just a matter of calling the get method for each one of the variables from HttpDigestCredentials except for user and password. The user will come in the form of a Principal and the password you must look for it yourself in your DB (in my case a DB4O database).
Then you must create a PasswordDigest object, that will take care of generate a hash with the getPasswordDigest() method, but first one must set the format to hex with passwordDigestObject.setFormat("hex").
There is one for the HA1 getPasswordDigest(user,password,realm) and there is another getPasswordDigest() method that takes just one string and one can use it to generate the rest of the hashes, both HA2 and with the previous hashed HA1 the final hash, of course with the nonce nonce_count client_nonce and qop, of course each one separated by a semicolon.
Then it comes the tricky part, although resin works with base64 encoding for digest when you call the getResponse() method from HttpDigestCredentials it returns a byte array (which is weird) so in order to compare it with your hash what I did was use the Hex.encodeHexString() method from org.apache.commons.codec.binary.Hex and pass the HttpCredentialsDigest getResponse() return value, and that will give a nice hex String to compare.
I was doing it the other way around, I was using the Base64 hash from PasswordDigest and converting the HttpDigestCredentials hash to Base64 and the resulting string were never the same.

S3's BOTO is returning NoSuchKey while trying to copy an existing key

I've create a key on S3.
mykey.exists() returns true
mykey.get_contents_to_filename() generates a file that is correct
But:
mykey.copy('bucket', '/backup/file')
returns:
NoSuchKey
The Specified key does not exist.
Key = mykey
It looks like I'm using boto 2.0b4
If the key exists, why am I getting a NoSuchKey error?
What am I missing?
edit: change backslash in key name to the foreslashes that I am actually using
I have a theory that because amazon s3 is eventually consistent, one request could see the key (.exists() == True) while another request ends up at a different s3 server which does not yet have knowledge of the new key (an inconsistent read - this is the difficulty with eventually consistent data stores. This is known behavior for s3 with a put followed by a head/get. I expect it to hold for copy as well.) After a usually short (but indefinite) period of time all requests will see your key. Normally this is only about a second or two. Put a 30 second timeout in your code between the exists() check and the copy. Does it still happen?
The issue is described here: https://forums.aws.amazon.com/thread.jspa?threadID=21634&tstart=0)
I think you may be running into an issue with your key name. The baskslash characters in the string '\backup\file' are actually is interpreted as string escapes so '\b' is replaced with the ASCII backspace character and '\f' is interpreted as the ASCII formfeed (see this for more details). While that probably isn't what you intended, it really should still work but there was a bug in the escaping of key names in boto2.0b4 (which is fixed now in github master) that is preventing this from working.
If you actually want your keyname to be "\backup\file" try specifying it as r'\backup\file' in Python. This treats it as a raw string and no escape processing will occur.