mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-07-13 11:54:46 -04:00
handshake interface implementation stuff
This commit is contained in:
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
/*
|
||||
|
68
lib/transport/ntcp/handshake/methods.go
Normal file
68
lib/transport/ntcp/handshake/methods.go
Normal 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")
|
||||
}
|
Reference in New Issue
Block a user