Start implementing the message handlers

This commit is contained in:
eyedeekay
2025-05-08 22:59:36 -04:00
parent 9cb4af8f06
commit 2a28c8ee01
5 changed files with 76 additions and 66 deletions

View File

@ -8,53 +8,9 @@ import (
"github.com/samber/oops"
)
func (c *NTCP2Session) sendHandshakeMessage(conn net.Conn, hs *handshake.HandshakeState, processor handshake.HandshakeMessageProcessor) error {
// 1. Create message
message, err := processor.CreateMessage(hs)
if err != nil {
return oops.Errorf("failed to create message: %w", err)
}
// 2. Set deadline
if err := conn.SetDeadline(time.Now().Add(NTCP2_HANDSHAKE_TIMEOUT)); err != nil {
return oops.Errorf("failed to set deadline: %w", err)
}
// 3. Obfuscate key
obfuscatedKey, err := processor.ObfuscateKey(message, hs)
if err != nil {
return oops.Errorf("failed to obfuscate key: %w", err)
}
// 4. Encrypt options
ciphertext, err := processor.Encrypt(message, obfuscatedKey, hs)
if err != nil {
return oops.Errorf("failed to encrypt options: %w", err)
}
// 5. Assemble message
fullMessage := append(obfuscatedKey, ciphertext...)
fullMessage = append(fullMessage, processor.GetPadding(message)...)
// 6. Write message
if _, err := conn.Write(fullMessage); err != nil {
return oops.Errorf("failed to send message: %w", err)
}
return nil
}
// sendSessionRequest sends Message 1 (SessionRequest) to the remote peer
func (c *NTCP2Session) sendSessionRequest(conn net.Conn, hs *handshake.HandshakeState) error {
/*
sendSessionRequest implements NTCP2 Message 1 (SessionRequest):
1. Create session request message with options block (version, padding length, etc.)
2. Set timeout deadline for the connection
3. Obfuscate ephemeral key (X) using AES with Bob's router hash as key
4. Encrypt options block using ChaCha20-Poly1305
5. Assemble final message: obfuscated X + encrypted options + padding
6. Write complete message to connection
*/
log.Debugf("NTCP2: Sending SessionRequest message")
// 1. Create and send X (ephemeral key) | Padding
// uses CreateSessionRequest from session_request.go

View File

@ -80,7 +80,7 @@ type HandshakeMessageProcessor interface {
ReadMessage(conn net.Conn, hs *HandshakeState) (messages.Message, error)
ProcessMessage(message messages.Message, hs *HandshakeState) error
ObfuscateKey(msg messages.Message, hs *HandshakeState) ([]byte, error)
Encrypt(msg messages.Message, obfuscatedKey []byte, hs *HandshakeState) ([]byte, error)
EncryptPayload(msg messages.Message, obfuscatedKey []byte, hs *HandshakeState) ([]byte, error)
GetPadding(msg messages.Message) []byte
MessageType() messages.MessageType
}

View File

@ -16,9 +16,8 @@ func (s *SessionConfirmedProcessor) CreateMessage(hs *handshake.HandshakeState)
panic("unimplemented")
}
// Encrypt implements handshake.HandshakeMessageProcessor.
// Subtle: this method shadows the method (*NTCP2Session).Encrypt of SessionConfirmedProcessor.NTCP2Session.
func (s *SessionConfirmedProcessor) Encrypt(msg messages.Message, obfuscatedKey []byte, hs *handshake.HandshakeState) ([]byte, error) {
// EncryptPayload implements handshake.HandshakeMessageProcessor.
func (s *SessionConfirmedProcessor) EncryptPayload(msg messages.Message, obfuscatedKey []byte, hs *handshake.HandshakeState) ([]byte, error) {
panic("unimplemented")
}

View File

@ -16,9 +16,8 @@ func (s *SessionCreatedProcessor) CreateMessage(hs *handshake.HandshakeState) (m
panic("unimplemented")
}
// Encrypt implements handshake.HandshakeMessageProcessor.
// Subtle: this method shadows the method (*NTCP2Session).Encrypt of SessionCreatedProcessor.NTCP2Session.
func (s *SessionCreatedProcessor) Encrypt(msg messages.Message, obfuscatedKey []byte, hs *handshake.HandshakeState) ([]byte, error) {
// EncryptPayload implements handshake.HandshakeMessageProcessor.
func (s *SessionCreatedProcessor) EncryptPayload(msg messages.Message, obfuscatedKey []byte, hs *handshake.HandshakeState) ([]byte, error) {
panic("unimplemented")
}
@ -29,7 +28,7 @@ func (s *SessionCreatedProcessor) GetPadding(msg messages.Message) []byte {
// MessageType implements handshake.HandshakeMessageProcessor.
func (s *SessionCreatedProcessor) MessageType() messages.MessageType {
panic("unimplemented")
return messages.MessageTypeSessionCreated
}
// ObfuscateKey implements handshake.HandshakeMessageProcessor.

View File

@ -8,6 +8,7 @@ import (
"github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/transport/ntcp/handshake"
"github.com/go-i2p/go-i2p/lib/transport/ntcp/messages"
"github.com/samber/oops"
)
/*
@ -23,10 +24,18 @@ type SessionRequestProcessor struct {
*NTCP2Session
}
// Encrypt implements handshake.HandshakeMessageProcessor.
// Subtle: this method shadows the method (*NTCP2Session).Encrypt of SessionRequestProcessor.NTCP2Session.
func (s *SessionRequestProcessor) Encrypt(msg messages.Message, obfuscatedKey []byte, hs *handshake.HandshakeState) ([]byte, error) {
panic("unimplemented")
// EncryptPayload encrypts the payload portion of the message
func (p *SessionRequestProcessor) EncryptPayload(
message messages.Message,
obfuscatedKey []byte,
hs *handshake.HandshakeState,
) ([]byte, error) {
req, ok := message.(*messages.SessionRequest)
if !ok {
return nil, oops.Errorf("expected SessionRequest message")
}
return p.NTCP2Session.encryptSessionRequestOptions(req, obfuscatedKey)
}
// MessageType implements handshake.HandshakeMessageProcessor.
@ -39,9 +48,46 @@ func (s *SessionRequestProcessor) ProcessMessage(message messages.Message, hs *h
panic("unimplemented")
}
// ReadMessage implements handshake.HandshakeMessageProcessor.
func (s *SessionRequestProcessor) ReadMessage(conn net.Conn, hs *handshake.HandshakeState) (messages.Message, error) {
panic("unimplemented")
// ReadMessage reads a SessionRequest message from the connection
func (p *SessionRequestProcessor) ReadMessage(conn net.Conn, hs *handshake.HandshakeState) (messages.Message, error) {
// 1. Read ephemeral key
obfuscatedX, err := p.NTCP2Session.readEphemeralKey(conn)
if err != nil {
return nil, err
}
// 2. Process ephemeral key
deobfuscatedX, err := p.NTCP2Session.processEphemeralKey(obfuscatedX, hs)
if err != nil {
return nil, err
}
// 3. Read options block
encryptedOptions, err := p.NTCP2Session.readOptionsBlock(conn)
if err != nil {
return nil, err
}
// 4. Process options block
options, err := p.NTCP2Session.processOptionsBlock(encryptedOptions, obfuscatedX, deobfuscatedX, hs)
if err != nil {
return nil, err
}
// 5. Read padding if present
paddingLen := options.PaddingLength.Int()
if paddingLen > 0 {
if err := p.NTCP2Session.readAndValidatePadding(conn, paddingLen); err != nil {
return nil, err
}
}
// Construct the full message
return &messages.SessionRequest{
XContent: [32]byte{}, // We've already processed this
Options: *options,
Padding: make([]byte, paddingLen), // Padding content doesn't matter after validation
}, nil
}
// CreateMessage implements HandshakeMessageProcessor.
@ -98,14 +144,24 @@ func (s *SessionRequestProcessor) CreateMessage(hs *handshake.HandshakeState) (m
}, nil
}
// GetPadding implements HandshakeMessageProcessor.
func (s *SessionRequestProcessor) GetPadding(msg messages.Message) []byte {
panic("unimplemented")
// GetPadding retrieves padding from a message
func (p *SessionRequestProcessor) GetPadding(message messages.Message) []byte {
req, ok := message.(*messages.SessionRequest)
if !ok {
return nil
}
return req.Padding
}
// ObfuscateKey implements HandshakeMessageProcessor.
func (s *SessionRequestProcessor) ObfuscateKey(msg messages.Message, hs *handshake.HandshakeState) ([]byte, error) {
return s.ObfuscateEphemeral(msg.(*messages.SessionRequest).XContent[:])
// ObfuscateKey obfuscates the ephemeral key for transmission
func (p *SessionRequestProcessor) ObfuscateKey(message messages.Message, handshake *handshake.HandshakeState) ([]byte, error) {
req, ok := message.(*messages.SessionRequest)
if !ok {
return nil, oops.Errorf("expected SessionRequest message")
}
return p.NTCP2Session.ObfuscateEphemeral(req.XContent[:])
}
var _ handshake.HandshakeMessageProcessor = (*SessionRequestProcessor)(nil)