Files
vppn/peer/multicast/packet.go

55 lines
1.5 KiB
Go

package multicast
import (
"encoding/binary"
"net/netip"
"golang.org/x/crypto/nacl/sign"
)
const (
BufferSize = packetSize + SignedPacketSize
SignedPacketSize = packetSize + signSize
packetSize = 43
signSize = 64
)
// Layout:
//
// [0] final octet of the sender's VPN IP
// [1:33] WG public key
// [33:35] WG listen port (big-endian uint16)
// [35:43] send time, Unix seconds (big-endian int64) — freshness/replay gate
type Packet struct {
PeerIP byte // Final octet of the sender's VPN IP.
WGPubKey [32]byte // WG public key.
WGPort uint16 // WG listen port.
Timestamp int64 // Unix timestamp.
Src netip.Addr // Source of packet.
Signed []byte // Raw signed message for verification (incoming packet).
}
// Marshal the packet into a buffer with prefixed signature.
func (p Packet) Marshal(buf []byte, signKey *[64]byte) []byte {
buf[0] = p.PeerIP
copy(buf[1:33], p.WGPubKey[:])
binary.BigEndian.PutUint16(buf[33:35], p.WGPort)
binary.BigEndian.PutUint64(buf[35:43], uint64(p.Timestamp))
return sign.Sign(buf[packetSize:packetSize], buf[:packetSize], signKey)
}
func (p Packet) Verify(buf []byte, pubKey *[32]byte) bool {
_, ok := sign.Open(buf, p.Signed, pubKey)
return ok
}
func Unmarshal(signed []byte) (p Packet) {
buf := signed[signSize:]
p.PeerIP = buf[0]
copy(p.WGPubKey[:], buf[1:33])
p.WGPort = binary.BigEndian.Uint16(buf[33:35])
p.Timestamp = int64(binary.BigEndian.Uint64(buf[35:43]))
p.Signed = signed
return
}