owpengram-server/internal/app/phone/dh.go
2026-09-09 02:49:30 +03:00

67 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package phone 实现私聊 1:1 通话的信令状态机与 DH 参数下发。
//
// 服务端职责边界信令转发、状态机、commit-reveal 核验SHA256(g_a)==g_a_hash
// connections 下发。媒体面由客户端 tgcalls 走 P2P/TURN密钥交换是 E2E 的,
// 服务端不知道也无法验证共享密钥本身。
package phone
import (
"crypto/rand"
"encoding/hex"
"fmt"
)
// DHConfigVersion 是 messages.getDhConfig 的服务端配置版本。p/g 是编译期常量,
// 客户端缓存命中(请求 version 相同)时只回 dhConfigNotModified{random}。
//
// ⚠ 提高此值会让所有客户端在下一次 messages.getDhConfig每次拨打/接听通话都会调用)
// 强制重新拉取 p/g而不是信任本地缓存。用于失效任何账号本地可能缓存的陈旧/错误
// p/g例如账号早年间对接过其它后端、缓存版本号恰好等于当时的 DHConfigVersion
// 此后再也不会刷新——版本号是纯常量,服务端自己永远不会主动使旧缓存过期)。
// 早先从 1→2 是为诊断一例「A 拨 B 接通即断key fingerprint/Ga hash 不合)」而提升。
// 上游又发现了同类问题的另一诱因:私有 DC 客户端若带着同为某个旧 version、但来自
// 另一配置 profile 的缓存,服务端错误返回 NotModified 会让密聊两端用不同 p/g
// 这里直接取上游更新、更高的版本号,一次性使两类陈旧缓存都失效。
const DHConfigVersion = 20260811
// DHG 是 DH generator。与官方一致取 3TDesktop MTP::IsPrimeAndGood 对
// 「官方 2048-bit prime + g∈{3,4,5,7}」有白名单快速通过路径DrKLO native 同。
const DHG = 3
// dhPrimeHex 是官方 2048-bit safe prime。与 internal/app/account/srp.go 的
// baseP 同值SRP 与通话 DH 共用官方参数);改动任一处须同步另一处。
const dhPrimeHex = "c71caeb9c6b1c9048e6c522f70f13f73980d40238e3e21c14934d037563d930f48198a0aa7c14058229493d22530f4dbfa336f6e0ac925139543aed44cce7c3720fd51f69458705ac68cd4fe6b6b13abdc9746512969328454f18faf8c595f642477fe96bb2a941d5bcd1d4ac8cc49880708fa9b378e3c4f3a9060bee67cf9a4a4a695811051907e162753b56b0f6b410dba74d8a84b2a14b3144e0ef1284754fd17ed950d5965b4b9dd46582db1178d169c6bc465b0d6ff9ca3928fef5b9ae4e418fc15e83ebea0f87fa9ff5eed70050ded2849f47bf959d956850ce929851f0d8115f635b105ee2e4e15d04b2454bf6f4fadf034b10403119cd8e3b92fcc5b"
var dhPrime = mustDecodeHex(dhPrimeHex)
// maxDHRandomLength 钳制客户端请求的随机字节数,防御恶意大请求。
const maxDHRandomLength = 1024
// DHPrime 返回官方 2048-bit prime 的拷贝。
func DHPrime() []byte {
return append([]byte(nil), dhPrime...)
}
// DHRandom 生成恰好 n 字节加密随机数n 钳制到 [0, maxDHRandomLength]。
// 客户端契约要求 random 尺寸与请求一致TDesktop 校验 random.size() 与其请求相同)。
func DHRandom(n int) ([]byte, error) {
if n < 0 {
n = 0
}
if n > maxDHRandomLength {
n = maxDHRandomLength
}
buf := make([]byte, n)
if _, err := rand.Read(buf); err != nil {
return nil, fmt.Errorf("phone: dh random: %w", err)
}
return buf, nil
}
func mustDecodeHex(s string) []byte {
b, err := hex.DecodeString(s)
if err != nil {
panic(fmt.Sprintf("phone: invalid dh prime hex: %v", err))
}
return b
}