owpengram-server/internal/domain/secretchat.go

188 lines
7.1 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 domain
import "errors"
// SecretChatState 是私聊端对端加密Secret Chat / EncryptedChat握手状态机的
// 服务端权威态。服务端是盲中继g_a/g_b/key_fingerprint/加密 bytes 全部不透明
// 存储与原样转发,永不接触 DH 共享密钥与明文。设计见 docs/secret-chat-module.md。
type SecretChatState string
const (
// SecretChatStateRequestedrequestEncryption 已受理、等接受方 acceptEncryption。
// 同一服务端态对发起方投影为 encryptedChatWaiting、对接受方投影为 encryptedChatRequested。
SecretChatStateRequested SecretChatState = "requested"
// SecretChatStateNormalacceptEncryption 完成 g_b/key_fingerprint 落库,握手成型。
SecretChatStateNormal SecretChatState = "normal"
// SecretChatStateDiscarded终态任一方 discardEncryption 触发。
SecretChatStateDiscarded SecretChatState = "discarded"
)
// Secret chat 存储层错误memory/postgres 双实现共用,行为契约由 storetest 钉死)。
var (
// ErrSecretChatNotFoundchat_id 不存在 → CHAT_ID_INVALID / ENCRYPTION_ID_INVALID。
ErrSecretChatNotFound = errors.New("secretchat: not found")
// ErrSecretChatAlreadyAcceptedaccept 一个已成型的密聊 → ENCRYPTION_ALREADY_ACCEPTED。
ErrSecretChatAlreadyAccepted = errors.New("secretchat: already accepted")
// ErrSecretChatAlreadyDeclinedaccept 一个已销毁的密聊 → ENCRYPTION_ALREADY_DECLINED。
ErrSecretChatAlreadyDeclined = errors.New("secretchat: already declined")
// ErrSecretChatIDConflictchat_id 主键撞键(计数器回退);调用方按 AtLeast 重分配重试。
ErrSecretChatIDConflict = errors.New("secretchat: chat id conflict")
)
// SecretChat 是一通私聊密聊的服务端权威态durable跨重启存活
// 字段命名对齐 TL encryptedChat*ID 是 int32 量级access_hash/admin_id/
// participant_id/key_fingerprint 是 int64。绑定维度是设备级perm auth_key 的 int64 值)。
type SecretChat struct {
// ID 是 chat_id全局单调 int32 序列;双方共享同一 id。
ID int
// AdminAccessHash / ParticipantAccessHash 双视角不同TL "check sum depending on user ID")。
AdminAccessHash int64
ParticipantAccessHash int64
// AdminUserID 是发起方ParticipantUserID 是接受方;据此判角色。
AdminUserID int64
ParticipantUserID int64
// AdminAuthKeyID / ParticipantAuthKeyID 是绑定设备的 perm auth_keyauthKeyIDToInt64 小端值)。
// ParticipantAuthKeyID 在 accept 前为 0建链前邀请对 participant 账号级可见)。
AdminAuthKeyID int64
ParticipantAuthKeyID int64
State SecretChatState
// GA 是 requestEncryption 携带的发起方公钥(盲存,左补零 256B
// GB 是 acceptEncryption 携带的接受方公钥accept 后落库)。
// 投影 GAOrB对 admin 视角是 GB对 participant 视角是 GATL 注释钉死)。
GA []byte
GB []byte
// KeyFingerprint 是接受方算出的共享密钥指纹,服务端原样 int64 中继、绝不重算。
KeyFingerprint int64
// Layer 是密聊内层 layer 快照不解析FolderID 透传 requested 归档意图。
Layer int
FolderID int
// HistoryDeleted 是 discard 时是否要求对端删整个会话历史。
HistoryDeleted bool
// RandomID 是 requestEncryption 的 int32 幂等键(同发起设备同 random_id 返同 chat
RandomID int32
// Date 是受理时刻unix 秒)。
Date int
}
// Terminal 报告密聊是否已销毁。
func (c SecretChat) Terminal() bool {
return c.State == SecretChatStateDiscarded
}
// HasParticipant 报告 userID 是否为本密聊的发起方或接受方。
func (c SecretChat) HasParticipant(userID int64) bool {
return userID != 0 && (userID == c.AdminUserID || userID == c.ParticipantUserID)
}
// IsAdmin 报告 userID 是否为发起方。
func (c SecretChat) IsAdmin(userID int64) bool {
return userID != 0 && userID == c.AdminUserID
}
// PeerOf 返回 userID 在本密聊中的对端userID 不是参与者时返回 0。
func (c SecretChat) PeerOf(userID int64) int64 {
switch userID {
case c.AdminUserID:
return c.ParticipantUserID
case c.ParticipantUserID:
return c.AdminUserID
default:
return 0
}
}
// PeerAuthKeyOf 返回 userID 的对端绑定设备 perm auth_keyint64非参与者或对端
// 未绑定返回 0。admin 的对端是 participant 设备,反之亦然。
func (c SecretChat) PeerAuthKeyOf(userID int64) int64 {
switch userID {
case c.AdminUserID:
return c.ParticipantAuthKeyID
case c.ParticipantUserID:
return c.AdminAuthKeyID
default:
return 0
}
}
// AccessHashFor 返回 userID 视角的 access_hash双方不同非参与者返回 0。
func (c SecretChat) AccessHashFor(userID int64) int64 {
switch userID {
case c.AdminUserID:
return c.AdminAccessHash
case c.ParticipantUserID:
return c.ParticipantAccessHash
default:
return 0
}
}
// EncryptedFileRef 是密聊文件的服务端快照P2盲中继内容是加密 bytes不解密
type EncryptedFileRef struct {
ID int64
AccessHash int64
Size int64
DCID int
KeyFingerprint int // int32 量级
}
// SecretChatMessage 是密聊 qts 投递队列里的一条不透明加密消息updateNewEncryptedMessage
// 的载荷。Bytes 是客户端加密的 DecryptedMessage服务端盲存盲转、永不解密。
// 按接收方设备ReceiverAuthKeyID的 qts 序列投递。
type SecretChatMessage struct {
ReceiverAuthKeyID int64
Qts int
ReceiverUserID int64
ChatID int
RandomID int64
Date int
IsService bool
Bytes []byte
File *EncryptedFileRef
}
// EncryptedStateEventType 区分无 qts 的密聊状态事件种类。
type EncryptedStateEventType int
const (
// EncryptedStateEventEncryptionupdateEncryption握手态变化投递时按 secret_chats
// 权威态重建(不固化快照)。
EncryptedStateEventEncryption EncryptedStateEventType = 1
// EncryptedStateEventReadupdateEncryptedMessagesRead已读回执携 MaxDate。
EncryptedStateEventRead EncryptedStateEventType = 2
)
// EncryptedStateEvent 是无 qts 的 durable 密聊状态事件(离线 getDifference 补偿)。
// TargetAuthKeyID=0 表示账号级(所有设备可见),非 0 表示绑定设备定向。
type EncryptedStateEvent struct {
ID int64
TargetUserID int64
TargetAuthKeyID int64
ChatID int
Type EncryptedStateEventType
MaxDate int
Date int
}
// SecretMessageDelivery 是 sendEncrypted* 要投递给对端设备的一条加密消息rpc 层组装,
// service 分配接收设备 qts 并落库)。
type SecretMessageDelivery struct {
RandomID int64
Bytes []byte
IsService bool
File *EncryptedFileRef
Date int
}
// SecretChatRequest 是 requestEncryption 受理入参(隐私/拉黑/self/bot 校验在 rpc 层先行)。
type SecretChatRequest struct {
AdminUserID int64
AdminAuthKeyID int64
ParticipantUserID int64
RandomID int32
GA []byte
Date int
}