From c70484076d04080afed4028b1058c4d7550d677c Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 29 Apr 2022 18:56:38 +0600 Subject: [PATCH 1/4] start 0.38.16 --- CHANGELOG.md | 2 ++ gradle.properties | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b03c87e77b..a057605c48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # TelegramBotAPI changelog +## 0.38.16 + ## 0.38.15 * `Common`: diff --git a/gradle.properties b/gradle.properties index b7a490f218..b09681206c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,6 +20,6 @@ javax_activation_version=1.1.1 dokka_version=1.6.10 library_group=dev.inmo -library_version=0.38.15 +library_version=0.38.16 github_release_plugin_version=2.3.7 From 4799617cedff0ddbfc0bfaf12b91fe592e815245 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 29 Apr 2022 19:11:38 +0600 Subject: [PATCH 2/4] "TelegramAPIUrlsKeeper" now have two new things: properties "webAppDataSecretKey" and fun "checkWebAppLink" --- CHANGELOG.md | 3 ++ .../kotlin/dev/inmo/tgbotapi/utils/Crypto.kt | 7 +++++ .../tgbotapi/utils/TelegramAPIUrlsKeeper.kt | 10 +++++++ .../dev/inmo/tgbotapi/utils/CryptoActual.kt | 8 +++++ .../dev/inmo/tgbotapi/utils/CryptoActual.kt | 29 +++++++++++++++++++ tgbotapi.webapps/build.gradle | 7 +++++ .../inmo/tgbotapi/webapps/CheckWebAppData.kt | 9 ++++++ .../dev/inmo/tgbotapi/webapps/WebApp.kt | 8 +++-- 8 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Crypto.kt create mode 100644 tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt create mode 100644 tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt create mode 100644 tgbotapi.webapps/src/commonMain/kotlin/dev/inmo/tgbotapi/webapps/CheckWebAppData.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index a057605c48..73e15253e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 0.38.16 +* `Core`: + * `TelegramAPIUrlsKeeper` now have two new things: properties `webAppDataSecretKey` and fun `checkWebAppLink` + ## 0.38.15 * `Common`: diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Crypto.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Crypto.kt new file mode 100644 index 0000000000..163dffea01 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Crypto.kt @@ -0,0 +1,7 @@ +package dev.inmo.tgbotapi.utils + +import dev.inmo.micro_utils.crypto.SourceString + +internal expect fun SourceString.hmacSha256(key: String): String + +internal expect fun SourceString.hex(): String diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper.kt index 422634479e..649a8ccc2b 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper.kt @@ -18,6 +18,10 @@ class TelegramAPIUrlsKeeper( token: String, hostUrl: String = telegramBotAPIDefaultUrl ) { + val webAppDataSecretKey by lazy { + token.hmacSha256("WebAppData") + } + val commonAPIUrl: String val fileBaseUrl: String @@ -28,4 +32,10 @@ class TelegramAPIUrlsKeeper( } fun createFileLinkUrl(filePath: String) = "${fileBaseUrl}/$filePath" + + /** + * @param rawData Data from [dev.inmo.tgbotapi.webapps.WebApp.initData] + * @param hash Data from [dev.inmo.tgbotapi.webapps.WebApp.initDataUnsafe] from the field [dev.inmo.tgbotapi.webapps.WebAppInitData.hash] + */ + fun checkWebAppLink(rawData: String, hash: String) = rawData.hmacSha256(webAppDataSecretKey).hex() == hash } diff --git a/tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt b/tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt new file mode 100644 index 0000000000..821bdea167 --- /dev/null +++ b/tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt @@ -0,0 +1,8 @@ +package dev.inmo.tgbotapi.utils + +import dev.inmo.micro_utils.crypto.CryptoJS +import dev.inmo.micro_utils.crypto.SourceString + +actual fun SourceString.hmacSha256(key: String) = CryptoJS.asDynamic().HmacSHA256(this, key).unsafeCast() + +actual fun SourceString.hex() = CryptoJS.asDynamic().format.Hex(this).unsafeCast() diff --git a/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt b/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt new file mode 100644 index 0000000000..7a63c5f7e6 --- /dev/null +++ b/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt @@ -0,0 +1,29 @@ +package dev.inmo.tgbotapi.utils + +import dev.inmo.micro_utils.crypto.SourceBytes +import dev.inmo.micro_utils.crypto.SourceString +import javax.crypto.Mac +import javax.crypto.spec.SecretKeySpec + +val HEX_ARRAY = "0123456789ABCDEF".toCharArray() + +private fun SourceBytes.hex(): String { + val hexChars = CharArray(size * 2) + for (j in indices) { + val v: Int = this[j].toInt() and 0xFF + hexChars[j * 2] = HEX_ARRAY[v ushr 4] + hexChars[j * 2 + 1] = HEX_ARRAY[v and 0x0F] + } + return String(hexChars) +} + +actual fun SourceString.hmacSha256(key: String): String { + val mac = Mac.getInstance("HmacSHA256") + + val secretKey = SecretKeySpec(key.toByteArray(), "HmacSHA256") + mac.init(secretKey) + + return mac.doFinal(toByteArray()).hex() +} + +actual fun SourceString.hex(): String = toByteArray().hex() diff --git a/tgbotapi.webapps/build.gradle b/tgbotapi.webapps/build.gradle index 257fcf8f02..951c331574 100644 --- a/tgbotapi.webapps/build.gradle +++ b/tgbotapi.webapps/build.gradle @@ -27,6 +27,13 @@ repositories { } kotlin { + jvm { + compilations.main { + kotlinOptions { + jvmTarget = "1.8" + } + } + } js(IR) { browser() nodejs() diff --git a/tgbotapi.webapps/src/commonMain/kotlin/dev/inmo/tgbotapi/webapps/CheckWebAppData.kt b/tgbotapi.webapps/src/commonMain/kotlin/dev/inmo/tgbotapi/webapps/CheckWebAppData.kt new file mode 100644 index 0000000000..19f09d7a0f --- /dev/null +++ b/tgbotapi.webapps/src/commonMain/kotlin/dev/inmo/tgbotapi/webapps/CheckWebAppData.kt @@ -0,0 +1,9 @@ +package dev.inmo.tgbotapi.webapps + +import dev.inmo.tgbotapi.utils.* + +/** + * @param rawData Data from [dev.inmo.tgbotapi.webapps.WebApp.initData] + * @param hash Data from [dev.inmo.tgbotapi.webapps.WebApp.initDataUnsafe] from the field [dev.inmo.tgbotapi.webapps.WebAppInitData.hash] + */ +fun TelegramAPIUrlsKeeper.checkWebAppLink(rawData: String, hash: String) = rawData.hmacSha256(webAppDataSecretKey).hex() == hash diff --git a/tgbotapi.webapps/src/jsMain/kotlin/dev/inmo/tgbotapi/webapps/WebApp.kt b/tgbotapi.webapps/src/jsMain/kotlin/dev/inmo/tgbotapi/webapps/WebApp.kt index 5422c340c2..dd1d788940 100644 --- a/tgbotapi.webapps/src/jsMain/kotlin/dev/inmo/tgbotapi/webapps/WebApp.kt +++ b/tgbotapi.webapps/src/jsMain/kotlin/dev/inmo/tgbotapi/webapps/WebApp.kt @@ -1,6 +1,7 @@ package dev.inmo.tgbotapi.webapps import dev.inmo.micro_utils.crypto.CryptoJS +import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper external class WebApp { val initData: String @@ -76,6 +77,7 @@ fun WebApp.onMainButtonClicked(eventHandler: EventHandler) = onEvent(EventType.M */ fun WebApp.onViewportChanged(eventHandler: ViewportChangedEventHandler) = onEvent(EventType.ViewportChanged, eventHandler) -fun WebApp.isInitDataSafe(botToken: String) = CryptoJS.hex( - CryptoJS.HmacSHA256(botToken, "WebAppData") -) == initDataUnsafe.hash +fun WebApp.isInitDataSafe(botToken: String) = TelegramAPIUrlsKeeper(botToken).checkWebAppLink( + initData, + initDataUnsafe.hash +) From 78a7a3546a4c291528778c89485fa23f4ad477d0 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 29 Apr 2022 19:18:22 +0600 Subject: [PATCH 3/4] remove checking of webapp data from webapp module due to its existing in core --- .../kotlin/dev/inmo/tgbotapi/webapps/CheckWebAppData.kt | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 tgbotapi.webapps/src/commonMain/kotlin/dev/inmo/tgbotapi/webapps/CheckWebAppData.kt diff --git a/tgbotapi.webapps/src/commonMain/kotlin/dev/inmo/tgbotapi/webapps/CheckWebAppData.kt b/tgbotapi.webapps/src/commonMain/kotlin/dev/inmo/tgbotapi/webapps/CheckWebAppData.kt deleted file mode 100644 index 19f09d7a0f..0000000000 --- a/tgbotapi.webapps/src/commonMain/kotlin/dev/inmo/tgbotapi/webapps/CheckWebAppData.kt +++ /dev/null @@ -1,9 +0,0 @@ -package dev.inmo.tgbotapi.webapps - -import dev.inmo.tgbotapi.utils.* - -/** - * @param rawData Data from [dev.inmo.tgbotapi.webapps.WebApp.initData] - * @param hash Data from [dev.inmo.tgbotapi.webapps.WebApp.initDataUnsafe] from the field [dev.inmo.tgbotapi.webapps.WebAppInitData.hash] - */ -fun TelegramAPIUrlsKeeper.checkWebAppLink(rawData: String, hash: String) = rawData.hmacSha256(webAppDataSecretKey).hex() == hash From 60c21002e18d2dbe91547fd3e27bb1011de312d8 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 29 Apr 2022 19:50:02 +0600 Subject: [PATCH 4/4] fixes --- .../kotlin/dev/inmo/tgbotapi/utils/Crypto.kt | 14 +++++++++++++- .../dev/inmo/tgbotapi/utils/CryptoActual.kt | 4 +--- .../dev/inmo/tgbotapi/utils/CryptoActual.kt | 15 --------------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Crypto.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Crypto.kt index 163dffea01..af150b34fa 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Crypto.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Crypto.kt @@ -1,7 +1,19 @@ package dev.inmo.tgbotapi.utils +import dev.inmo.micro_utils.crypto.SourceBytes import dev.inmo.micro_utils.crypto.SourceString internal expect fun SourceString.hmacSha256(key: String): String +private val HEX_ARRAY = "0123456789abcdef".toCharArray() -internal expect fun SourceString.hex(): String +internal fun SourceBytes.hex(): String { + val hexChars = CharArray(size * 2) + for (j in indices) { + val v: Int = this[j].toInt() and 0xFF + hexChars[j * 2] = HEX_ARRAY[v ushr 4] + hexChars[j * 2 + 1] = HEX_ARRAY[v and 0x0F] + } + return hexChars.concatToString() +} + +internal fun SourceString.hex(): String = encodeToByteArray().hex() diff --git a/tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt b/tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt index 821bdea167..a8b23eae8a 100644 --- a/tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt +++ b/tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt @@ -3,6 +3,4 @@ package dev.inmo.tgbotapi.utils import dev.inmo.micro_utils.crypto.CryptoJS import dev.inmo.micro_utils.crypto.SourceString -actual fun SourceString.hmacSha256(key: String) = CryptoJS.asDynamic().HmacSHA256(this, key).unsafeCast() - -actual fun SourceString.hex() = CryptoJS.asDynamic().format.Hex(this).unsafeCast() +actual fun SourceString.hmacSha256(key: String) = CryptoJS.asDynamic().HmacSHA256(this, key).toString().unsafeCast() diff --git a/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt b/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt index 7a63c5f7e6..65075f0119 100644 --- a/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt +++ b/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/utils/CryptoActual.kt @@ -1,22 +1,9 @@ package dev.inmo.tgbotapi.utils -import dev.inmo.micro_utils.crypto.SourceBytes import dev.inmo.micro_utils.crypto.SourceString import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec -val HEX_ARRAY = "0123456789ABCDEF".toCharArray() - -private fun SourceBytes.hex(): String { - val hexChars = CharArray(size * 2) - for (j in indices) { - val v: Int = this[j].toInt() and 0xFF - hexChars[j * 2] = HEX_ARRAY[v ushr 4] - hexChars[j * 2 + 1] = HEX_ARRAY[v and 0x0F] - } - return String(hexChars) -} - actual fun SourceString.hmacSha256(key: String): String { val mac = Mac.getInstance("HmacSHA256") @@ -25,5 +12,3 @@ actual fun SourceString.hmacSha256(key: String): String { return mac.doFinal(toByteArray()).hex() } - -actual fun SourceString.hex(): String = toByteArray().hex()