NTCP2: Change noise interface so we get static keys from better places

This commit is contained in:
eyedeekay
2024-12-21 22:13:03 -05:00
parent bd92221d56
commit 8bc5ca162a
11 changed files with 136 additions and 32 deletions

View File

@ -7,7 +7,7 @@ import (
"time"
. "github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/util/logger"
"github.com/go-i2p/logger"
"github.com/sirupsen/logrus"
)

View File

@ -148,10 +148,10 @@ func Test10K(t *testing.T) {
t.Fatalf("Failed to read temp directory: %v", err)
}
for _, file := range files {
for d, file := range files {
if !file.IsDir() && strings.HasPrefix(file.Name(), "routerInfo-") {
// Read the router info file
log.Println("RI LOAD: ", file.Name())
log.Println("RI LOAD: ", d, file.Name())
data, err := os.ReadFile(filepath.Join(tempDir, file.Name()))
if err != nil {
t.Logf("Failed to read file %s: %v", file.Name(), err)

View File

@ -1,7 +1,6 @@
package transport
import (
"github.com/go-i2p/go-i2p/lib/common/router_identity"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/logger"
)
@ -25,7 +24,7 @@ func Mux(t ...Transport) (tmux *TransportMuxer) {
}
// set the identity for every transport
func (tmux *TransportMuxer) SetIdentity(ident router_identity.RouterIdentity) (err error) {
func (tmux *TransportMuxer) SetIdentity(ident router_info.RouterInfo) (err error) {
log.WithField("identity", ident).Debug("TransportMuxer: Setting identity for all transports")
for i, t := range tmux.trans {
err = t.SetIdentity(ident)

View File

@ -14,7 +14,6 @@ type HandshakeState struct {
ephemeral *noise.DHKey
pattern noise.HandshakePattern
handshakeComplete bool
HandKey noise.DHKey
*noise.HandshakeState
}

View File

@ -13,7 +13,7 @@ import (
func (c *NoiseSession) RunIncomingHandshake() error {
log.Debug("Starting incoming handshake")
negData, msg, state, err := c.ComposeReceiverHandshakeMessage(c.HandKey, nil, nil, nil)
negData, msg, state, err := c.ComposeReceiverHandshakeMessage(*c.HandshakeKey(), nil, nil, nil)
if err != nil {
log.WithError(err).Error("Failed to compose receiver handshake message")
return err
@ -42,11 +42,11 @@ func (c *NoiseSession) RunIncomingHandshake() error {
return nil
}
func (c *NoiseSession) ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) {
func (c *NoiseSession) ComposeReceiverHandshakeMessage(localStatic noise.DHKey, remoteStatic []byte, payload []byte, ephemeralPrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) {
log.Debug("Starting ComposeReceiverHandshakeMessage")
if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() {
log.WithField("rs_length", len(rs)).Error("Invalid remote static key length")
if len(remoteStatic) != 0 && len(remoteStatic) != noise.DH25519.DHLen() {
log.WithField("rs_length", len(remoteStatic)).Error("Invalid remote static key length")
return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported")
}
@ -56,18 +56,18 @@ func (c *NoiseSession) ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte,
negData[5] = NOISE_PATTERN_XK
var random io.Reader
if len(ePrivate) == 0 {
if len(ephemeralPrivate) == 0 {
random = rand.Reader
log.Debug("Using crypto/rand as random source")
} else {
random = bytes.NewBuffer(ePrivate)
random = bytes.NewBuffer(ephemeralPrivate)
}
config := noise.Config{
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256),
Pattern: pattern,
Initiator: false,
StaticKeypair: s,
StaticKeypair: localStatic,
Random: random,
}

View File

@ -4,6 +4,7 @@ import (
"bytes"
"crypto/rand"
"errors"
"fmt"
"io"
"github.com/sirupsen/logrus"
@ -14,7 +15,7 @@ import (
func (c *NoiseSession) RunOutgoingHandshake() error {
log.Debug("Starting outgoing handshake")
negData, msg, state, err := c.ComposeInitiatorHandshakeMessage(c.HandKey, nil, nil, nil)
negData, msg, state, err := c.ComposeInitiatorHandshakeMessage(nil, nil)
if err != nil {
log.WithError(err).Error("Failed to compose initiator handshake message")
return err
@ -46,8 +47,6 @@ func (c *NoiseSession) RunOutgoingHandshake() error {
}
func (c *NoiseSession) ComposeInitiatorHandshakeMessage(
localStatic noise.DHKey,
remoteStatic []byte,
payload []byte,
ephemeralPrivate []byte,
) (
@ -58,6 +57,21 @@ func (c *NoiseSession) ComposeInitiatorHandshakeMessage(
) {
log.Debug("Starting ComposeInitiatorHandshakeMessage")
remoteStatic, err := c.peerStaticKey()
if err != nil {
return nil, nil, nil, fmt.Errorf("Peer static key retrieval error: %s", err)
}
/*localStatic, err := c.localStaticKey()
if err != nil {
return nil, nil, nil, fmt.Errorf("Local static key retrieval error: %s", err)
}
localStaticDH := noise.DHKey{
Public: localStatic[:],
Private: localStatic[:],
}*/
localStaticDH := *c.HandshakeKey()
if len(remoteStatic) != 0 && len(remoteStatic) != noise.DH25519.DHLen() {
return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported")
}
@ -78,7 +92,7 @@ func (c *NoiseSession) ComposeInitiatorHandshakeMessage(
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256),
Pattern: pattern,
Initiator: true,
StaticKeypair: localStatic,
StaticKeypair: localStaticDH,
Random: random,
}

View File

@ -19,7 +19,7 @@ type NoiseSession struct {
router_info.RouterInfo
*noise.CipherState
*sync.Cond
*NoiseTransport // The parent transport, which "Dialed" the connection to the peer whith whom we established the session
*NoiseTransport // The parent transport, which "Dialed" the connection to the peer with whom we established the session
*HandshakeState
RecvQueue *cb.Queue
SendQueue *cb.Queue
@ -90,6 +90,33 @@ func (c *NoiseSession) processCallback(publicKey []byte, payload []byte) error {
return err
}
// PeerStaticKey is equal to the NTCP2 peer's static public key, found in their router info
func (s *NoiseSession) peerStaticKey() ([32]byte, error) {
for _, addr := range s.RouterInfo.RouterAddresses() {
transportStyle, err := addr.TransportStyle().Data()
if err != nil {
continue
}
if transportStyle == NOISE_PROTOCOL_NAME {
return addr.StaticKey()
}
}
return [32]byte{}, fmt.Errorf("Remote static key error")
}
func (s *NoiseSession) peerStaticIV() ([16]byte, error) {
for _, addr := range s.RouterInfo.RouterAddresses() {
transportStyle, err := addr.TransportStyle().Data()
if err != nil {
continue
}
if transportStyle == NOISE_PROTOCOL_NAME {
return addr.InitializationVector()
}
}
return [16]byte{}, fmt.Errorf("Remote static IV error")
}
// newBlock allocates a new packet, from hc's free list if possible.
func newBlock() []byte {
// return make([]byte, MaxPayloadSize)

View File

@ -8,20 +8,24 @@ package noise
import (
"errors"
"fmt"
"net"
"sync"
"github.com/flynn/noise"
"github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/common/router_identity"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/transport"
)
const NOISE_PROTOCOL_NAME = "NOISE"
type NoiseTransport struct {
sync.Mutex
router_identity.RouterIdentity
router_info.RouterInfo
transportStyle string
Listener net.Listener
peerConnections map[data.Hash]transport.TransportSession
}
@ -71,9 +75,9 @@ func (noopt *NoiseTransport) Name() string {
// will bind if the underlying socket is not already
// if the underlying socket is already bound update the RouterIdentity
// returns any errors that happen if they do
func (noopt *NoiseTransport) SetIdentity(ident router_identity.RouterIdentity) (err error) {
func (noopt *NoiseTransport) SetIdentity(ident router_info.RouterInfo) (err error) {
log.WithField("identity", ident).Debug("NoiseTransport: Setting identity")
noopt.RouterIdentity = ident
noopt.RouterInfo = ident
if noopt.Listener == nil {
log.WithFields(logrus.Fields{
"at": "(NoiseTransport) SetIdentity",
@ -158,6 +162,7 @@ func NewNoiseTransport(netSocket net.Listener) *NoiseTransport {
return &NoiseTransport{
peerConnections: make(map[data.Hash]transport.TransportSession),
Listener: netSocket,
transportStyle: NOISE_PROTOCOL_NAME,
}
}
@ -175,3 +180,35 @@ func NewNoiseTransportSocket() (*NoiseTransport, error) {
log.WithField("addr", netSocket.Addr().String()).Debug("Created new NoiseTransportSocket")
return _transport, nil
}
// LocalStaticKey is equal to the NTCP2 static public key, found in our router info
func (s *NoiseTransport) localStaticKey() ([32]byte, error) {
// s.RouterIdentity
for _, addr := range s.RouterInfo.RouterAddresses() {
transportStyle, err := addr.TransportStyle().Data()
if err != nil {
continue
}
if transportStyle == s.transportStyle {
return addr.StaticKey()
}
}
return [32]byte{}, fmt.Errorf("Remote static key error")
}
func (s *NoiseTransport) localStaticIV() ([16]byte, error) {
for _, addr := range s.RouterInfo.RouterAddresses() {
transportStyle, err := addr.TransportStyle().Data()
if err != nil {
continue
}
if transportStyle == s.transportStyle {
return addr.InitializationVector()
}
}
return [16]byte{}, fmt.Errorf("Remote static IV error")
}
func (h *NoiseTransport) HandshakeKey() *noise.DHKey {
return nil
}

View File

@ -30,6 +30,7 @@ import (
// NTCP2Session extends the base noise.NoiseSession with NTCP2-specific functionality
type NTCP2Session struct {
*noise.NoiseSession
*NTCP2Transport
paddingStrategy PaddingStrategy
}

View File

@ -19,18 +19,18 @@ const (
NTCP_MESSAGE_MAX_SIZE = 65537
)
var exampleNTCPTransport transport.Transport = &Transport{}
var exampleNTCPTransport transport.Transport = &NTCP2Transport{}
// Transport is an ntcp2 transport implementing transport.Transport interface
type Transport struct {
// NTCP2Transport is an ntcp2 transport implementing transport.NTCP2Transport interface
type NTCP2Transport struct {
*noise.NoiseTransport
}
func (t *Transport) Name() string {
func (t *NTCP2Transport) Name() string {
return NTCP_PROTOCOL_NAME
}
func (t *Transport) Compatible(routerInfo router_info.RouterInfo) bool {
func (t *NTCP2Transport) Compatible(routerInfo router_info.RouterInfo) bool {
// Check if the router info contains NTCP2 address and capabilities
addresses := routerInfo.RouterAddresses()
for _, addr := range addresses {
@ -45,7 +45,7 @@ func (t *Transport) Compatible(routerInfo router_info.RouterInfo) bool {
return false
}
func (t *Transport) GetSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) {
func (t *NTCP2Transport) GetSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) {
// Create new NTCP2 session
session, err := NewNTCP2Session(routerInfo)
if err != nil {
@ -53,14 +53,14 @@ func (t *Transport) GetSession(routerInfo router_info.RouterInfo) (transport.Tra
}
// Perform handshake
if err := session.Handshake(routerInfo); err != nil {
if err := session.NTCP2Transport.Handshake(routerInfo); err != nil {
return nil, err
}
return session, nil
}
func (t *Transport) Accept() (net.Conn, error) {
func (t *NTCP2Transport) Accept() (net.Conn, error) {
conn, err := t.NoiseTransport.Accept()
if err != nil {
return nil, err
@ -86,3 +86,31 @@ func (t *Transport) Accept() (net.Conn, error) {
return session, nil
}
// LocalStaticKey is equal to the NTCP2 static public key, found in our router info
func (s *NTCP2Transport) localStaticKey() ([32]byte, error) {
// s.RouterIdentity
for _, addr := range s.RouterInfo.RouterAddresses() {
transportStyle, err := addr.TransportStyle().Data()
if err != nil {
continue
}
if transportStyle == NTCP_PROTOCOL_NAME {
return addr.StaticKey()
}
}
return [32]byte{}, fmt.Errorf("Remote static key error")
}
func (s *NTCP2Transport) localStaticIV() ([16]byte, error) {
for _, addr := range s.RouterInfo.RouterAddresses() {
transportStyle, err := addr.TransportStyle().Data()
if err != nil {
continue
}
if transportStyle == NTCP_PROTOCOL_NAME {
return addr.InitializationVector()
}
}
return [16]byte{}, fmt.Errorf("Remote static IV error")
}

View File

@ -3,7 +3,6 @@ package transport
import (
"net"
"github.com/go-i2p/go-i2p/lib/common/router_identity"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/i2np"
@ -37,7 +36,7 @@ type Transport interface {
// will bind if the underlying socket is not already
// if the underlying socket is already bound update the RouterIdentity
// returns any errors that happen if they do
SetIdentity(ident router_identity.RouterIdentity) error
SetIdentity(ident router_info.RouterInfo) error
// Obtain a transport session with a router given its RouterInfo.
// If a session with this router is NOT already made attempt to create one and block until made or until an error happens