fix: sync temp auth key expiry boundaries

This commit is contained in:
A 2026-07-13 23:04:15 +08:00
parent 305e8a0008
commit 20a310f6ca
50 changed files with 3626 additions and 335 deletions

View file

@ -1,15 +1,44 @@
package store
import "context"
import (
"context"
"errors"
"math"
)
var (
// ErrInvalidAuthKeyProtocolExpiry 表示新握手试图写入 migration-only
// unknown sentinel 或超出 TL int32 时间戳范围的协议寿命。
ErrInvalidAuthKeyProtocolExpiry = errors.New("invalid auth key protocol expiry")
// ErrAuthKeyProtocolMetadataConflict 表示同一 cryptographic auth_key_id
// 被尝试改写为另一 key body 或另一 permanent/temp 类型/寿命。
ErrAuthKeyProtocolMetadataConflict = errors.New("auth key protocol metadata conflict")
// ErrAuthKeyNotPermanent 防止 authorization 落到 temporary/legacy-unknown key。
ErrAuthKeyNotPermanent = errors.New("auth key is not permanent")
// ErrAuthKeyBindingInvalid 表示 temp/perm 引用缺失、类型错误,或 binding
// expiry 未归一到握手权威值。
ErrAuthKeyBindingInvalid = errors.New("invalid temporary auth key binding")
)
// ValidNewAuthKeyProtocolExpiry 只允许握手写 permanent(0) 或 TL int32
// 范围内的 positive temporary expiry。-1 仅能由 migration 0086 写入。
func ValidNewAuthKeyProtocolExpiry(expiresAt int) bool {
return expiresAt >= 0 && int64(expiresAt) <= math.MaxInt32
}
// AuthKeyData 是一条持久化的 MTProto auth key 记录。
//
// 不依赖 td 协议类型:连接层在边界做 crypto.AuthKey ↔ AuthKeyData 转换。
type AuthKeyData struct {
ID [8]byte // auth_key_id(key 的 SHA1 低 64 位)
Value [256]byte // 2048-bit auth key
ServerSalt int64 // 密钥交换产出的初始 server salt
CreatedAt int64 // unix 秒
ID [8]byte // auth_key_id(key 的 SHA1 低 64 位)
Value [256]byte // 2048-bit auth key
ServerSalt int64 // 密钥交换产出的初始 server salt
CreatedAt int64 // unix 秒
// ExpiresAt 是 temporary/media-temporary auth key 的协议失效时间(unix 秒)。
// 0 只允许表示 permanent key;-1 仅表示 migration 0086 无法证明类型的历史 key,
// edge 必须用 -404 拒绝并迫使客户端重握手。key 类型是握手事实,不能由
// authorization 是否存在推断。
ExpiresAt int
Layer int
DeviceModel string
Platform string
@ -30,7 +59,7 @@ type AuthKeyClientInfo struct {
// AuthKeyStore 持久化 auth key。实现见 store/memory(测试替身)、store/postgres。
type AuthKeyStore interface {
// Save 保存或覆盖一条 auth key 记录。
// Save 保存一条 auth key 记录;同 ID 重试只能保持 key body 与协议类型/寿命不变。
Save(ctx context.Context, k AuthKeyData) error
// Get 按 auth_key_id 查询;不存在时 found=false。
Get(ctx context.Context, id [8]byte) (data AuthKeyData, found bool, err error)