For the sake of me, I can’t get to validate a Telegram hash in Java.
I have a working JS example compiled from different sources that I’ve reduced to barebones to illustrate this question.
function main() {
var k = CryptoJS.HmacSHA256('k', 'WebAppData');
console.log("k: " + k);
var h = CryptoJS.HmacSHA256('data', k);
console.log("h: " + h);
}
main();
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
The response of the complete example matches the expected hash
"k: 3db03151d3fb2678c9fc0f24ee15817bfd1ff922a712a055f63066f875e43fc1"
"h: 9158b0aeb1e882c075ea46a0d5302cffba1a9b66b0df40f5f01eef614f7d9f94"
Trying to do the same thing using Apache commons’ Hmac method
var secretKey = new HmacUtils("HmacSHA256", "WebAppData").hmacHex("k");
var hash = new HmacUtils("HmacSHA256", secretKey).hmacHex("data");
I end up with the first one being correct but not the second one, that differs from the other implementation.
secretKey: 3db03151d3fb2678c9fc0f24ee15817bfd1ff922a712a055f63066f875e43fc1
hash: 2c73ad3290e04a382b29edea6cb0ef4b1454592429336c32e98ad611452581b2
what am I failing to see?
Isn’t there a method to handle this validation in the Telegram SDK I missed to avoid doing this by hand?
2
Answers
The problem is that you take the hex-encoded form of the secret key as the key of the hash. The
HmacUtils(String, String)
constructor will encode the string to bytes using UTF-8, which is not what you want here, so you need to use theHmacUtils(String, byte[])
constructor.So, you need to use the raw byte form:
Output:
This matches the hash from the JavaScript code.
Here is the full class for validation: