Work on implementing and migrating to message processors

This commit is contained in:
eyedeekay
2025-05-10 21:23:05 -04:00
parent 09fe22178d
commit 4a89c14734
2 changed files with 108 additions and 9 deletions

View File

@ -1,8 +1,11 @@
package ntcp
import (
"crypto/rand"
"fmt"
"net"
"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"
)
@ -45,7 +48,47 @@ type SessionConfirmedProcessor struct {
// CreateMessage implements handshake.HandshakeMessageProcessor.
func (s *SessionConfirmedProcessor) CreateMessage(hs *handshake.HandshakeState) (messages.Message, error) {
panic("unimplemented")
// Create the SessionConfirmed message
sc := &messages.SessionConfirmed{}
// Step 1: Get our static key from the handshake state
// Note: The static key must be encrypted using the handshakeState's WriteMessage
// but we need to extract it first to store in the result structure
localKeyPair, err := s.NTCP2Session.localStaticKey()
if err != nil {
return nil, fmt.Errorf("failed to get local static keypair: %w", err)
}
// Copy the 32-byte static key
copy(sc.StaticKey[:], localKeyPair[:])
// Step 2: Set the RouterInfo
sc.RouterInfo = &s.NTCP2Session.RouterInfo
// Step 3: Create options with padding settings
// Use default padding for now - we should make this something we can configure
paddingLength, err := data.NewIntegerFromInt(calculatePaddingLength(sc.RouterInfo), 1)
if err != nil {
return nil, fmt.Errorf("failed to create padding length: %w", err)
}
sc.Options = &messages.ConfirmedOptions{
PaddingLength: paddingLength,
}
// Step 4: Generate padding data according to the specified length
// In a real implementation, this should be cryptographically secure random data
if paddingLength.Int() > 0 {
sc.Padding = make([]byte, paddingLength.Int())
if _, err := rand.Read(sc.Padding); err != nil {
return nil, fmt.Errorf("failed to generate padding: %w", err)
}
}
// The actual encryption of the message will happen in the calling function
// using the handshakeState.WriteMessage() method, as it needs to maintain the
// proper noise protocol state
return sc, nil
}
// EncryptPayload implements handshake.HandshakeMessageProcessor.

View File

@ -1,8 +1,12 @@
package ntcp
import (
"crypto/rand"
"math/big"
"net"
"github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/crypto/curve25519"
"github.com/go-i2p/go-i2p/lib/transport/ntcp/handshake"
"github.com/go-i2p/go-i2p/lib/transport/ntcp/messages"
"github.com/samber/oops"
@ -40,7 +44,46 @@ type SessionCreatedProcessor struct {
// CreateMessage implements handshake.HandshakeMessageProcessor.
func (s *SessionCreatedProcessor) CreateMessage(hs *handshake.HandshakeState) (messages.Message, error) {
panic("unimplemented")
// 1. Generate ephemeral key (handshakeState has already done this, we just need to extract it)
ephemeralKey, err := s.NTCP2Session.HandshakeState.(*handshake.HandshakeState).LocalEphemeral.Public()
if err != nil {
return nil, oops.Errorf("failed to get local ephemeral key: %w", err)
}
// 2. Create padding according to NTCP2 spec
// NTCP2 spec recommends 0-31 bytes of random padding
paddingSize, err := rand.Int(rand.Reader, big.NewInt(32))
if err != nil {
return nil, oops.Errorf("failed to generate random padding size: %w", err)
}
padding := make([]byte, paddingSize.Int64())
if _, err := rand.Read(padding); err != nil {
return nil, oops.Errorf("failed to generate padding: %w", err)
}
// 3. Create response options
timestamp, err := data.DateFromTime(s.GetCurrentTime())
if err != nil {
return nil, oops.Errorf("failed to create timestamp: %w", err)
}
paddingLen, err := data.NewIntegerFromInt(len(padding), 1)
if err != nil {
return nil, oops.Errorf("failed to create padding length: %w", err)
}
// Create response options with appropriate fields
responseOptions := &messages.CreatedOptions{
PaddingLength: paddingLen,
Timestamp: timestamp,
}
// 4. Return the complete SessionCreated message
return &messages.SessionCreated{
YContent: [32]byte(ephemeralKey.Bytes()), // Y is the obfuscated ephemeral key
Options: responseOptions,
Padding: padding,
}, nil
}
// EncryptPayload implements handshake.HandshakeMessageProcessor.
@ -62,9 +105,27 @@ func (s *SessionCreatedProcessor) EncryptPayload(
)
}
// GetPadding implements handshake.HandshakeMessageProcessor.
// ObfuscateKey should follow the same pattern as in SessionRequestProcessor
func (s *SessionCreatedProcessor) ObfuscateKey(msg messages.Message, hs *handshake.HandshakeState) ([]byte, error) {
created, ok := msg.(*messages.SessionCreated)
if !ok {
return nil, oops.Errorf("expected SessionCreated message")
}
// Store the ephemeral key in the handshake state for reuse
hs.LocalEphemeral = curve25519.Curve25519PrivateKey(created.YContent[:])
return s.NTCP2Session.ObfuscateEphemeral(created.YContent[:])
}
// GetPadding retrieves padding from a message
func (s *SessionCreatedProcessor) GetPadding(msg messages.Message) []byte {
panic("unimplemented")
created, ok := msg.(*messages.SessionCreated)
if !ok {
return nil
}
return created.Padding
}
// MessageType implements handshake.HandshakeMessageProcessor.
@ -72,11 +133,6 @@ func (s *SessionCreatedProcessor) MessageType() messages.MessageType {
return messages.MessageTypeSessionCreated
}
// ObfuscateKey implements handshake.HandshakeMessageProcessor.
func (s *SessionCreatedProcessor) ObfuscateKey(msg messages.Message, hs *handshake.HandshakeState) ([]byte, error) {
panic("unimplemented")
}
// ProcessMessage implements handshake.HandshakeMessageProcessor.
func (s *SessionCreatedProcessor) ProcessMessage(message messages.Message, hs *handshake.HandshakeState) error {
panic("unimplemented")