Reputation: 1542
im am following this amazon documentation in an attempt to find the algorithm to generate a signature in javascript. I cannot seem to get it to work.
// html
// <head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/sha256.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/hmac.min.js"></script>
// body (javascript)
var test_string = "GET\nwebservices.amazon.com\n/onca/xml\nAWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&AssociateTag=mytag-20&ItemId=0679722769&Operation=ItemLookup&ResponseGroup=Images%2CItemAttributes%2COffers%2CReviews&Service=AWSECommerceService&Timestamp=2014-08-18T12%3A00%3A00Z&Version=2013-08-01"
var signature2 = CryptoJS.HmacSHA256(test_string, "1234567890");
console.log(signature2.toString());
I amd getting 8fb6d93342d767d797799aee4ea5a6d8322f0d8554537c313cfa69fa25f1cd07
I should be getting j7bZM0LXZ9eXeZruTqWm2DIvDYVUU3wxPPpp+iXxzQc=
Hmmm anyone knows whats wrong?
Upvotes: 0
Views: 1241
Reputation: 193
let hash = CryptoJS.HmacSHA256(message, secret_key);
let result = CryptoJS.enc.Base64.stringify(hash);
I'm posting this solution here since I'm trying to do this exact same exercise in ReactNative, and ReactNative doesn't like npm's base crypto package. CryptoJS works as a replacement.
NOTE: (this was infuriating) I had to get rid of the first \n, though Amazon specifically tells you to prepend the lines with breaks and the GET has a line space above it in their example..
FULL SOLUTION:
let secret_key = "1234567890";
let message = 'GET' +
'\nwebservices.amazon.com' +
'\n/onca/xml' +
'\nAWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&AssociateTag=mytag-20&ItemId=0679722769&Operation=ItemLookup&ResponseGroup=Images%2CItemAttributes%2COffers%2CReviews&Service=AWSECommerceService&Timestamp=2014-08-18T12%3A00%3A00Z&Version=2013-08-01'
let hash = CryptoJS.HmacSHA256(message, secret_key);
let result = CryptoJS.enc.Base64.stringify(hash);
console.log('MARK: RESULT ', result);
Upvotes: 0
Reputation: 1038710
There's nothing wrong, it's just that the string you got represents an array of bytes (with their hex representation). So all you need to do is Base 64 encode this array of bytes and you will get the exact same result. Checkout it out here, paste your hex represented byte array and base 64 encode it: http://tomeko.net/online_tools/hex_to_base64.php?lang=en
As far as how this can be done, well, you may have a look at this question or this one.
UPDATE:
As pointed out in the comments it seems that there's a built-in way in cryptojs to convert directly to base64:
console.log(signature2.toString(CryptoJS.enc.Base64));
Upvotes: 2