Added session connect packet

live
noah metz 2024-04-03 19:31:58 -06:00
parent 3f1485e493
commit a52250bcf8
4 changed files with 99 additions and 21 deletions

@ -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) {

@ -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")

@ -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))
}
}

@ -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
)
/*