From a52250bcf8d9043dc55cf92bc7c53fd77aa2cd39 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Wed, 3 Apr 2024 19:31:58 -0600 Subject: [PATCH] Added session connect packet --- client.go | 8 ++--- packet.go | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ packet_test.go | 17 +++++++++++ server.go | 15 ---------- 4 files changed, 99 insertions(+), 21 deletions(-) diff --git a/client.go b/client.go index 1a53223..aa3e65b 100644 --- a/client.go +++ b/client.go @@ -10,13 +10,9 @@ type Client struct { Key ed25519.PrivateKey } -func KeyID(key ed25519.PublicKey) ClientID { - hash := sha512.Sum512([]byte(key)) - return (ClientID)((hash)[0:16]) -} - func(client Client) ID() ClientID { - return KeyID(client.Key.Public().(ed25519.PublicKey)) + hash := sha512.Sum512([]byte(client.Key.Public().(ed25519.PublicKey))) + return (ClientID)(hash[0:16]) } func NewClient(key ed25519.PrivateKey) (Client, error) { diff --git a/packet.go b/packet.go index 5081dc6..ce1141a 100644 --- a/packet.go +++ b/packet.go @@ -4,11 +4,91 @@ import ( "crypto/ed25519" "crypto/rand" "crypto/sha512" + "encoding/binary" + "fmt" + "slices" "filippo.io/edwards25519" ) +type PacketType uint16 +const ( + ID_LENGTH = 16 + PUBKEY_LENGTH = 32 + ECDH_LENGTH = 32 + SIGNATURE_LENGTH = 64 + HMAC_LENGTH = 64 + + SESSION_OPEN_LENGTH = PUBKEY_LENGTH + ECDH_LENGTH + SIGNATURE_LENGTH + SESSION_CONNECT_LENGTH = ID_LENGTH + 2 + HMAC_LENGTH // + return addr string length + + SESSION_OPEN PacketType = iota + SESSION_CONNECT + SESSION_CLOSE + SESSION_CLOSED + SESSION_DATA +) + +func SessionKeyID(session_secret []byte) SessionID { + hash := sha512.Sum512(session_secret) + return (SessionID)(hash[0:16]) +} + +func NewSessionConnect(address string, session_secret []byte) []byte { + packet := make([]byte, SESSION_CONNECT_LENGTH + len(address)) + cur := 0 + + session_id := [16]byte(SessionKeyID(session_secret)) + copy(packet[cur:], session_id[:]) + cur += ID_LENGTH + + binary.BigEndian.PutUint16(packet[cur:], uint16(len(address))) + cur += 2 + + copy(packet[cur:], []byte(address)) + cur += len(address) + + hmac := sha512.Sum512(append(packet[:cur], session_secret...)) + copy(packet[cur:], hmac[:]) + + return packet +} + +func ParseSessionConnect(session_connect []byte, session_secret []byte) (SessionID, string, error) { + if len(session_connect) < SESSION_CONNECT_LENGTH { + return SessionID{}, "", fmt.Errorf("Bad session connect length: %d/%d", len(session_connect), SESSION_CONNECT_LENGTH) + } + + cur := 0 + + session_id := SessionID(session_connect[cur:cur+ID_LENGTH]) + cur += ID_LENGTH + + address_length := int(binary.BigEndian.Uint16(session_connect[cur:cur+2])) + cur += 2 + + if len(session_connect) != (SESSION_CONNECT_LENGTH + address_length) { + return SessionID{}, "", fmt.Errorf("Bad session connect length: %d/%d", len(session_connect), SESSION_CONNECT_LENGTH + address_length) + } + + address := string(session_connect[cur:cur+address_length]) + cur += address_length + + hmac_digest := make([]byte, cur) + copy(hmac_digest, session_connect[:cur]) + + hmac := session_connect[cur:cur+HMAC_LENGTH] + cur += HMAC_LENGTH + + calculated_hmac := sha512.Sum512(append(hmac_digest, session_secret...)) + if slices.Compare(hmac, calculated_hmac[:]) != 0 { + return SessionID{}, "", fmt.Errorf("Session connect bad HMAC") + } + + return session_id, address, nil +} + func NewSessionOpen(key ed25519.PrivateKey) ([]byte, ed25519.PrivateKey, error) { if key == nil { return nil, nil, fmt.Errorf("Cannot create a SESSION_OPEN packet without a key") diff --git a/packet_test.go b/packet_test.go index 1fdb6d1..5c02537 100644 --- a/packet_test.go +++ b/packet_test.go @@ -49,3 +49,20 @@ func TestECDH(t *testing.T) { t.Fatalf("Server and Client secrets do not match") } } + +func TestSessionConnect(t *testing.T) { + secret := make([]byte, 32) + test_addr := "test_addr" + + session_connect := NewSessionConnect(test_addr, secret) + parsed_session_id, parsed_addr, err := ParseSessionConnect(session_connect, secret) + fatalErr(t, err) + + if parsed_addr != test_addr { + t.Fatalf("Parsed address(%s) does not match test address(%s)", parsed_addr, test_addr) + } + + if parsed_session_id != SessionKeyID(secret) { + t.Fatalf("Parsed session ID %s does not match original %s", parsed_session_id, SessionKeyID(secret)) + } +} diff --git a/server.go b/server.go index 81c7d22..d8efb4f 100644 --- a/server.go +++ b/server.go @@ -13,21 +13,6 @@ import ( const ( SERVER_UDP_BUFFER_SIZE = 2048 - - PUBKEY_LENGTH = 32 - ECDH_LENGTH = 32 - SIGNATURE_LENGTH = 64 - SESSION_OPEN_LENGTH = PUBKEY_LENGTH + ECDH_LENGTH + SIGNATURE_LENGTH -) - -type PacketType uint16 -const ( - SESSION_OPEN PacketType = iota - SESSION_AUTHENTICATE - SESSION_CONNECT - SESSION_CLOSE - SESSION_CLOSED - SESSION_DATA ) /*