Python Code:
signature = hmac.new(bytearray.fromhex(key), data.encode('utf-8'), hashlib.sha256).hexdigest()
Solutions That I have tried
var compute_hmac = crypto.createHmac('sha256', key).update(data).digest('hex');
var compute_hmac = crypto.createHmac('sha256', Buffer.from(key, 'hex').toString()).update(data).digest('hex');
const hmac = crypto.createHmac('sha256', Buffer.from(key, 'hex'))
Trying to validate webhook signatures of the following API
https://developer.close.com/topics/webhooks/
data is the payload received, the same thing is passed to python and JS code. But somehow, hex digest of python code is validated and hex code of JS code is entirely different.
Please refer to API link mentioned above (webhook signatures) to understand what I'm trying to achieve
Pass directly the keybuffer instead of adding .toString() to it
var compute_hmac = crypto.createHmac('sha256', Buffer.from(key, 'hex')).update(data).digest('hex');
py code
import hashlib
import hmac
key ="A1FF92";
data = "hello"
signature = hmac.new(bytearray.fromhex(key), data.encode('utf-8'), hashlib.sha256).hexdigest()
//78a1151ddd4f298a134e4625362af2ab8ef4bd49719e17053ec1eadd4cbf1bab
node code
var crypto = require("crypto")
var key = "A1FF92"
var data="hello";
var compute_hmac = crypto.createHmac('sha256', Buffer.from(key, 'hex')).update(data).digest('hex');
// 78a1151ddd4f298a134e4625362af2ab8ef4bd49719e17053ec1eadd4cbf1bab
Related
I have Ruby 2.5.3 code that create hmac with sha256
require 'openssl'
key = '4629de5def93d6a2abea6afa9bd5476d9c6cbc04223f9a2f7e517b535dde3e25'
message = 'lucas'
hash = OpenSSL::HMAC.hexdigest('sha256', key, message)
hash => ba2e2505c6f302fb3c40bea4491d95bacd96c3d12e8fbe50197ca431165fcee2
But the result is different from Python & JavaScript code. What should I do in Ruby code to have the same result as from the others?
Python
import hmac
import hashlib
import binascii
message = "lucas"
key = "4629de5def93d6a2abea6afa9bd5476d9c6cbc04223f9a2f7e517b535dde3e25"
hash = hmac.new(
binascii.unhexlify(bytearray(key, "utf-8")),
msg=message.encode('utf-8'),
digestmod=hashlib.sha256
).hexdigest()
hash => 99427c7bba36a6902c5fd6383f2fb0214d19b81023296b4bd6b9e024836afea2
JavaScript
const crypto = require('crypto');
const message = 'lucas';
const key = '4629de5def93d6a2abea6afa9bd5476d9c6cbc04223f9a2f7e517b535dde3e25';
const hash = crypto.createHmac('sha256', Buffer.from(key, 'hex'))
.update(message)
.digest('hex');
hash => 99427c7bba36a6902c5fd6383f2fb0214d19b81023296b4bd6b9e024836afea2
In Python and JS you are using the "key" as hexstring, means that the hexstring is converted to a binary format. In Ruby the key is used without conversion. – Michael Fehr
This gave me the solution.
key = '4629de5def93d6a2abea6afa9bd5476d9c6cbc04223f9a2f7e517b535dde3e25'
message = 'lucas'
puts OpenSSL::HMAC.hexdigest('sha256', [key].pack('H*') , message)
hash => 99427c7bba36a6902c5fd6383f2fb0214d19b81023296b4bd6b9e024836afea2
thank you!
I have an Angular project in which I have to implement datatrans payment. But I am not able to generate sign for payment.
I am following process given on this link (enter link description here) to generate sign.
But i am not able to achive it.
I am using angular library crypto-js to generate HMAC-SHA-256 signed string.
Here is my javascript code.
const merchantId = 'xxxxxxx';
const refNo = '1234567890';
const amount = 0;
const currency = 'CHF';
const theme = 'DT2015';
const paymentmethod = 'VIS';
const stringSs = merchantId+amount+currency+refNo;
const base = 16;
// My Hmac Key
const s = 'fa3d0ea1772cf21e53158283e4f123ebf1eb1ccfb15619e2fc91ee6860a2e5e48409e902b610ce5dc6f7f77fab8affb60d69b2a7aa9acf56723d868d36ab3f32';
// Step 1: Code to generate hex to byte of hmac key
const a = s.replace(/../g, '$&_').slice (0, -1).split ('_').map ((x) => parseInt (x, base));
// Step 3: Sign the string with HMAC-SHA-256 together with your HMAC key
const signedString = HmacSHA256(a, stringSs);
// Step 4: Translate the signature from byte to hex format
const signString = enc.Hex.stringify(signedString);
Can you help me into this to suggest what i am doing wrong or in what way it can be achieved.
You can do it with crypto (no need of extra libraries to install)
// Typescript
import * as crypto from 'crypto';
function signKey (clientKey: string, msg: string) {
const key = new Buffer(clientKey, 'hex');
return crypto.createHmac('sha256', key).update(msg).digest('hex');
}
// Javascript
const crypto = require('crypto')
function signKey (clientKey, msg) {
const key = new Buffer(clientKey, 'hex');
return crypto.createHmac('sha256', key).update(msg).digest('hex');
}
signKey(s, stringSs)
To answer the question for crypto-js (see https://github.com/brix/crypto-js) as requested, the following will do the trick:
// Javascript; example from datatrans documentation using a random key
stringSs ='3000017692850CHF91827364';
key='1ca12d7c0629194a9f9d0dbbc957709dd3aed385925b077e726813f0b452de6a38256abd1116138d21754cfb33964b6b1aaa375b74d3580fcda916898f553c92';
expectedSign='d7dee9ae1e542bc02bcb063a3dd3673871b2e43ccb4c230f26e8b85d14e25901';
signedString = CryptoJS.HmacSHA256(stringSs, CryptoJS.enc.Hex.parse(key));
resultSign = CryptoJS.enc.Hex.stringify(signedString);
// now resultSign == expectedSign is true :-)
Ninja Turtles approach was almost correct except of step 1, hex to byte. Use a builtin function of Crypto-JS instead and everything works as expected.
The scenario is that I have a JS script that creates a HMAC for a user provided input and I want to compute the same HMAC for the same input using python. To make things clearer, consider the following JS and Python code snippets.
Javascript
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/hmac-sha256.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/enc-base64.min.js"></script>
<script>
var secretAccessKey = "bAvW5O18eSrxke4I7eFcrnrDJkN+wKQmx9aSHuMZQ0w=";
var stringtoSign = "Test";
// Generate HMAC SHA256 signature
var secretAccessKeyBase64 = CryptoJS.enc.Base64.parse(secretAccessKey);
var hash = CryptoJS.HmacSHA256(stringtoSign, secretAccessKeyBase64);
var signature = CryptoJS.enc.Base64.stringify(hash);
</script>
Python
stringToSign = "Test"
secretAccessKey = "bAvW5O18eSrxke4I7eFcrnrDJkN+wKQmx9aSHuMZQ0w="
secretAccessKeyBase64 = base64.b64decode(secretAccessKey).hex()
keyBytes = bytes(secretAccessKeyBase64, 'utf-8')
stringToSignBytes = bytes(stringToSign, 'utf-8')
signatureHash = hmac.new(keyBytes, stringToSignBytes, digestmod=hashlib.sha256).digest()
signature = base64.b64encode(signatureHash)
print(signature)
The Javascript code gives me b+1wRzDODA85vyDZkXByPIKO5qmnjCRNF5gZFi33/Ic=, while python gives me the value b'SsZ4bcYe3op1nGU6bySzlSc9kgg9Kgp37qzF15s2zNc='
Why is my python code generating a different HMAC for (seemingly) identical inputs that was provided to the JS script? Is there anyway to obtain the HMAC value outputted by the JS code using python?
You are using a Base64 encoded value as secret in Javascript, whereas in Python you use the plain text secret.
<script>
var secretAccessKeyBase64 = "secret";
var hash = CryptoJS.HmacSHA256("Message", secretAccessKeyBase64);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
document.write(hashInBase64);
</script>
This prints out the same value as the Python code:
qnR8UCqJggD55PohusaBNviGoOJ67HC6Btry4qXLVZc=
Edit:
base64 returns a byte-object there is no need to convert it to hex():
stringToSign = "Test"
secretAccessKey = "bAvW5O18eSrxke4I7eFcrnrDJkN+wKQmx9aSHuMZQ0w="
secretAccessKeyBase64 = base64.b64decode(secretAccessKey)
keyBytes = secretAccessKeyBase64
stringToSignBytes = bytes(stringToSign, 'utf-8')
signatureHash = hmac.new(keyBytes, stringToSignBytes, digestmod=hashlib.sha256).digest()
signature = base64.b64encode(signatureHash)
print(signature)
Prints correctly:
b'b+1wRzDODA85vyDZkXByPIKO5qmnjCRNF5gZFi33/Ic='
I'm attempting to port some Python code to Javascript. Here is the Python code:
# Python
import codecs
from Crypto.Cipher import AES
key = b"\xc3\x99\xff\xff\xc3\x99\xff\xff\xc3\x99\xff\xff\xc3\x99\xff\xff"
...
aes = AES.new(key, AES.MODE_ECB)
token = aes.encrypt("HELLO\x00\x00".encode("utf-8"))
token_hex = codecs.encode(token, "hex").decode("utf-8")
I'm not exactly sure how to port my Python key variable. Should it be UInt16Array...or a string?
This is my Javascript so far:
// Javascript
const crypto = require('crypto');
const key = '???' // <-- This is one place I am stuck. String? Byte array?
....
const cipher = crypto.createCipher('aes-128-ecb', key);
let tokenHex = cipher.update('HELLO\x00\x00', 'utf8', 'hex');
tokenHex = tokenHex.toString('utf8')
I appreciate any insight you can provide as to how I can get a matching tokenHex in Javascript.
Thank you!
What you are after is Buffer, which represents a collection of bytes.
You probably want to instantiate the key variable similar to this:
let key = Buffer.from("c399ff...", "hex");
I can get a hmac sing using Python as following:
import hmac, base64, hashlib
def make_sign():
hash_data = "data"
secret = "this is secret"
sha512 = hashlib.sha512
hmac_obj = hmac.new(secret, hash_data, sha512)
str_hash = hmac_obj.digest()
sign = base64.b64encode(str_hash)
hex_hash = hmac_obj.hexdigest()
hex_sign = base64.b64encode(hex_hash)
print "correct_sign:",sign
print "hex_digest_sign:",hex_sign
make_sign()
output:
correct_sign: Lg4pXNCIpitNQt2DLU19qWb+FxdsYZlK4LLncfkTzSidrYoFJLNolUziRqh09B5HyRdCTEP7enZp6/Te34FK1g==
hex_digest_sign: MmUwZTI5NWNkMDg4YTYyYjRkNDJkZDgzMmQ0ZDdkYTk2NmZlMTcxNzZjNjE5OTRhZTBiMmU3NzFmOTEzY2QyODlkYWQ4YTA1MjRiMzY4OTU0Y2UyNDZhODc0ZjQxZTQ3YzkxNzQyNGM0M2ZiN2E3NjY5ZWJmNGRlZGY4MTRhZDY=
but with js, I can get hex_digest_sign, but I need to get correct_sign for web request.
function make_request() {
hash_data = "data"
secret = "this is secret"
hmac = hmac_512(hash_data, secret)
var sign = $.base64.encode(hmac),
console.log("js_sign="+sign);
}
function hmac_512(message, secret) {
var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA512, secret);
hmac.update(message);
var hash = hmac.finalize();
return hash;
}
js output:
js_sign="MmUwZTI5NWNkMDg4YTYyYjRkNDJkZDgzMmQ0ZDdkYTk2NmZlMTcxNzZjNjE5OTRhZTBiMmU3NzFmOTEzY2QyODlkYWQ4YTA1MjRiMzY4OTU0Y2UyNDZhODc0ZjQxZTQ3YzkxNzQyNGM0M2ZiN2E3NjY5ZWJmNGRlZGY4MTRhZDY="
the correct sign is correct_sign: Lg4pXNCIpitNQt2DLU19qWb+FxdsYZlK4LLncfkTzSidrYoFJLNolUziRqh09B5HyRdCTEP7enZp6/Te34FK1g==
how to get it in js?
I suspect that you are running into trouble with types and encoding. According to the CryptoJS source, the iterative hashing style that you are using returns a WordArray once you call finalize().
With that, once you go to print the results, you are printing the contents of the WordArray.
The purpose for itterative hashing is typically if you have a large input, you can break it into chunks to work on one piece at a time. Try the below edit I made that removes this as it does not look like you need to iterate.
function hmac_512(message, secret) {
var newHMAC = CryptoJS.HmacSHA256(message, secret);
return newHMAC;
}
The above will simply return the HMAC in string form which, once Base64 encoded, should match the result you see in Python.
Hope this helps!