mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-06-15 21:28:49 -04:00
Start implementing the message handlers
This commit is contained in:
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user