-
-
Save Pitasi/574cb19348141d7bf8de83a0555fd2dc to your computer and use it in GitHub Desktop.
// Copied by https://gist.github.com/dotcypress/8fd12d6e886cd74bba8f1aa8dbd346aa, | |
// thanks for improving code style | |
const { createHash, createHmac } = require('crypto'); | |
const TOKEN = "ABC:12345..."; | |
// I prefer get the secret's hash once but check the gist linked | |
// on line 1 if you prefer passing the bot token as a param | |
const secret = createHash('sha256') | |
.update(TOKEN) | |
.digest() | |
function checkSignature ({ hash, ...data }) { | |
const checkString = Object.keys(data) | |
.sort() | |
.filter((k) => data[k]) | |
.map(k => (`${k}=${data[k]}`)) | |
.join('\n'); | |
const hmac = createHmac('sha256', secret) | |
.update(checkString) | |
.digest('hex'); | |
return hmac === hash; | |
} | |
// Sample usage | |
const payload = { | |
id: '424242424242', | |
first_name: 'John', | |
last_name: 'Doe', | |
username: 'username', | |
photo_url: 'https://t.me/i/userpic/320/username.jpg', | |
auth_date: '1519400000', | |
hash: '87e5a7e644d0ee362334d92bc8ecc981ca11ffc11eca809505' | |
} | |
checkSignature(payload) |
Did you actually use this token const TOKEN = "ABC:12345...";
to create the hash in payload
?
The example as it is doesn't work for me. It works as soon as I use real data, i.e. a live response from Telegram and my own bot token.
I think people merely copy/pasting and expecting this to work is what leads to confusion.
Replace payload.hash
with fdd4901b22ee5ea34d77caeac88b5ecba818226ab9c7c7775c8ff675d7e4cb92
and this example works.
I think the gist you copied this from always used some made-up value for the hash, to begin with. Even the length doesn't add up.
@ImTheDeveloper I had the same issue and found out that when users do not specify their last_name
the hash does not match. To fix the error, I've filtered out empty data for checkString
:
const checkString = Object.keys(data)
.sort()
.filter((k) => data[k])
.map(k => (`${k}=${data[k]}`))
.join('\n');
Thanks @lub0v, I updated the gist with your suggestion :)
Updated version
const secret = crypto.createHash('sha256')
.update(botToken?.trim())
.digest();
const checkString = Object.keys(data)
.sort()
.filter((k) => data[k])
.filter((k) => ![ 'hash' ].includes(k))
.map(k => (`${k}=${data[k]}`))
.join('\n');
const hmac = crypto.createHmac('sha256', secret)
.update(checkString)
.digest('hex');
return hmac === data.hash;
Hi for me it did nit work without WebAppData
const originalHash = Buffer.from(data.hash, 'hex');
delete data.hash;
const checkString = Object.keys(data)
.sort()
.map((key) => `${key}=${data[key]}`)
.join('\n');
const hmacKey = crypto
.createHmac('sha256', 'WebAppData')
.update(Buffer.from(botToken, 'utf8'))
.digest();
const hmac = crypto.createHmac('sha256', hmacKey);
hmac.update(checkString);
const computedHash = hmac.digest();
return crypto.timingSafeEqual(computedHash, originalHash);
IT WORKS, THANKS!
I'm not sure. Is it possible that you are receiving requests that are not from Telegram? Did you make any change to my code?