
本文详解 telegram 官方 webapp 数据签名验证(hmac-sha256 两层嵌套哈希)的 java 实现要点,重点纠正常见误区——误将 hex 字符串直接用作第二层 hmac 密钥,而应使用原始字节数组。
本文详解 telegram 官方 webapp 数据签名验证(hmac-sha256 两层嵌套哈希)的 java 实现要点,重点纠正常见误区——误将 hex 字符串直接用作第二层 hmac 密钥,而应使用原始字节数组。
Telegram WebApp 在向后端传递用户数据(如 user, auth_date, hash 等)时,要求服务端严格校验 hash 字段的有效性,以防止篡改。其验证逻辑为两步 HMAC-SHA256:
-
第一层:以固定字符串
"WebAppData"为密钥,对初始密钥k(即 Telegram 提供的bot_token或临时init_data中的hash前置密钥)进行哈希,得到二进制密钥secretKey; -
第二层:以第一步生成的 原始字节密钥(非 hex 字符串)为密钥,对排序后的
init_data键值对(不含hash=)进行哈希,结果与客户端传入的hash字段比对。
关键陷阱在于:许多开发者误用 HmacUtils(String, String) 构造器将第一层输出的 hex 字符串(如 "3db03151...")直接作为第二层密钥——这会导致 Java 将该字符串按 UTF-8 编码为字节,而非还原为原始哈希字节,从而产生错误结果。
✅ 正确做法是:始终使用 byte[] 类型密钥传递中间结果。以下为完整、可运行的 Java 示例(基于 Apache Commons Codec 1.15+):
import org.apache.commons.codec.digest.HmacUtils;
import java.nio.charset.StandardCharsets;
public class TelegramHashValidator {
public static void main(String[] args) {
// Step 1: 第一层 HMAC —— key = "WebAppData", data = "k"
byte[] secretKey = new HmacUtils("HmacSHA256", "WebAppData".getBytes(StandardCharsets.UTF_8))
.hmac("k".getBytes(StandardCharsets.UTF_8));
// Step 2: 第二层 HMAC —— key = secretKey (raw bytes), data = "data"
String hash = new HmacUtils("HmacSHA256", secretKey)
.hmacHex("data".getBytes(StandardCharsets.UTF_8));
// 输出验证(与 JS 结果一致)
System.out.println("secretKey (hex): " +
java.util.HexFormat.of().formatHex(secretKey));
System.out.println("final hash: " + hash);
// → 3db03151d3fb2678c9fc0f24ee15817bfd1ff922a712a055f63066f875e43fc1
// → 9158b0aeb1e882c075ea46a0d5302cffba1a9b66b0df40f5f01eef614f7d9f94
}
}⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- 使用
HmacUtils(String, byte[])构造器,确保密钥为原始哈希字节,而非 hex 字符串; - 所有输入数据(如
"k"、"data")需显式指定StandardCharsets.UTF_8编码,避免平台默认编码差异; - 实际生产中,
"data"应替换为按字母序拼接的init_data参数(如auth_date=123&user=%7B%22id%22%3A123%7D),且不包含hash=字段; - 不建议依赖第三方 Telegram SDK(如
TelegramBots)自动处理此逻辑——其 Bot API SDK 主要面向消息收发,WebApp 数据校验需自行实现,官方未提供开箱即用的验证工具类。
总结:Telegram WebApp 哈希校验本质是「密钥派生 + 数据签名」,核心在于密钥传递的二进制保真。只要坚持 byte[] → byte[] → hex 的链路,即可与前端 JavaScript(CryptoJS)完全对齐,保障数据完整性与安全性。


















