prevent mitm by signing server messages

This commit is contained in:
2026-07-24 14:01:13 +02:00
parent 3f11053834
commit fa9348592e
6 changed files with 114 additions and 39 deletions

View File

@@ -4,44 +4,53 @@ import "encoding/binary"
const PROTO_VERSION uint16 = 1
// pubKey - public key generated by the client
// privKey - private key generated by the client
// sessionKey - key established between two peers
// multicastKey - key shared between everyone for encrypting multicast pkts
// authSecret - secret given during registration for authenticating subsequent requests
// pubKey - public key generated by the client
// privKey - private key generated by the client
// serverPubKey - pre-shared public key used for authenticating the server
// serverPrivKey - long-term private key used for authenticating the server
// sessionKey - per-peer symmetrical key derived via HPKE for encrypting unicast packets
// multicastKey - key shared between everyone for encrypting multicast packets
// authSecret - secret assigned to a client for authenticating subsequent requests
// SYM = XChaCha20Poly1305 with nonce prepended
// HMAC = HMAC-SHA-256
// hpke = HPKE(MLKEM768X25519, ChaCha20Poly1305, HKDF-SHA-256)
// ds = ML-DSA
// packet format
// [ version - 2 bytes ] [ type - 2 bytes ] [ payload - see below ]
const (
_ uint16 = iota
// (client -> server) requests a challenge to prove the ownership of the privKey
// [ pubKey - 1216 bytes ]
REQ_GET_CHALLENGE
// (server -> client) provides a pubKey-encrypted authSecret
// [ ciphertext - 1168 bytes ]
// (server -> client) provides an encrypted authSecret
// [ ds.Sign(serverPrivKey, rest) - 2420 bytes ] [ HPKE(pubKey, authSecret) - 1168 bytes ]
RESP_GET_CHALLENGE
// (client -> server) requests an IP
// [ HMAC(authSecret, pubKey) - 32 bytes ] [ pubKey - 1216 bytes ]
REQ_REGISTER
// (server -> client) returns the assigned IP and pubKey-encrypted multicastKey
// [ ip - 16 bytes ] [ ciphertext - 1168 bytes ]
// (server -> client) returns the assigned IP and encrypted multicastKey
// [ ds.Sign(serverPrivKey, rest) - 2420 bytes ] [ ip - 16 bytes ] [ hpke.Seal(pubKey, multicastKey) - 1168 bytes ]
RESP_REGISTER
// (client -> server -> client2) relays an encrypted packet to a specified peer
// [ HMAC(authSecret, rest) - 32 bytes ] [ destIP - 16 bytes ] [ srcIP - 16 bytes ] [ encryptedPkt ]
ENC_PKT
// (client -> server -> *) broadcasts an encrypted packet
// [ HMAC(authSecret, rest) - 32 bytes ] [ encryptedPkt ]
BROADCAST_PKT
// (client -> server) requests peer's pubKey from the server for encapsulation
// [ ip - 16 bytes ]
REQ_GET_PUBKEY
// (server -> client) provides requested pubKey
// [ ip - 16 bytes ] [ pubKey - 1216 bytes ]
// [ ds.Sign(serverPrivKey, rest) - 2420 bytes ] [ ip - 16 bytes ] [ pubKey - 1216 bytes ]
RESP_GET_PUBKEY
// (client -> server -> client2) establishes a sessionKey with another peer
// [ HMAC(authSecret, rest) - 32 bytes ] [ destIP - 16 bytes ] [ srcIP - 16 bytes ] [ ciphertext - 1120 bytes ]
// [ HMAC(authSecret, rest) - 32 bytes ] [ destIP - 16 bytes ] [ srcIP - 16 bytes ] [ hpke.Encap(pubKey) - 1120 bytes ]
REQ_ESTABLISH
// (client2 -> server -> client) acknowledges the sessionKey was established
// [ HMAC(authSecret, rest) - 32 bytes ] [ destIP - 16 bytes ] [ srcIP - 16 bytes ]
RESP_ESTABLISH
// (client -> server -> client2) relays an encrypted packet to a specified peer
// [ HMAC(authSecret, rest) - 32 bytes ] [ destIP - 16 bytes ] [ srcIP - 16 bytes ] [ SYM(sessionKey, pkt) ]
UNICAST_PKT
// (client -> server -> *) broadcasts an encrypted packet
// [ HMAC(authSecret, rest) - 32 bytes ] [ SYM(multicastKey, pkt) ]
BROADCAST_PKT
)
func BuildPkt(pktType uint16, parts ...[]byte) []byte {