handshake interface implementation stuff

This commit is contained in:
eyedeekay
2025-05-10 20:25:02 -04:00
parent dd116095aa
commit a4acb01be9
3 changed files with 96 additions and 0 deletions

View File

@ -3,6 +3,8 @@ package ntcp
import (
"encoding/binary"
"github.com/go-i2p/go-i2p/lib/transport/ntcp/handshake"
"github.com/go-i2p/go-i2p/lib/transport/ntcp/kdf"
"github.com/samber/oops"
"golang.org/x/crypto/chacha20poly1305"
)
@ -123,3 +125,26 @@ func (c *NTCP2Session) DecryptWithDerivedKey(
) ([]byte, error) {
return c.PerformAEADWithDerivedKey(keyMaterial, data, associatedData, nonceCounter, false)
}
// Extend aead.go with the following function:
// DeriveSessionKeys derives all required keys for a session using existing X25519 shared secret
// This replaces scattered key derivation across session files
func (c *NTCP2Session) DeriveSessionKeys(sharedSecret []byte, ephemeralKey []byte) error {
// Use existing KDF context from the kdf package
kdfContext := kdf.NewNTCP2KDF()
// Derive ChaCha20 key (already implemented)
chacha20Key, err := kdfContext.MixKey(sharedSecret)
if err != nil {
return oops.Errorf("failed to derive ChaCha20 key: %w", err)
}
// Store key in session for reuse
c.HandshakeState.(*handshake.HandshakeState).ChachaKey = chacha20Key
// Mix hash with ephemeral key (consistent implementation)
kdfContext.MixHash(ephemeralKey)
return nil
}

View File

@ -8,6 +8,7 @@ import (
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/crypto/curve25519"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"github.com/go-i2p/go-i2p/lib/transport/handshake"
"github.com/go-i2p/go-i2p/lib/transport/ntcp/messages"
"github.com/samber/oops"
)
@ -40,6 +41,8 @@ type HandshakeState struct {
RouterInfo *router_info.RouterInfo
}
var _ handshake.HandshakeState = &HandshakeState{}
// NewHandshakeState creates a new handshake state for initiating a connection
func NewHandshakeState(localKey types.PrivateKey, remoteKey types.PublicKey, ri *router_info.RouterInfo) (*HandshakeState, error) {
/*

View File

@ -0,0 +1,68 @@
package handshake
import (
"github.com/flynn/noise"
"github.com/go-i2p/go-i2p/lib/crypto/curve25519"
"github.com/samber/oops"
)
// CompleteHandshake implements handshake.HandshakeState.
func (h *HandshakeState) CompleteHandshake() error {
// Verify we have all necessary components for a complete handshake
if len(h.SharedSecret) == 0 {
return oops.Errorf("handshake incomplete: missing shared secret")
}
if len(h.ChachaKey) == 0 {
return oops.Errorf("handshake incomplete: missing session key")
}
if len(h.HandshakeHash) == 0 {
return oops.Errorf("handshake incomplete: missing handshake hash")
}
return nil
}
// GenerateEphemeral implements handshake.HandshakeState.
func (h *HandshakeState) GenerateEphemeral() (*noise.DHKey, error) {
// Already generated in NewHandshakeState, but we format it for noise protocol
if h.LocalEphemeral == nil {
var err error
_, h.LocalEphemeral, err = curve25519.GenerateKeyPair()
if err != nil {
return nil, oops.Errorf("failed to generate ephemeral key: %w", err)
}
}
// Convert our key types to Noise framework key type
public, err := h.LocalEphemeral.Public()
if err != nil {
return nil, oops.Errorf("failed to get public key: %w", err)
}
// Convert to Noise DHKey format
dhKey := &noise.DHKey{
Private: h.LocalEphemeral.Bytes(),
Public: public.Bytes(),
}
return dhKey, nil
}
// HandshakeComplete implements handshake.HandshakeState.
func (h *HandshakeState) HandshakeComplete() bool {
// The handshake is complete when we have:
// 1. A shared secret
// 2. A ChaCha20 key for the session
// 3. A handshake hash
return h.SharedSecret != nil &&
h.ChachaKey != nil &&
h.HandshakeHash != nil &&
len(h.SharedSecret) > 0 &&
len(h.ChachaKey) > 0 &&
len(h.HandshakeHash) > 0
}
// WriteMessage implements handshake.HandshakeState.
func (h *HandshakeState) WriteMessage(payload []byte) ([]byte, *noise.CipherState, *noise.CipherState, error) {
return []byte{}, nil, nil, oops.Errorf("not implemented")
}