owpengram-server/internal/app/secretchat/dh.go

55 lines
2.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 secretchat 实现私聊端对端加密Secret Chat / EncryptedChat的握手
// 状态机。服务端是盲中继g_a/g_b/key_fingerprint/加密 bytes 全部不透明存储与
// 原样转发,唯一参与密码学的点是对 g_a/g_b 做 DH 范围边界校验(防弱 DH/MITM
// 共享密钥与明文是 E2E 客户端职责,服务端不知道也无法计算。
// 设计见 docs/secret-chat-module.md。
package secretchat
import (
"errors"
"math/big"
appphone "telesrv/internal/app/phone"
)
// dhPubSize 是 g_a/g_b 的规范字节长度2048-bit
const dhPubSize = 256
// ErrGAInvalidg_a/g_b 不在合法 DH 区间 → rpc 层映射为 DH_G_A_INVALID。
var ErrGAInvalid = errors.New("secretchat: dh parameter invalid")
var (
// dhPrimeMinusOne/边界值复用 phone 域官方 2048-bit safe prime与 getDhConfig 下发的 p 同源)。
dhPrimeMinusOne = new(big.Int).Sub(new(big.Int).SetBytes(appphone.DHPrime()), big.NewInt(1))
// 2^(2048-64) 下界与 p-2^(2048-64) 上界(官方 isGoodPrime 同款边界)。
dhLowerBound = new(big.Int).Lsh(big.NewInt(1), 2048-64)
dhUpperBound = new(big.Int).Sub(new(big.Int).SetBytes(appphone.DHPrime()), new(big.Int).Lsh(big.NewInt(1), 2048-64))
dhOne = big.NewInt(1)
)
// validateDHParam 对 g_a/g_b 做范围校验,通过后左补零到 256 字节返回(规范线格式;
// 首字节为 0 被裁的合法 g_a 不能误拒)。校验用的是 big.Int 值,与补零无关。
func validateDHParam(g []byte) ([]byte, error) {
if len(g) == 0 || len(g) > dhPubSize {
return nil, ErrGAInvalid
}
x := new(big.Int).SetBytes(g)
// 1 < x < p-1 且 2^(2048-64) < x < p-2^(2048-64)
if x.Cmp(dhOne) <= 0 || x.Cmp(dhPrimeMinusOne) >= 0 {
return nil, ErrGAInvalid
}
if x.Cmp(dhLowerBound) <= 0 || x.Cmp(dhUpperBound) >= 0 {
return nil, ErrGAInvalid
}
return leftPad256(g), nil
}
// leftPad256 左补零到 256 字节(输入已保证 ≤256
func leftPad256(b []byte) []byte {
if len(b) == dhPubSize {
return append([]byte(nil), b...)
}
out := make([]byte, dhPubSize)
copy(out[dhPubSize-len(b):], b)
return out
}