Skip to content

Instantly share code, notes, and snippets.

@bezenson
Forked from zubiden/validate_init_data.js
Created January 21, 2023 22:25
Show Gist options
  • Save bezenson/8f7e470c84b0cda09f14d40f7adc1b8a to your computer and use it in GitHub Desktop.
Save bezenson/8f7e470c84b0cda09f14d40f7adc1b8a to your computer and use it in GitHub Desktop.
Telegram Web Bots data validation in JavaScript via Web Crypto API (dependency-free)
// Thanks to @MarvinMiles for Telegram Widget Login check function https://gist.github.com/MarvinMiles/f041205d872b0d8547d054eafeafe2a5
// This function validates Web App input https://core.telegram.org/bots/webapps#validating-data-received-via-the-web-app
// Transforms Telegram.WebApp.initData string into object
function transformInitData(initData) {
return Object.fromEntries(new URLSearchParams(initData));
}
// Accepts init data object and bot token
async function validate(data, botToken) {
const encoder = new TextEncoder()
const checkString = await Object.keys(data)
.filter((key) => key !== "hash")
.map((key) => `${key}=${data[key]}`)
.sort()
.join("\n")
// console.log('computed string:', checkString)
const secretKey = await crypto.subtle.importKey("raw", encoder.encode('WebAppData'), { name: "HMAC", hash: "SHA-256" }, true, ["sign"])
const secret = await crypto.subtle.sign("HMAC", secretKey, encoder.encode(botToken))
const signatureKey = await crypto.subtle.importKey("raw", secret, { name: "HMAC", hash: "SHA-256" }, true, ["sign"])
const signature = await crypto.subtle.sign("HMAC", signatureKey, encoder.encode(checkString))
const hex = [...new Uint8Array(signature)].map(b => b.toString(16).padStart(2, '0')).join('')
// console.log('original hash:', data.hash)
// console.log('computed hash:', hex)
return data.hash === hex
}
@bezenson
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment