From ffc28cfbacda3694833103a11da29ca0c315a579 Mon Sep 17 00:00:00 2001 From: crashiura Date: Sun, 3 Jul 2022 02:37:12 +0300 Subject: [PATCH 1/2] validate web app hash --- helpers.go | 42 ++++++++++++++++++++++++++++++++++++++++++ helpers_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/helpers.go b/helpers.go index 8220e74e..ef8705be 100644 --- a/helpers.go +++ b/helpers.go @@ -1,7 +1,14 @@ package tgbotapi import ( + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" "net/url" + "sort" + "strings" ) // NewMessage creates a new Message. @@ -925,3 +932,38 @@ func NewDeleteMyCommandsWithScope(scope BotCommandScope) DeleteMyCommandsConfig func NewDeleteMyCommandsWithScopeAndLanguage(scope BotCommandScope, languageCode string) DeleteMyCommandsConfig { return DeleteMyCommandsConfig{Scope: &scope, LanguageCode: languageCode} } + +// ValidateWebAppData validate data received via the Web App +// https://core.telegram.org/bots/webapps#validating-data-received-via-the-web-app +func ValidateWebAppData(token, telegramInitData string) (bool, error) { + initData, err := url.ParseQuery(telegramInitData) + if err != nil { + return false, fmt.Errorf("error parsing data %w", err) + } + + dataCheckString := make([]string, 0, len(initData)) + for k, v := range initData { + if k == "hash" { + continue + } + if len(v) > 0 { + dataCheckString = append(dataCheckString, fmt.Sprintf("%s=%s", k, v[0])) + } + } + + sort.Strings(dataCheckString) + + secret := hmac.New(sha256.New, []byte("WebAppData")) + secret.Write([]byte(token)) + + hHash := hmac.New(sha256.New, secret.Sum(nil)) + hHash.Write([]byte(strings.Join(dataCheckString, "\n"))) + + hash := hex.EncodeToString(hHash.Sum(nil)) + + if initData.Get("hash") != hash { + return false, errors.New("hash not equal") + } + + return true, nil +} diff --git a/helpers_test.go b/helpers_test.go index 724f6ac2..f2dd65e3 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -234,3 +234,41 @@ func TestNewDiceWithEmoji(t *testing.T) { t.Fail() } } + +func TestValidateWebAppData(t *testing.T) { + t.Run("success", func(t *testing.T) { + token := "5473903189:AAFnHnISQMP5UQQ5MEaoEWvxeiwNgz2CN2U" + initData := "query_id=AAG1bpMJAAAAALVukwmZ_H2t&user=%7B%22id%22%3A160657077%2C%22first_name%22%3A%22Yury%20R%22%2C%22last_name%22%3A%22%22%2C%22username%22%3A%22crashiura%22%2C%22language_code%22%3A%22en%22%7D&auth_date=1656804462&hash=8d6960760a573d3212deb05e20d1a34959c83d24c1bc44bb26dde49a42aa9b34" + result, err := ValidateWebAppData(token, initData) + if err != nil { + t.Fail() + } + if !result { + t.Fail() + } + }) + + t.Run("error bad init data", func(t *testing.T) { + token := "5473903189:AAFnHnISQMP5UQQ5MEaoEWvxeiwNgz2CN2U" + initData := "asdfasdfasdfasdfasdf" + result, err := ValidateWebAppData(token, initData) + if err == nil { + t.Fail() + } + if result { + t.Fail() + } + }) + + t.Run("error", func(t *testing.T) { + token := "5473903189:AAFnHnISQMP5UQQ5MEaoEWvxeiwNgz2CN2U" + initData := "asdfasdfasdfasdfasdf" + result, err := ValidateWebAppData(token, initData) + if err == nil { + t.Fail() + } + if result { + t.Fail() + } + }) +} From 189292093b230e278577ae4d528d57bc6c4e2835 Mon Sep 17 00:00:00 2001 From: crashiura Date: Sun, 3 Jul 2022 02:43:22 +0300 Subject: [PATCH 2/2] validate web app hash --- helpers_test.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/helpers_test.go b/helpers_test.go index f2dd65e3..9119543d 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -248,18 +248,6 @@ func TestValidateWebAppData(t *testing.T) { } }) - t.Run("error bad init data", func(t *testing.T) { - token := "5473903189:AAFnHnISQMP5UQQ5MEaoEWvxeiwNgz2CN2U" - initData := "asdfasdfasdfasdfasdf" - result, err := ValidateWebAppData(token, initData) - if err == nil { - t.Fail() - } - if result { - t.Fail() - } - }) - t.Run("error", func(t *testing.T) { token := "5473903189:AAFnHnISQMP5UQQ5MEaoEWvxeiwNgz2CN2U" initData := "asdfasdfasdfasdfasdf"