From 6b5ea57cbd233811762f1268f6834799e992178a Mon Sep 17 00:00:00 2001 From: idk Date: Mon, 19 Sep 2022 14:35:49 -0400 Subject: [PATCH 01/94] Move my noise transport tests to a branch so I don't mess up the other branch --- Makefile | 2 +- PASTA.md | 16 +-------------- lib/transport/noise/session.go | 29 +++++++++++++++++++++++++-- lib/transport/noise/session_test.go | 1 + lib/transport/noise/transport.go | 19 ++++++++++++++---- lib/transport/noise/transport_test.go | 15 ++++++++++++++ 6 files changed, 60 insertions(+), 22 deletions(-) create mode 100644 lib/transport/noise/session_test.go create mode 100644 lib/transport/noise/transport_test.go diff --git a/Makefile b/Makefile index d503b26..a0a8c64 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ $(EXE): $(GO) build -v -o $(EXE) test: - $(GO) test -v -failfast ./lib/common/data/... + $(GO) test -v -failfast ./lib/transport/noise/... clean: $(GO) clean -v diff --git a/PASTA.md b/PASTA.md index 599b8ba..69aebee 100644 --- a/PASTA.md +++ b/PASTA.md @@ -1,19 +1,5 @@ Weekly notes about what I'm working on ====================================== -July 18, 2022: + - Work on writing test for pure-noise transport - - Implementation-in-Progress of a pure-Noise TCP transport using flynn/noise. - - This transport is **not** operable with the rest of the I2P network and useful - only for testing the transport interface implementation. - - Most examples/docs on flynn/noise use client-server paradigm and not P2P paradigm, strictly - speaking. - - It does *not* process messages for obfuscation or de-obfuscation, key difference from NTCP2 - - It doesn't yet actually manage sending messages on a socket, right now it can: - - Set up a Transport muxer - - Set up a Transport, which is basically a session muxer sharing a common socket - - Set up a Session, which is an individual connection to a peer which speaks the transport protocol - - At some point there needs to be a loop on the socket which reads the socket for input and output. - - At this time the transports *intentionally* do not know about the nature of the underlying socket - beyond the fact that it must implement a `net.Conn` interface so that it can connect over TCP. - - In the future, this will need to be able to accept either a `net.Conn` or a `net.PacketConn` diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index 49319c8..83e002f 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -1,10 +1,11 @@ package noise import ( + "fmt" "net" cb "github.com/emirpasic/gods/queues/circularbuffer" - //. "github.com/flynn/noise" + log "github.com/sirupsen/logrus" "github.com/go-i2p/go-i2p/lib/common/router_info" "github.com/go-i2p/go-i2p/lib/i2np" @@ -36,10 +37,34 @@ func (s *NoiseSession) Close() error { return nil } -func NewNoiseTransportSession(ri router_info.RouterInfo, socket net.Conn) (transport.TransportSession, error) { +func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSession, error) { + socket, err := DialNoise("noise", ri) + if err != nil { + return nil, err + } return &NoiseSession{ Queue: cb.New(1024), RouterInfo: ri, Conn: socket, }, nil } + +// DialNoise initiates a session with a remote Noise transport, using a +// routerinfo to derive the address to connect to. It doesn't have any chance of +// working yet. +func DialNoise(network string, addr router_info.RouterInfo) (net.Conn, error) { + for _, addr := range addr.RouterAddresses() { + log.WithFields(log.Fields{ + "at": "(DialNoise)", + "addr": addr, + }).Log("error parsing router info") + Dial("noise", string(addr.TransportStyle())) + } + return nil, fmt.Errorf("No valid transport discovered.") +} + +// Dial initiates a session with a remote Noise transport at a host:port +// or ip:port +func Dial(network, addr string) (net.Conn, error) { + return net.Dial("tcp", addr) +} diff --git a/lib/transport/noise/session_test.go b/lib/transport/noise/session_test.go new file mode 100644 index 0000000..5b190a3 --- /dev/null +++ b/lib/transport/noise/session_test.go @@ -0,0 +1 @@ +package noise diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index a930bb5..e9dcc9f 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -20,7 +20,7 @@ import ( type NoiseTransport struct { routerIdentity router_identity.RouterIdentity peerConnections map[data.Hash]transport.TransportSession - netSocket net.Conn + netSocket net.Listener } var exampleNoiseTransport transport.Transport = &NoiseTransport{} @@ -48,10 +48,10 @@ func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (tran if len(hash) == 0 { return nil, errors.New("NoiseTransport: GetSession: RouterInfo has no IdentityHash") } - if t, ok := noopt.peerConnections[hash]; ok == true { + if t, ok := noopt.peerConnections[hash]; ok { return t, nil } - if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo, noopt.netSocket); err != nil { + if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo); err != nil { return noopt.peerConnections[hash], err } return nil, fmt.Errorf("Unable to obtain transport session with %s", routerInfo.IdentHash()) @@ -70,9 +70,20 @@ func (noopt *NoiseTransport) Close() error { return nil } -func NewNoiseTransport(netSocket net.Conn) *NoiseTransport { +// NewNoiseTransport create a NoiseTransport using a supplied net.Listener +func NewNoiseTransport(netSocket net.Listener) *NoiseTransport { return &NoiseTransport{ peerConnections: make(map[data.Hash]transport.TransportSession), netSocket: netSocket, } } + +// NewNoiseTransportSocket creates a Noise transport socket with a random +// host and port. +func NewNoiseTransportSocket() (*NoiseTransport, error) { + netSocket, err := net.Listen("tcp", "") + if err != nil { + return nil, err + } + return NewNoiseTransport(netSocket), nil +} diff --git a/lib/transport/noise/transport_test.go b/lib/transport/noise/transport_test.go new file mode 100644 index 0000000..f7bfb51 --- /dev/null +++ b/lib/transport/noise/transport_test.go @@ -0,0 +1,15 @@ +package noise + +import ( + "net" + "testing" +) + +func TestTransportMuxer(t *testing.T) { + ln, err := net.Listen("tcp", ":42069") + if err != nil { + t.Error(err) + } + nt := NewNoiseTransport(ln) + t.Log(nt.Name()) +} From a4ed06e5308012195932624ca2182acd49b46637 Mon Sep 17 00:00:00 2001 From: idk Date: Mon, 26 Sep 2022 12:18:33 -0400 Subject: [PATCH 02/94] update my notes --- PASTA.md | 9 +++++++-- lib/transport/noise/transport.go | 7 +++++-- lib/transport/noise/transport_test.go | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/PASTA.md b/PASTA.md index 69aebee..8574f0c 100644 --- a/PASTA.md +++ b/PASTA.md @@ -1,5 +1,10 @@ Weekly notes about what I'm working on ====================================== - - Work on writing test for pure-noise transport - +Started writing tests for noise transport and things started to get more real, for instance: +after reversing the too-many-sockets issue I realized I had left myself without a way to configure the actual underlying socket +like I couldn't tell it a port to use so it would pick a random one every time and so I'd have to get the port from the socket structure itself +then I got pulled back over to Easy-Install for a few days with the updates url in router.config bug, then the gitlab email issue, didn't get much further than that +thulium's willingness to second-guess my refactoring decisions continues to be valuable, he's finding things to simplify about twice a week days and running them by me, looking forward to seeing what comes of that +we're both working on branches right now with merges planned for "Soon" +EOT diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index e9dcc9f..a72f145 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -33,8 +33,11 @@ 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) error { +func (noopt *NoiseTransport) SetIdentity(ident router_identity.RouterIdentity) (err error) { noopt.routerIdentity = ident + if noopt.netSocket == nil { + noopt.netSocket, err = net.ListenTCP() + } return nil } @@ -57,7 +60,7 @@ func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (tran return nil, fmt.Errorf("Unable to obtain transport session with %s", routerInfo.IdentHash()) } -// return true if a routerInfo is compatable with this transport +// Compatable return true if a routerInfo is compatable with this transport func (noopt *NoiseTransport) Compatable(routerInfo router_info.RouterInfo) bool { _, ok := noopt.peerConnections[routerInfo.IdentHash()] return ok diff --git a/lib/transport/noise/transport_test.go b/lib/transport/noise/transport_test.go index f7bfb51..d121286 100644 --- a/lib/transport/noise/transport_test.go +++ b/lib/transport/noise/transport_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func TestTransportMuxer(t *testing.T) { +func TestTransport(t *testing.T) { ln, err := net.Listen("tcp", ":42069") if err != nil { t.Error(err) From fdc34b382ef8f67970ecf3d50af79fa8f0a9a20d Mon Sep 17 00:00:00 2001 From: idk Date: Sun, 16 Oct 2022 17:19:38 -0400 Subject: [PATCH 03/94] Fix some tests so it compiles again --- PASTA.md | 7 ------- lib/transport/noise/session.go | 2 +- lib/transport/noise/transport.go | 8 +++++++- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/PASTA.md b/PASTA.md index 8574f0c..2197447 100644 --- a/PASTA.md +++ b/PASTA.md @@ -1,10 +1,3 @@ Weekly notes about what I'm working on ====================================== -Started writing tests for noise transport and things started to get more real, for instance: -after reversing the too-many-sockets issue I realized I had left myself without a way to configure the actual underlying socket -like I couldn't tell it a port to use so it would pick a random one every time and so I'd have to get the port from the socket structure itself -then I got pulled back over to Easy-Install for a few days with the updates url in router.config bug, then the gitlab email issue, didn't get much further than that -thulium's willingness to second-guess my refactoring decisions continues to be valuable, he's finding things to simplify about twice a week days and running them by me, looking forward to seeing what comes of that -we're both working on branches right now with merges planned for "Soon" -EOT diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index 83e002f..83581ef 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -57,7 +57,7 @@ func DialNoise(network string, addr router_info.RouterInfo) (net.Conn, error) { log.WithFields(log.Fields{ "at": "(DialNoise)", "addr": addr, - }).Log("error parsing router info") + }).Error("error parsing router info") Dial("noise", string(addr.TransportStyle())) } return nil, fmt.Errorf("No valid transport discovered.") diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index a72f145..a0cb7ee 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -15,6 +15,7 @@ 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/go-i2p/lib/transport" + log "github.com/sirupsen/logrus" ) type NoiseTransport struct { @@ -36,7 +37,12 @@ func (noopt *NoiseTransport) Name() string { func (noopt *NoiseTransport) SetIdentity(ident router_identity.RouterIdentity) (err error) { noopt.routerIdentity = ident if noopt.netSocket == nil { - noopt.netSocket, err = net.ListenTCP() + log.WithFields(log.Fields{ + "at": "(NoiseTransport) SetIdentity", + "reason": "network socket is null", + }).Error("network socket is null") + err = errors.New("network socket is null") + return } return nil } From 7d16b0b2571ac2ce908aee8fdc2f14645fcc05b3 Mon Sep 17 00:00:00 2001 From: idk Date: Mon, 17 Oct 2022 02:16:44 -0400 Subject: [PATCH 04/94] update my notes --- PASTA.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PASTA.md b/PASTA.md index 2197447..db01fbf 100644 --- a/PASTA.md +++ b/PASTA.md @@ -1,3 +1,10 @@ Weekly notes about what I'm working on ====================================== +I made a ton of progress on Noise last week, I've got a fully working handshake and I think I'll be able to send an I2NP message to another Go Transport soon with a Go TransportSession +The logic of my Noise transport is basically identical to the logic of NoiseSocket, which is because I only made it through the process by writing it side-by-side with NoiseSocket +In particular I took all the locking logic from NoiseSocket, which was important and seemed really hard to get right so I started with theirs and sort of re-factored it into what I needed to satisfy the interfaces +The specific flavor of Noise it's using is Noise IK +My Noise transport will be able to act as a net.Conn and a net.Listener so it should be easy to write a test app that just "echoes" something soon +I plan to do that(Implement as a standard Go interface) with NTCP2 as well, and would like to something similar for SSU2(which would be a different interface, net.PacketConn) +All the interesting stuff is happening in `lib/transport/noise/*.go` right now From 0fcded4c5167e98d55b1f61384700f7726cea45f Mon Sep 17 00:00:00 2001 From: idk Date: Sun, 13 Nov 2022 22:24:31 -0500 Subject: [PATCH 05/94] check in more noise handshake missing pieces --- lib/transport/noise/client_handshake.go | 6 ++-- lib/transport/noise/client_session.go | 13 +++++++++ lib/transport/noise/noise_constants.go | 37 +++++++++++++++++++++++++ lib/transport/noise/session.go | 13 +++++++++ lib/transport/noise/transport.go | 16 ++++------- 5 files changed, 71 insertions(+), 14 deletions(-) create mode 100644 lib/transport/noise/noise_constants.go diff --git a/lib/transport/noise/client_handshake.go b/lib/transport/noise/client_handshake.go index 8d664bd..b93c8ae 100644 --- a/lib/transport/noise/client_handshake.go +++ b/lib/transport/noise/client_handshake.go @@ -18,7 +18,7 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, } var pattern noise.HandshakePattern negData = make([]byte, 6) - copy(negData, negotiationData) + copy(negData, initNegotiationData(nil)) pattern = noise.HandshakeIK negData[5] = NOISE_PATTERN_IK var random io.Reader @@ -55,7 +55,7 @@ func (c *NoiseSession) RunClientHandshake() error { state *noise.HandshakeState err error ) - if negData, msg, state, err = ComposeInitiatorHandshakeMessage(c.StaticKey, nil, nil, nil); err != nil { + if negData, msg, state, err = ComposeInitiatorHandshakeMessage(c.DHKey, nil, nil, nil); err != nil { return err } if _, err = c.Write(negData); err != nil { @@ -80,7 +80,7 @@ func (c *NoiseSession) RunClientHandshake() error { // cannot reuse msg for read, need another buf inBlock := c.NoiseTransport.newBlock() inBlock.reserve(len(msg))*/ - var payload int + var payload []byte payload, c.CipherState, c.NoiseTransport.CipherState, err = state.ReadMessage(inBlock.data, msg) /*if err != nil { c.NoiseTransport.freeBlock(inBlock) diff --git a/lib/transport/noise/client_session.go b/lib/transport/noise/client_session.go index 6799b3f..c0043b8 100644 --- a/lib/transport/noise/client_session.go +++ b/lib/transport/noise/client_session.go @@ -1,6 +1,7 @@ package noise import ( + "encoding/binary" "errors" "sync/atomic" @@ -73,3 +74,15 @@ func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { } return n, nil } + +func initNegotiationData(negotiationData []byte) []byte { + if negotiationData != nil { + return negotiationData + } + negotiationData = make([]byte, 6) + binary.BigEndian.PutUint16(negotiationData, 1) //version + negotiationData[2] = NOISE_DH_CURVE25519 + negotiationData[3] = NOISE_CIPHER_AESGCM + negotiationData[4] = NOISE_HASH_BLAKE2b + return negotiationData +} diff --git a/lib/transport/noise/noise_constants.go b/lib/transport/noise/noise_constants.go new file mode 100644 index 0000000..e565a4d --- /dev/null +++ b/lib/transport/noise/noise_constants.go @@ -0,0 +1,37 @@ +package noise + +import "github.com/flynn/noise" + +const ( + NOISE_DH_CURVE25519 = 1 + + NOISE_CIPHER_CHACHAPOLY = 1 + NOISE_CIPHER_AESGCM = 2 + + NOISE_HASH_BLAKE2s = 1 + NOISE_HASH_BLAKE2b = 2 + NOISE_HASH_SHA256 = 3 + NOISE_HASH_SHA512 = 4 + + NOISE_PATTERN_XX = 9 + NOISE_PATTERN_IK = 14 + + uint16Size = 2 // uint16 takes 2 bytes +) + +var ciphers = map[byte]noise.CipherFunc{ + NOISE_CIPHER_CHACHAPOLY: noise.CipherChaChaPoly, + NOISE_CIPHER_AESGCM: noise.CipherAESGCM, +} + +var hashes = map[byte]noise.HashFunc{ + NOISE_HASH_BLAKE2s: noise.HashBLAKE2s, + NOISE_HASH_BLAKE2b: noise.HashBLAKE2b, + NOISE_HASH_SHA256: noise.HashSHA256, + NOISE_HASH_SHA512: noise.HashSHA512, +} + +var patterns = map[byte]noise.HandshakePattern{ + NOISE_PATTERN_XX: noise.HandshakeXX, + NOISE_PATTERN_IK: noise.HandshakeIK, +} diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index 2088633..da012f3 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -23,6 +23,8 @@ type NoiseSession struct { sync.Mutex *sync.Cond *NoiseTransport + noise.DHKey + VerifyCallback VerifyCallbackFunc handshakeBuffer bytes.Buffer activeCall int32 handshakeComplete bool @@ -78,6 +80,17 @@ func (s *NoiseSession) Close() error { return nil } +func (c *NoiseSession) processCallback(publicKey []byte, payload []byte) error { + if c.VerifyCallback == nil { + return nil + } + + err := c.VerifyCallback(publicKey, payload) + return err +} + +type VerifyCallbackFunc func(publicKey []byte, data []byte) error + func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSession, error) { socket, err := DialNoise("noise", ri) if err != nil { diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index 33203ac..df599c4 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -25,10 +25,6 @@ type NoiseTransport struct { sync.Mutex Listener net.Listener peerConnections map[data.Hash]transport.TransportSession -<<<<<<< HEAD - netSocket net.Listener -======= ->>>>>>> 8d631239b7559bf5f65b5e1e6872219d156efa8b } var exampleNoiseTransport transport.Transport = &NoiseTransport{} @@ -55,8 +51,8 @@ func (noopt *NoiseTransport) Name() string { // 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) { - noopt.routerIdentity = ident - if noopt.netSocket == nil { + noopt.RouterIdentity = ident + if noopt.Listener == nil { log.WithFields(log.Fields{ "at": "(NoiseTransport) SetIdentity", "reason": "network socket is null", @@ -79,11 +75,9 @@ func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (tran if t, ok := noopt.peerConnections[hash]; ok { return t, nil } - conn, err := noopt.Accept() - if err == nil { - if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo, conn); err != nil { - return noopt.peerConnections[hash], err - } + var err error + if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo); err != nil { + return noopt.peerConnections[hash], err } return nil, err } From dab108c270bacedd2ddc0fb6d5be25906063101a Mon Sep 17 00:00:00 2001 From: idk Date: Sun, 13 Nov 2022 23:46:57 -0500 Subject: [PATCH 06/94] Client=>Outgoing --- .../noise/{client_handshake.go => outgoing_handshake.go} | 6 +++--- .../noise/{client_session.go => outgoing_session.go} | 2 +- lib/transport/noise/session.go | 5 +++++ 3 files changed, 9 insertions(+), 4 deletions(-) rename lib/transport/noise/{client_handshake.go => outgoing_handshake.go} (95%) rename lib/transport/noise/{client_session.go => outgoing_session.go} (97%) diff --git a/lib/transport/noise/client_handshake.go b/lib/transport/noise/outgoing_handshake.go similarity index 95% rename from lib/transport/noise/client_handshake.go rename to lib/transport/noise/outgoing_handshake.go index b93c8ae..6967a89 100644 --- a/lib/transport/noise/client_handshake.go +++ b/lib/transport/noise/outgoing_handshake.go @@ -30,7 +30,7 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, prologue := make([]byte, 2, uint16Size+len(negData)) binary.BigEndian.PutUint16(prologue, uint16(len(negData))) prologue = append(prologue, negData...) - prologue = append(initString, prologue...) + //prologue = append(initString, prologue...) state, err = noise.NewHandshakeState(noise.Config{ StaticKeypair: s, Initiator: true, @@ -49,7 +49,7 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, return } -func (c *NoiseSession) RunClientHandshake() error { +func (c *NoiseSession) RunIncomingHandshake() error { var ( negData, msg []byte state *noise.HandshakeState @@ -109,7 +109,7 @@ func (c *NoiseSession) RunClientHandshake() error { c.freeBlock(b) if c.CipherState == nil || c.NoiseTransport.CipherState == nil { log.WithFields(log.Fields{ - "at": "(NoiseSession) RunClientHandshake", + "at": "(NoiseSession) RunIncomingHandshake", "reason": "unsupported session", }).Error("unsupported session") return errors.New("unsupported session") diff --git a/lib/transport/noise/client_session.go b/lib/transport/noise/outgoing_session.go similarity index 97% rename from lib/transport/noise/client_session.go rename to lib/transport/noise/outgoing_session.go index c0043b8..4ed1b45 100644 --- a/lib/transport/noise/client_session.go +++ b/lib/transport/noise/outgoing_session.go @@ -24,7 +24,7 @@ func (c *NoiseSession) Write(b []byte) (int, error) { break } } - if err := c.RunClientHandshake(); err != nil { + if err := c.RunIncomingHandshake(); err != nil { return 0, err } c.Mutex.Lock() diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index da012f3..567fd23 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -89,6 +89,11 @@ func (c *NoiseSession) processCallback(publicKey []byte, payload []byte) error { return err } +// newBlock allocates a new packet, from hc's free list if possible. +func (h *NoiseSession) newBlock() *buffer { + return new(buffer) +} + type VerifyCallbackFunc func(publicKey []byte, data []byte) error func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSession, error) { From 0419665d7b05dfcb06364854c59a09b24c413377 Mon Sep 17 00:00:00 2001 From: idk Date: Mon, 14 Nov 2022 00:10:58 -0500 Subject: [PATCH 07/94] use separate incoming and outgoing queues --- lib/transport/noise/handshake.go | 2 +- lib/transport/noise/noise_constants.go | 9 ++++-- lib/transport/noise/outgoing_handshake.go | 28 ++++++++++--------- lib/transport/noise/session.go | 17 ++++++----- .../{outgoing_session.go => write_session.go} | 2 +- 5 files changed, 34 insertions(+), 24 deletions(-) rename lib/transport/noise/{outgoing_session.go => write_session.go} (97%) diff --git a/lib/transport/noise/handshake.go b/lib/transport/noise/handshake.go index 59cc91a..ec9e968 100644 --- a/lib/transport/noise/handshake.go +++ b/lib/transport/noise/handshake.go @@ -30,7 +30,7 @@ func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error { defer session.(*NoiseSession).Mutex.Unlock() c.Mutex.Lock() // if c.config.isClient { - if err := session.(*NoiseSession).RunClientHandshake(); err != nil { + if err := session.(*NoiseSession).RunOutgoingHandshake(); err != nil { return err } // Wake any other goroutines that are waiting for this handshake to diff --git a/lib/transport/noise/noise_constants.go b/lib/transport/noise/noise_constants.go index e565a4d..1ab677c 100644 --- a/lib/transport/noise/noise_constants.go +++ b/lib/transport/noise/noise_constants.go @@ -1,6 +1,10 @@ package noise -import "github.com/flynn/noise" +import ( + "math" + + "github.com/flynn/noise" +) const ( NOISE_DH_CURVE25519 = 1 @@ -16,7 +20,8 @@ const ( NOISE_PATTERN_XX = 9 NOISE_PATTERN_IK = 14 - uint16Size = 2 // uint16 takes 2 bytes + uint16Size = 2 // uint16 takes 2 bytes + MaxPayloadSize = math.MaxUint16 - 16 /*mac size*/ - uint16Size /*data len*/ ) var ciphers = map[byte]noise.CipherFunc{ diff --git a/lib/transport/noise/outgoing_handshake.go b/lib/transport/noise/outgoing_handshake.go index 6967a89..f739702 100644 --- a/lib/transport/noise/outgoing_handshake.go +++ b/lib/transport/noise/outgoing_handshake.go @@ -49,7 +49,7 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, return } -func (c *NoiseSession) RunIncomingHandshake() error { +func (c *NoiseSession) RunOutgoingHandshake() error { var ( negData, msg []byte state *noise.HandshakeState @@ -65,10 +65,12 @@ func (c *NoiseSession) RunIncomingHandshake() error { return err } //read negotiation data - /*if err := c.readPacket(); err != nil { + if i2np, err := c.ReadNextI2NP(); err != nil { return err + } else { + c.RecvQueue.Enqueue(i2np) } - negotiationData := c.handshakeBuffer.Next(c.handshakeBuffer.Len()) + /*negotiationData := c.handshakeBuffer.Next(c.handshakeBuffer.Len()) //read noise message if err := c.readPacket(); err != nil { return err @@ -76,21 +78,21 @@ func (c *NoiseSession) RunIncomingHandshake() error { msg = c.handshakeBuffer.Next(c.handshakeBuffer.Len()) if len(negotiationData) != 0 || len(msg) == 0 { return errors.New("Server returned error") - } - // cannot reuse msg for read, need another buf - inBlock := c.NoiseTransport.newBlock() - inBlock.reserve(len(msg))*/ + }*/ + //cannot reuse msg for read, need another buf + inBlock := newBlock() + //inBlock.reserve(len(msg)) var payload []byte - payload, c.CipherState, c.NoiseTransport.CipherState, err = state.ReadMessage(inBlock.data, msg) + payload, c.CipherState, c.NoiseTransport.CipherState, err = state.ReadMessage(inBlock, msg) + if err != nil { + //c.NoiseTransport.freeBlock(inBlock) + return err + } + err = c.processCallback(state.PeerStatic(), payload) /*if err != nil { c.NoiseTransport.freeBlock(inBlock) return err }*/ - err = c.processCallback(state.PeerStatic(), payload) - if err != nil { - c.NoiseTransport.freeBlock(inBlock) - return err - } /*c.NoiseTransport.freeBlock(inBlock) if c.CipherState == nil && c.NoiseTransport.CipherState == nil { b := c.newBlock() diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index 567fd23..bb59fe7 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -17,13 +17,14 @@ import ( ) type NoiseSession struct { - *cb.Queue router_info.RouterInfo *noise.CipherState sync.Mutex *sync.Cond *NoiseTransport noise.DHKey + RecvQueue *cb.Queue + SendQueue *cb.Queue VerifyCallback VerifyCallbackFunc handshakeBuffer bytes.Buffer activeCall int32 @@ -64,11 +65,11 @@ func (s *NoiseSession) LocalAddr() net.Addr { } func (s *NoiseSession) QueueSendI2NP(msg i2np.I2NPMessage) { - s.Queue.Enqueue(msg) + s.SendQueue.Enqueue(msg) } func (s *NoiseSession) SendQueueSize() int { - return s.Queue.Size() + return s.SendQueue.Size() } func (s *NoiseSession) ReadNextI2NP() (i2np.I2NPMessage, error) { @@ -76,7 +77,8 @@ func (s *NoiseSession) ReadNextI2NP() (i2np.I2NPMessage, error) { } func (s *NoiseSession) Close() error { - s.Queue.Clear() + s.SendQueue.Clear() + s.RecvQueue.Clear() return nil } @@ -90,8 +92,8 @@ func (c *NoiseSession) processCallback(publicKey []byte, payload []byte) error { } // newBlock allocates a new packet, from hc's free list if possible. -func (h *NoiseSession) newBlock() *buffer { - return new(buffer) +func newBlock() []byte { + return make([]byte, MaxPayloadSize) } type VerifyCallbackFunc func(publicKey []byte, data []byte) error @@ -102,7 +104,8 @@ func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSes return nil, err } return &NoiseSession{ - Queue: cb.New(1024), + SendQueue: cb.New(1024), + RecvQueue: cb.New(1024), RouterInfo: ri, Conn: socket, }, nil diff --git a/lib/transport/noise/outgoing_session.go b/lib/transport/noise/write_session.go similarity index 97% rename from lib/transport/noise/outgoing_session.go rename to lib/transport/noise/write_session.go index 4ed1b45..a4e30e2 100644 --- a/lib/transport/noise/outgoing_session.go +++ b/lib/transport/noise/write_session.go @@ -24,7 +24,7 @@ func (c *NoiseSession) Write(b []byte) (int, error) { break } } - if err := c.RunIncomingHandshake(); err != nil { + if err := c.RunOutgoingHandshake(); err != nil { return 0, err } c.Mutex.Lock() From 116e22f8da1bdccd22df4efbe1326fff70d4e0a3 Mon Sep 17 00:00:00 2001 From: idk Date: Mon, 12 Dec 2022 17:44:43 +0000 Subject: [PATCH 08/94] Try to figure out how to implement the pieces I'm still missing from the Noise handshake, but I think that I probably need to redo it again anyway --- PASTA.md | 20 +++++++----- lib/common/router_address/router_address.go | 16 +++++----- lib/common/router_info/router_info.go | 27 ++++++++++++++++ lib/transport/noise/handshake.go | 19 +++++++++--- lib/transport/noise/noise_constants.go | 16 +++------- lib/transport/noise/outgoing_handshake.go | 23 ++++++-------- lib/transport/noise/session.go | 23 +++++++------- lib/transport/noise/transport.go | 6 +++- lib/transport/noise/transport_test.go | 17 ++++++++++- lib/transport/noise/write_session.go | 8 ++--- lib/transport/ntcp/constants.go | 34 +++++++++++++++++++++ lib/transport/ntcp/session.go | 5 +-- lib/transport/ntcp/transport.go | 7 +++-- 13 files changed, 152 insertions(+), 69 deletions(-) create mode 100644 lib/transport/ntcp/constants.go diff --git a/PASTA.md b/PASTA.md index db01fbf..1369fcd 100644 --- a/PASTA.md +++ b/PASTA.md @@ -1,10 +1,16 @@ Weekly notes about what I'm working on ====================================== -I made a ton of progress on Noise last week, I've got a fully working handshake and I think I'll be able to send an I2NP message to another Go Transport soon with a Go TransportSession -The logic of my Noise transport is basically identical to the logic of NoiseSocket, which is because I only made it through the process by writing it side-by-side with NoiseSocket -In particular I took all the locking logic from NoiseSocket, which was important and seemed really hard to get right so I started with theirs and sort of re-factored it into what I needed to satisfy the interfaces -The specific flavor of Noise it's using is Noise IK -My Noise transport will be able to act as a net.Conn and a net.Listener so it should be easy to write a test app that just "echoes" something soon -I plan to do that(Implement as a standard Go interface) with NTCP2 as well, and would like to something similar for SSU2(which would be a different interface, net.PacketConn) -All the interesting stuff is happening in `lib/transport/noise/*.go` right now +I finally got back to work on go-i2p last Friday, continuing work on the Noise transport(also enhanced marek's privs as a reddit mod which has been helpful, also the Dread community does appear to have begun to step a little re: onboarding eachother) +I can now make a socket, instantiate a noise transport using the socket, and begin to use it to manage "incoming" and "outgoing" handshakes. +They don't complete yet, still working on that, but it's more like debugging now and less figuring out how to actually do it, I more or less know where the pieces go now +I'm beginning to notice drawbacks of what I've done here already, I think noiseSocket is intended at times as example of a way to use flynn/noise which is not exactly like I would do it or how a P2P application needs to do it +Some of the functions are very long and hard to break down, and they use a different Noise flavor than NTCP2 by default, so I'm breaking things down into steps until I have exactly one step of a Noise handshake, exactly one function +Which should finally give me what I've been hoping for all along, an interface where I can modify steps(i.e. add padding, eventually turn it into NTCP2) by instantiating it with different versions of that function, so I get to think about reusability now +I'm going to attempt to ask a question I don't quite know how to ask yet, and maybe won't know the answer until I try it out for myself: +Supposing: +0. Go network structures can be "nested" if they implement the common interface(`net.Conn`, `net.PacketConn`), and use the common interface to store the information about the socket in their implmentation, and only use the functions of the common interface(This is true) +1. That I can instantiate this Noise-framework Transport struct with functions to modify the process in a granular enough way that turning it into NTCP2 is a matter of writing a few custom functions and plugging them in to an instance of the struct(Sort of like what you would do with inheritance)(which I think is true) +2. that I can instantiate it with both a `net.Conn(TCP Socket interface)` and a `net.PacketConn(UDP Socket interface)` because I only use the common features of those 2 interfaces, (Which isn't true yet but I'm thinking about how to do it) +Does that potential definition of a moddable Noise-over-many-transports library mean that I can approach SSU2 mostly in terms of connection management and peer testing, because the crypto would be similar enough to NTCP2 that I could re-use the custom functions? +I'll find out the hard way eventually the first time I have to do it with SSU2, but it would be exciting to have come up with a design that has accelerating returns in such a way. \ No newline at end of file diff --git a/lib/common/router_address/router_address.go b/lib/common/router_address/router_address.go index 4462f10..36a62d2 100644 --- a/lib/common/router_address/router_address.go +++ b/lib/common/router_address/router_address.go @@ -65,7 +65,7 @@ options :: Mapping type RouterAddress struct { cost *Integer expiration *Date - transport_style *I2PString + Transport_Style *I2PString options *Mapping parserErr error } @@ -75,11 +75,11 @@ func (router_address RouterAddress) Bytes() []byte { bytes := make([]byte, 0) bytes = append(bytes, router_address.cost.Bytes()...) bytes = append(bytes, router_address.expiration.Bytes()...) - strData, err := router_address.transport_style.Data() + strData, err := router_address.Transport_Style.Data() if err != nil { log.WithFields(log.Fields{ "error": err, - }).Error("RouterAddress.Bytes: error getting transport_style bytes") + }).Error("RouterAddress.Bytes: error getting Transport_Style bytes") } else { bytes = append(bytes, strData...) } @@ -99,7 +99,7 @@ func (router_address RouterAddress) Expiration() Date { // TransportStyle returns the transport style for this RouterAddress as an I2PString. func (router_address RouterAddress) TransportStyle() I2PString { - return *router_address.transport_style + return *router_address.Transport_Style } // Options returns the options for this RouterAddress as an I2P Mapping. @@ -107,9 +107,7 @@ func (router_address RouterAddress) Options() Mapping { return *router_address.options } -// // Check if the RouterAddress is empty or if it is too small to contain valid data. -// func (router_address RouterAddress) checkValid() (err error, exit bool) { /*addr_len := len(router_address) exit = false @@ -161,12 +159,12 @@ func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []b }).Error("error parsing RouterAddress") router_address.parserErr = err } - transport_style, remainder, err := NewI2PString(remainder) - router_address.transport_style = transport_style + Transport_Style, remainder, err := NewI2PString(remainder) + router_address.Transport_Style = Transport_Style if err != nil { log.WithFields(log.Fields{ "at": "(RouterAddress) ReadNewRouterAddress", - "reason": "error parsing transport_style", + "reason": "error parsing Transport_Style", }).Error("error parsing RouterAddress") router_address.parserErr = err } diff --git a/lib/common/router_info/router_info.go b/lib/common/router_info/router_info.go index 2cd353b..945019d 100644 --- a/lib/common/router_info/router_info.go +++ b/lib/common/router_info/router_info.go @@ -3,6 +3,8 @@ package router_info import ( "errors" + "net" + "strings" . "github.com/go-i2p/go-i2p/lib/common/data" . "github.com/go-i2p/go-i2p/lib/common/router_address" @@ -106,6 +108,8 @@ type RouterInfo struct { signature *Signature } +var routerInfoTest net.Addr = &RouterInfo{} + // Bytes returns the RouterInfo as a []byte suitable for writing to a stream. func (router_info RouterInfo) Bytes() ([]byte, error) { var err error @@ -124,6 +128,29 @@ func (router_info RouterInfo) Bytes() ([]byte, error) { return bytes, err } +// Network Implements net.Addr, returns comma-separated list of transport types +func (router_info *RouterInfo) Network() string { + var str []string + for _, addr := range router_info.addresses { + t, err := addr.Transport_Style.Data() + if err != nil { + return strings.Join(str, ",") + } + str = append(str, t) + } + return strings.Join(str, ",") +} + +// String Implements net.Addr, returns router-info `Bytes` converted to a string +func (router_info *RouterInfo) String() string { + bytes, err := router_info.Bytes() + if err != nil { + // TODO handle this issue + return "" + } + return string(bytes) +} + // RouterIdentity returns the router identity as *RouterIdentity. func (router_info *RouterInfo) RouterIdentity() *RouterIdentity { return router_info.router_identity diff --git a/lib/transport/noise/handshake.go b/lib/transport/noise/handshake.go index ec9e968..607f77d 100644 --- a/lib/transport/noise/handshake.go +++ b/lib/transport/noise/handshake.go @@ -4,24 +4,33 @@ import ( "sync" "github.com/go-i2p/go-i2p/lib/common/router_info" + "github.com/go-i2p/go-i2p/lib/transport" ) -func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error { - c.Mutex.Lock() - defer c.Mutex.Unlock() +func (c *NoiseTransport) getSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) { session, err := c.GetSession(routerInfo) if err != nil { - return err + return nil, err } for { if session.(*NoiseSession).handshakeComplete { - return nil + return nil, nil } if session.(*NoiseSession).Cond == nil { break } session.(*NoiseSession).Cond.Wait() } + return session, nil +} + +func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error { + c.Mutex.Lock() + defer c.Mutex.Unlock() + session, err := c.getSession(routerInfo) + if err != nil { + return err + } // Set handshakeCond to indicate that this goroutine is committing to // running the handshake. session.(*NoiseSession).Cond = sync.NewCond(&c.Mutex) diff --git a/lib/transport/noise/noise_constants.go b/lib/transport/noise/noise_constants.go index 1ab677c..1984c57 100644 --- a/lib/transport/noise/noise_constants.go +++ b/lib/transport/noise/noise_constants.go @@ -12,13 +12,9 @@ const ( NOISE_CIPHER_CHACHAPOLY = 1 NOISE_CIPHER_AESGCM = 2 - NOISE_HASH_BLAKE2s = 1 - NOISE_HASH_BLAKE2b = 2 - NOISE_HASH_SHA256 = 3 - NOISE_HASH_SHA512 = 4 + NOISE_HASH_SHA256 = 3 - NOISE_PATTERN_XX = 9 - NOISE_PATTERN_IK = 14 + NOISE_PATTERN_XK = 11 uint16Size = 2 // uint16 takes 2 bytes MaxPayloadSize = math.MaxUint16 - 16 /*mac size*/ - uint16Size /*data len*/ @@ -30,13 +26,9 @@ var ciphers = map[byte]noise.CipherFunc{ } var hashes = map[byte]noise.HashFunc{ - NOISE_HASH_BLAKE2s: noise.HashBLAKE2s, - NOISE_HASH_BLAKE2b: noise.HashBLAKE2b, - NOISE_HASH_SHA256: noise.HashSHA256, - NOISE_HASH_SHA512: noise.HashSHA512, + NOISE_HASH_SHA256: noise.HashSHA256, } var patterns = map[byte]noise.HandshakePattern{ - NOISE_PATTERN_XX: noise.HandshakeXX, - NOISE_PATTERN_IK: noise.HandshakeIK, + NOISE_PATTERN_XK: noise.HandshakeXK, } diff --git a/lib/transport/noise/outgoing_handshake.go b/lib/transport/noise/outgoing_handshake.go index f739702..d20ad65 100644 --- a/lib/transport/noise/outgoing_handshake.go +++ b/lib/transport/noise/outgoing_handshake.go @@ -16,11 +16,10 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported") } - var pattern noise.HandshakePattern negData = make([]byte, 6) copy(negData, initNegotiationData(nil)) - pattern = noise.HandshakeIK - negData[5] = NOISE_PATTERN_IK + pattern := noise.HandshakeXK + negData[5] = NOISE_PATTERN_XK var random io.Reader if len(ePrivate) == 0 { random = rand.Reader @@ -35,7 +34,7 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, StaticKeypair: s, Initiator: true, Pattern: pattern, - CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherAESGCM, noise.HashBLAKE2b), + CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256), PeerStatic: rs, Prologue: prologue, Random: random, @@ -50,12 +49,8 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, } func (c *NoiseSession) RunOutgoingHandshake() error { - var ( - negData, msg []byte - state *noise.HandshakeState - err error - ) - if negData, msg, state, err = ComposeInitiatorHandshakeMessage(c.DHKey, nil, nil, nil); err != nil { + negData, msg, state, err := ComposeInitiatorHandshakeMessage(c.DHKey, nil, nil, nil) + if err != nil { return err } if _, err = c.Write(negData); err != nil { @@ -70,15 +65,17 @@ func (c *NoiseSession) RunOutgoingHandshake() error { } else { c.RecvQueue.Enqueue(i2np) } - /*negotiationData := c.handshakeBuffer.Next(c.handshakeBuffer.Len()) + negotiationData := c.handshakeBuffer.Next(c.handshakeBuffer.Len()) //read noise message - if err := c.readPacket(); err != nil { + if i2np, err := c.ReadNextI2NP(); err != nil { return err + } else { + c.RecvQueue.Enqueue(i2np) } msg = c.handshakeBuffer.Next(c.handshakeBuffer.Len()) if len(negotiationData) != 0 || len(msg) == 0 { return errors.New("Server returned error") - }*/ + } //cannot reuse msg for read, need another buf inBlock := newBlock() //inBlock.reserve(len(msg)) diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index bb59fe7..d9a6772 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -33,28 +33,28 @@ type NoiseSession struct { } // Read implements net.Conn -func (*NoiseSession) Read(b []byte) (n int, err error) { - panic("unimplemented") +func (noise_session *NoiseSession) Read(b []byte) (n int, err error) { + return noise_session.Conn.Read(b) } // RemoteAddr implements net.Conn -func (*NoiseSession) RemoteAddr() net.Addr { - panic("unimplemented") +func (noise_session *NoiseSession) RemoteAddr() net.Addr { + return &noise_session.RouterInfo } // SetDeadline implements net.Conn -func (*NoiseSession) SetDeadline(t time.Time) error { - panic("unimplemented") +func (noise_session *NoiseSession) SetDeadline(t time.Time) error { + return noise_session.Conn.SetDeadline(t) } // SetReadDeadline implements net.Conn -func (*NoiseSession) SetReadDeadline(t time.Time) error { - panic("unimplemented") +func (noise_session *NoiseSession) SetReadDeadline(t time.Time) error { + return noise_session.Conn.SetReadDeadline(t) } // SetWriteDeadline implements net.Conn -func (*NoiseSession) SetWriteDeadline(t time.Time) error { - panic("unimplemented") +func (noise_session *NoiseSession) SetWriteDeadline(t time.Time) error { + return noise_session.Conn.SetWriteDeadline(t) } var exampleNoiseSession transport.TransportSession = &NoiseSession{} @@ -86,7 +86,6 @@ func (c *NoiseSession) processCallback(publicKey []byte, payload []byte) error { if c.VerifyCallback == nil { return nil } - err := c.VerifyCallback(publicKey, payload) return err } @@ -120,7 +119,7 @@ func DialNoise(network string, addr router_info.RouterInfo) (net.Conn, error) { "at": "(DialNoise)", "addr": addr, }).Error("error parsing router info") - Dial("noise", string(addr.TransportStyle())) + return Dial(string(addr.TransportStyle()), "") } return nil, fmt.Errorf("No valid transport discovered.") } diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index df599c4..9d0b8b0 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -34,19 +34,23 @@ var exampleNoiseTransport transport.Transport = &NoiseTransport{} // implements net.Listener var ExampleNoiseListener net.Listener = exampleNoiseTransport +// Accept a connection on a listening socket. func (noopt *NoiseTransport) Accept() (net.Conn, error) { return noopt.Listener.Accept() } +// Addr of the transport, for now this is returning the IP:Port the transport is listening on, +// but this might actually be the router identity func (noopt *NoiseTransport) Addr() net.Addr { return noopt.Listener.Addr() } +// Name of the transport TYPE, in this case `noise` func (noopt *NoiseTransport) Name() string { return "noise" } -// Set the router identity for this transport. +// SetIdentity will set the router identity for this transport. // 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 diff --git a/lib/transport/noise/transport_test.go b/lib/transport/noise/transport_test.go index d121286..cdf972d 100644 --- a/lib/transport/noise/transport_test.go +++ b/lib/transport/noise/transport_test.go @@ -11,5 +11,20 @@ func TestTransport(t *testing.T) { t.Error(err) } nt := NewNoiseTransport(ln) - t.Log(nt.Name()) + go func() { + for { + conn, err := nt.Accept() + if err != nil { + t.Log(err) + } + conn.Write([]byte("World")) + } + }() + lnn, err := net.Listen("tcp", ":42070") + if err != nil { + t.Error(err) + } + ntt := NewNoiseTransport(lnn) + t.Log(ntt.Name()) + //ntt.GetSession() } diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index a4e30e2..508d2aa 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -44,7 +44,7 @@ func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { } } for len(data) > 0 { - /*m := len(data) + m := len(data) packet := c.InitializePacket() maxPayloadSize := c.maxPayloadSizeForWrite(packet) if m > int(maxPayloadSize) { @@ -70,7 +70,7 @@ func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { } n += m data = data[m:] - */ + } return n, nil } @@ -82,7 +82,7 @@ func initNegotiationData(negotiationData []byte) []byte { negotiationData = make([]byte, 6) binary.BigEndian.PutUint16(negotiationData, 1) //version negotiationData[2] = NOISE_DH_CURVE25519 - negotiationData[3] = NOISE_CIPHER_AESGCM - negotiationData[4] = NOISE_HASH_BLAKE2b + negotiationData[3] = NOISE_CIPHER_CHACHAPOLY + negotiationData[4] = NOISE_HASH_SHA256 return negotiationData } diff --git a/lib/transport/ntcp/constants.go b/lib/transport/ntcp/constants.go new file mode 100644 index 0000000..2086a8a --- /dev/null +++ b/lib/transport/ntcp/constants.go @@ -0,0 +1,34 @@ +package ntcp + +import ( + "math" + + "github.com/flynn/noise" +) + +const ( + NOISE_DH_CURVE25519 = 1 + + NOISE_CIPHER_CHACHAPOLY = 1 + NOISE_CIPHER_AESGCM = 2 + + NOISE_HASH_SHA256 = 3 + + NOISE_PATTERN_XK = 11 + + uint16Size = 2 // uint16 takes 2 bytes + MaxPayloadSize = math.MaxUint16 - 16 /*mac size*/ - uint16Size /*data len*/ +) + +var ciphers = map[byte]noise.CipherFunc{ + NOISE_CIPHER_CHACHAPOLY: noise.CipherChaChaPoly, + NOISE_CIPHER_AESGCM: noise.CipherAESGCM, +} + +var hashes = map[byte]noise.HashFunc{ + NOISE_HASH_SHA256: noise.HashSHA256, +} + +var patterns = map[byte]noise.HandshakePattern{ + NOISE_PATTERN_XK: noise.HandshakeXK, +} diff --git a/lib/transport/ntcp/session.go b/lib/transport/ntcp/session.go index cb36582..d251c7b 100644 --- a/lib/transport/ntcp/session.go +++ b/lib/transport/ntcp/session.go @@ -1,6 +1,7 @@ package ntcp +import "github.com/go-i2p/go-i2p/lib/transport/noise" + // Session implements TransportSession // An established transport session -type Session struct { -} +type Session noise.NoiseSession diff --git a/lib/transport/ntcp/transport.go b/lib/transport/ntcp/transport.go index 69a4f15..03fcbfd 100644 --- a/lib/transport/ntcp/transport.go +++ b/lib/transport/ntcp/transport.go @@ -1,5 +1,7 @@ package ntcp +import "github.com/go-i2p/go-i2p/lib/transport/noise" + /** * https://geti2p.net/spec/ntcp2 **/ @@ -10,6 +12,5 @@ const ( NTCP_MESSAGE_MAX_SIZE = 65537 ) -// Transport is an ntcp transport implementing transport.Transport interface -type Transport struct { -} +// NTCPTransport is an ntcp transport implementing transport.Transport interface +type NTCPTransport noise.NoiseTransport From 65febb5dcf226517efc7a4d24fb75e25ae277eb9 Mon Sep 17 00:00:00 2001 From: idk Date: Thu, 15 Dec 2022 23:52:05 +0000 Subject: [PATCH 09/94] Work on organizing this Noise over TCP Socket stuff --- lib/transport/noise/handshake.go | 20 +----- lib/transport/noise/i2np.go | 15 ++++ lib/transport/noise/incoming_handshake.go | 64 +++++++++++++++++ lib/transport/noise/noise_constants.go | 18 ++++- lib/transport/noise/outgoing_handshake.go | 62 +---------------- lib/transport/noise/read_session.go | 84 +++++++++++++++++++++++ lib/transport/noise/session.go | 67 +++++------------- lib/transport/noise/transport.go | 21 +++++- lib/transport/noise/write_session.go | 74 ++++++++++---------- 9 files changed, 253 insertions(+), 172 deletions(-) create mode 100644 lib/transport/noise/i2np.go create mode 100644 lib/transport/noise/incoming_handshake.go create mode 100644 lib/transport/noise/read_session.go diff --git a/lib/transport/noise/handshake.go b/lib/transport/noise/handshake.go index 607f77d..a5d7c55 100644 --- a/lib/transport/noise/handshake.go +++ b/lib/transport/noise/handshake.go @@ -4,26 +4,8 @@ import ( "sync" "github.com/go-i2p/go-i2p/lib/common/router_info" - "github.com/go-i2p/go-i2p/lib/transport" ) -func (c *NoiseTransport) getSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) { - session, err := c.GetSession(routerInfo) - if err != nil { - return nil, err - } - for { - if session.(*NoiseSession).handshakeComplete { - return nil, nil - } - if session.(*NoiseSession).Cond == nil { - break - } - session.(*NoiseSession).Cond.Wait() - } - return session, nil -} - func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error { c.Mutex.Lock() defer c.Mutex.Unlock() @@ -38,7 +20,7 @@ func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error { session.(*NoiseSession).Mutex.Lock() defer session.(*NoiseSession).Mutex.Unlock() c.Mutex.Lock() - // if c.config.isClient { + if err := session.(*NoiseSession).RunOutgoingHandshake(); err != nil { return err } diff --git a/lib/transport/noise/i2np.go b/lib/transport/noise/i2np.go new file mode 100644 index 0000000..41bd980 --- /dev/null +++ b/lib/transport/noise/i2np.go @@ -0,0 +1,15 @@ +package noise + +import "github.com/go-i2p/go-i2p/lib/i2np" + +func (s *NoiseSession) QueueSendI2NP(msg i2np.I2NPMessage) { + s.SendQueue.Enqueue(msg) +} + +func (s *NoiseSession) SendQueueSize() int { + return s.SendQueue.Size() +} + +func (s *NoiseSession) ReadNextI2NP() (i2np.I2NPMessage, error) { + return i2np.I2NPMessage{}, nil +} diff --git a/lib/transport/noise/incoming_handshake.go b/lib/transport/noise/incoming_handshake.go new file mode 100644 index 0000000..80d8835 --- /dev/null +++ b/lib/transport/noise/incoming_handshake.go @@ -0,0 +1,64 @@ +package noise + +import ( + "bytes" + "crypto/rand" + "encoding/binary" + "errors" + "io" + "log" + + "github.com/flynn/noise" +) + +func ComposeRecieverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) { + if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() { + return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported") + } + negData = make([]byte, 6) + copy(negData, initNegotiationData(nil)) + pattern := noise.HandshakeXK + negData[5] = NOISE_PATTERN_XK + var random io.Reader + if len(ePrivate) == 0 { + random = rand.Reader + } else { + random = bytes.NewBuffer(ePrivate) + } + prologue := make([]byte, 2, uint16Size+len(negData)) + binary.BigEndian.PutUint16(prologue, uint16(len(negData))) + prologue = append(prologue, negData...) + //prologue = append(initString, prologue...) + state, err = noise.NewHandshakeState(noise.Config{ + StaticKeypair: s, + Initiator: false, + Pattern: pattern, + CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256), + PeerStatic: rs, + Prologue: prologue, + Random: random, + }) + if err != nil { + return + } + padBuf := make([]byte, 2+len(payload)) + copy(padBuf[2:], payload) + msg, _, _, err = state.WriteMessage(msg, padBuf) + return +} + +func (c *NoiseSession) RunIncomingHandshake() error { + negData, msg, state, err := ComposeRecieverHandshakeMessage(c.HandKey, nil, nil, nil) + if err != nil { + return err + } + if _, err = c.Write(negData); err != nil { + return err + } + if _, err = c.Write(msg); err != nil { + return err + } + log.Println(state) + c.handshakeComplete = true + return nil +} diff --git a/lib/transport/noise/noise_constants.go b/lib/transport/noise/noise_constants.go index 1984c57..7fdab54 100644 --- a/lib/transport/noise/noise_constants.go +++ b/lib/transport/noise/noise_constants.go @@ -1,7 +1,7 @@ package noise import ( - "math" + "encoding/binary" "github.com/flynn/noise" ) @@ -16,8 +16,8 @@ const ( NOISE_PATTERN_XK = 11 - uint16Size = 2 // uint16 takes 2 bytes - MaxPayloadSize = math.MaxUint16 - 16 /*mac size*/ - uint16Size /*data len*/ + uint16Size = 2 // uint16 takes 2 bytes + MaxPayloadSize = 65537 ) var ciphers = map[byte]noise.CipherFunc{ @@ -32,3 +32,15 @@ var hashes = map[byte]noise.HashFunc{ var patterns = map[byte]noise.HandshakePattern{ NOISE_PATTERN_XK: noise.HandshakeXK, } + +func initNegotiationData(negotiationData []byte) []byte { + if negotiationData != nil { + return negotiationData + } + negotiationData = make([]byte, 6) + binary.BigEndian.PutUint16(negotiationData, 1) //version + negotiationData[2] = NOISE_DH_CURVE25519 + negotiationData[3] = NOISE_CIPHER_CHACHAPOLY + negotiationData[4] = NOISE_HASH_SHA256 + return negotiationData +} diff --git a/lib/transport/noise/outgoing_handshake.go b/lib/transport/noise/outgoing_handshake.go index d20ad65..5786924 100644 --- a/lib/transport/noise/outgoing_handshake.go +++ b/lib/transport/noise/outgoing_handshake.go @@ -6,6 +6,7 @@ import ( "encoding/binary" "errors" "io" + "log" "github.com/flynn/noise" ) @@ -49,7 +50,7 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, } func (c *NoiseSession) RunOutgoingHandshake() error { - negData, msg, state, err := ComposeInitiatorHandshakeMessage(c.DHKey, nil, nil, nil) + negData, msg, state, err := ComposeInitiatorHandshakeMessage(c.HandKey, nil, nil, nil) if err != nil { return err } @@ -59,64 +60,7 @@ func (c *NoiseSession) RunOutgoingHandshake() error { if _, err = c.Write(msg); err != nil { return err } - //read negotiation data - if i2np, err := c.ReadNextI2NP(); err != nil { - return err - } else { - c.RecvQueue.Enqueue(i2np) - } - negotiationData := c.handshakeBuffer.Next(c.handshakeBuffer.Len()) - //read noise message - if i2np, err := c.ReadNextI2NP(); err != nil { - return err - } else { - c.RecvQueue.Enqueue(i2np) - } - msg = c.handshakeBuffer.Next(c.handshakeBuffer.Len()) - if len(negotiationData) != 0 || len(msg) == 0 { - return errors.New("Server returned error") - } - //cannot reuse msg for read, need another buf - inBlock := newBlock() - //inBlock.reserve(len(msg)) - var payload []byte - payload, c.CipherState, c.NoiseTransport.CipherState, err = state.ReadMessage(inBlock, msg) - if err != nil { - //c.NoiseTransport.freeBlock(inBlock) - return err - } - err = c.processCallback(state.PeerStatic(), payload) - /*if err != nil { - c.NoiseTransport.freeBlock(inBlock) - return err - }*/ - /*c.NoiseTransport.freeBlock(inBlock) - if c.CipherState == nil && c.NoiseTransport.CipherState == nil { - b := c.newBlock() - if b.data, c.CipherState, c.NoiseTransport.CipherState, err = state.WriteMessage(b.data, pad(c.config.Payload)); err != nil { - c.freeBlock(b) - return err - } - if _, err = c.Write(nil); err != nil { - c.freeBlock(b) - return err - } - if _, err = c.Write(b.data); err != nil { - c.freeBlock(b) - return err - } - c.freeBlock(b) - if c.CipherState == nil || c.NoiseTransport.CipherState == nil { - log.WithFields(log.Fields{ - "at": "(NoiseSession) RunIncomingHandshake", - "reason": "unsupported session", - }).Error("unsupported session") - return errors.New("unsupported session") - } - } - */ - //c.in.padding, c.out.padding = c.config.Padding, c.config.Padding - //c.channelBinding = state.ChannelBinding() + log.Println(state) c.handshakeComplete = true return nil } diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go new file mode 100644 index 0000000..5510311 --- /dev/null +++ b/lib/transport/noise/read_session.go @@ -0,0 +1,84 @@ +package noise + +import ( + "errors" + "sync/atomic" + + log "github.com/sirupsen/logrus" +) + +func (c *NoiseSession) Read(b []byte) (int, error) { + // interlock with Close below + for { + x := atomic.LoadInt32(&c.activeCall) + if x&1 != 0 { + log.WithFields(log.Fields{ + "at": "(NoiseSession) Read", + "reason": "session is closed", + }).Error("session is closed") + return 0, errors.New("session is closed") + } + if atomic.CompareAndSwapInt32(&c.activeCall, x, x+2) { + defer atomic.AddInt32(&c.activeCall, -2) + break + } + } + if !c.handshakeComplete { + if err := c.RunIncomingHandshake(); err != nil { + return 0, err + } + } + c.Mutex.Lock() + defer c.Mutex.Unlock() + if !c.handshakeComplete { + return 0, errors.New("internal error") + } + n, err := c.readPacketLocked(b) + return n, err +} + +func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { + m := len(data) + /*packet := c.InitializePacket() + maxPayloadSize := c.maxPayloadSizeForRead(packet) + if m > int(maxPayloadSize) { + m = int(maxPayloadSize) + } + if c.CipherState != nil { + ////fmt.Println("writing encrypted packet:", m) + packet.reserve(uint16Size + uint16Size + m + macSize) + packet.resize(uint16Size + uint16Size + m) + copy(packet.data[uint16Size+uint16Size:], data[:m]) + binary.BigEndian.PutUint16(packet.data[uint16Size:], uint16(m)) + //fmt.Println("encrypt size", uint16(m)) + } else { + packet.resize(len(packet.data) + len(data)) + copy(packet.data[uint16Size:len(packet.data)], data[:m]) + binary.BigEndian.PutUint16(packet.data, uint16(len(data))) + } + b := c.encryptIfNeeded(packet)*/ + //c.freeBlock(packet) + return m, data, nil +} + +func (c *NoiseSession) readPacketLocked(data []byte) (int, error) { + var n int + if len(data) == 0 { //special case to answer when everything is ok during handshake + if _, err := c.Conn.Read(make([]byte, 2)); err != nil { + return 0, err + } + } + for len(data) > 0 { + m, b, err := c.encryptPacket(data) + if err != nil { + return 0, err + } + if n, err := c.Conn.Read(b); err != nil { + return n, err + } else { + n += m + data = data[m:] + } + } + return n, nil +} diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index d9a6772..8938039 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -9,10 +9,8 @@ import ( cb "github.com/emirpasic/gods/queues/circularbuffer" "github.com/flynn/noise" - log "github.com/sirupsen/logrus" "github.com/go-i2p/go-i2p/lib/common/router_info" - "github.com/go-i2p/go-i2p/lib/i2np" "github.com/go-i2p/go-i2p/lib/transport" ) @@ -21,10 +19,12 @@ type NoiseSession struct { *noise.CipherState sync.Mutex *sync.Cond - *NoiseTransport - noise.DHKey + *NoiseTransport // The parent transport, which "Dialed" the connection to the peer whith whom we established the session RecvQueue *cb.Queue SendQueue *cb.Queue + SendKey noise.DHKey + RecvKey noise.DHKey + HandKey noise.DHKey VerifyCallback VerifyCallbackFunc handshakeBuffer bytes.Buffer activeCall int32 @@ -32,11 +32,6 @@ type NoiseSession struct { Conn net.Conn } -// Read implements net.Conn -func (noise_session *NoiseSession) Read(b []byte) (n int, err error) { - return noise_session.Conn.Read(b) -} - // RemoteAddr implements net.Conn func (noise_session *NoiseSession) RemoteAddr() net.Addr { return &noise_session.RouterInfo @@ -64,18 +59,6 @@ func (s *NoiseSession) LocalAddr() net.Addr { return s.Conn.LocalAddr() } -func (s *NoiseSession) QueueSendI2NP(msg i2np.I2NPMessage) { - s.SendQueue.Enqueue(msg) -} - -func (s *NoiseSession) SendQueueSize() int { - return s.SendQueue.Size() -} - -func (s *NoiseSession) ReadNextI2NP() (i2np.I2NPMessage, error) { - return i2np.I2NPMessage{}, nil -} - func (s *NoiseSession) Close() error { s.SendQueue.Clear() s.RecvQueue.Clear() @@ -98,34 +81,18 @@ func newBlock() []byte { type VerifyCallbackFunc func(publicKey []byte, data []byte) error func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSession, error) { - socket, err := DialNoise("noise", ri) - if err != nil { - return nil, err + //socket, err := DialNoise("noise", ri) + for _, addr := range ri.RouterAddresses() { + socket, err := net.Dial("tcp", string(addr.Bytes())) + if err != nil { + return nil, err + } + return &NoiseSession{ + SendQueue: cb.New(1024), + RecvQueue: cb.New(1024), + RouterInfo: ri, + Conn: socket, + }, nil } - return &NoiseSession{ - SendQueue: cb.New(1024), - RecvQueue: cb.New(1024), - RouterInfo: ri, - Conn: socket, - }, nil -} - -// DialNoise initiates a session with a remote Noise transport, using a -// routerinfo to derive the address to connect to. It doesn't have any chance of -// working yet. -func DialNoise(network string, addr router_info.RouterInfo) (net.Conn, error) { - for _, addr := range addr.RouterAddresses() { - log.WithFields(log.Fields{ - "at": "(DialNoise)", - "addr": addr, - }).Error("error parsing router info") - return Dial(string(addr.TransportStyle()), "") - } - return nil, fmt.Errorf("No valid transport discovered.") -} - -// Dial initiates a session with a remote Noise transport at a host:port -// or ip:port -func Dial(network, addr string) (net.Conn, error) { - return net.Dial("tcp", addr) + return nil, fmt.Errorf("Transport constructor error") } diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index 9d0b8b0..4302407 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -20,9 +20,9 @@ import ( ) type NoiseTransport struct { - *noise.CipherState - router_identity.RouterIdentity sync.Mutex + router_identity.RouterIdentity + *noise.CipherState Listener net.Listener peerConnections map[data.Hash]transport.TransportSession } @@ -86,6 +86,23 @@ func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (tran return nil, err } +func (c *NoiseTransport) getSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) { + session, err := c.GetSession(routerInfo) + if err != nil { + return nil, err + } + for { + if session.(*NoiseSession).handshakeComplete { + return nil, nil + } + if session.(*NoiseSession).Cond == nil { + break + } + session.(*NoiseSession).Cond.Wait() + } + return session, nil +} + // Compatable return true if a routerInfo is compatable with this transport func (noopt *NoiseTransport) Compatable(routerInfo router_info.RouterInfo) bool { _, ok := noopt.peerConnections[routerInfo.IdentHash()] diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index 508d2aa..fd5a065 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -1,7 +1,6 @@ package noise import ( - "encoding/binary" "errors" "sync/atomic" @@ -24,8 +23,10 @@ func (c *NoiseSession) Write(b []byte) (int, error) { break } } - if err := c.RunOutgoingHandshake(); err != nil { - return 0, err + if !c.handshakeComplete { + if err := c.RunOutgoingHandshake(); err != nil { + return 0, err + } } c.Mutex.Lock() defer c.Mutex.Unlock() @@ -36,6 +37,30 @@ func (c *NoiseSession) Write(b []byte) (int, error) { return n, err } +func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { + m := len(data) + /*packet := c.InitializePacket() + maxPayloadSize := c.maxPayloadSizeForWrite(packet) + if m > int(maxPayloadSize) { + m = int(maxPayloadSize) + } + if c.CipherState != nil { + ////fmt.Println("writing encrypted packet:", m) + packet.reserve(uint16Size + uint16Size + m + macSize) + packet.resize(uint16Size + uint16Size + m) + copy(packet.data[uint16Size+uint16Size:], data[:m]) + binary.BigEndian.PutUint16(packet.data[uint16Size:], uint16(m)) + //fmt.Println("encrypt size", uint16(m)) + } else { + packet.resize(len(packet.data) + len(data)) + copy(packet.data[uint16Size:len(packet.data)], data[:m]) + binary.BigEndian.PutUint16(packet.data, uint16(len(data))) + } + b := c.encryptIfNeeded(packet)*/ + //c.freeBlock(packet) + return m, data, nil +} + func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { var n int if len(data) == 0 { //special case to answer when everything is ok during handshake @@ -44,45 +69,16 @@ func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { } } for len(data) > 0 { - m := len(data) - packet := c.InitializePacket() - maxPayloadSize := c.maxPayloadSizeForWrite(packet) - if m > int(maxPayloadSize) { - m = int(maxPayloadSize) + m, b, err := c.encryptPacket(data) + if err != nil { + return 0, err } - if c.CipherState != nil { - ////fmt.Println("writing encrypted packet:", m) - packet.reserve(uint16Size + uint16Size + m + macSize) - packet.resize(uint16Size + uint16Size + m) - copy(packet.data[uint16Size+uint16Size:], data[:m]) - binary.BigEndian.PutUint16(packet.data[uint16Size:], uint16(m)) - //fmt.Println("encrypt size", uint16(m)) - } else { - packet.resize(len(packet.data) + len(data)) - copy(packet.data[uint16Size:len(packet.data)], data[:m]) - binary.BigEndian.PutUint16(packet.data, uint16(len(data))) - } - b := c.encryptIfNeeded(packet) - c.freeBlock(packet) - ////fmt.Println(hex.EncodeToString(b)) - if _, err := c.conn.Write(b); err != nil { + if n, err := c.Conn.Write(b); err != nil { return n, err + } else { + n += m + data = data[m:] } - n += m - data = data[m:] - } return n, nil } - -func initNegotiationData(negotiationData []byte) []byte { - if negotiationData != nil { - return negotiationData - } - negotiationData = make([]byte, 6) - binary.BigEndian.PutUint16(negotiationData, 1) //version - negotiationData[2] = NOISE_DH_CURVE25519 - negotiationData[3] = NOISE_CIPHER_CHACHAPOLY - negotiationData[4] = NOISE_HASH_SHA256 - return negotiationData -} From 16961abc962e4593faf1a545d53f5759aee5e890 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 3 Oct 2024 13:33:01 -0400 Subject: [PATCH 10/94] !WIP! -added error handling in TestTransport() -fixed typo to ComposeReceiverHandshakeMessage -experimental implementation of encryptPacket -added encrdecr_packet_test.go --- lib/transport/noise/encrdecr_packet_test.go | 165 ++++++++++++++++++++ lib/transport/noise/incoming_handshake.go | 4 +- lib/transport/noise/read_session.go | 12 +- lib/transport/noise/transport_test.go | 5 +- lib/transport/noise/write_session.go | 20 ++- 5 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 lib/transport/noise/encrdecr_packet_test.go diff --git a/lib/transport/noise/encrdecr_packet_test.go b/lib/transport/noise/encrdecr_packet_test.go new file mode 100644 index 0000000..678a4a6 --- /dev/null +++ b/lib/transport/noise/encrdecr_packet_test.go @@ -0,0 +1,165 @@ +package noise + +import ( + "crypto/rand" + "encoding/binary" + "github.com/flynn/noise" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestEncryptDecryptPacketOffline(t *testing.T) { + // Generate static keypairs + initiatorStatic, err := noise.DH25519.GenerateKeypair(rand.Reader) + if err != nil { + t.Fatalf("Failed to generate initiator static keypair: %v", err) + } + responderStatic, err := noise.DH25519.GenerateKeypair(rand.Reader) + if err != nil { + t.Fatalf("Failed to generate responder static keypair: %v", err) + } + + pattern := noise.HandshakeXK + cipherSuite := noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256) + + // Negotiation + negData := initNegotiationData(nil) + prologue := make([]byte, 2, uint16Size+len(negData)) + binary.BigEndian.PutUint16(prologue, uint16(len(negData))) + prologue = append(prologue, negData...) + + // Handshake + initiatorHS, err := noise.NewHandshakeState(noise.Config{ + StaticKeypair: initiatorStatic, + Initiator: true, + Pattern: pattern, + CipherSuite: cipherSuite, + Prologue: prologue, + PeerStatic: responderStatic.Public, // Must set this + }) + if err != nil { + t.Fatalf("Failed to create initiator handshake state: %v", err) + } + + responderHS, err := noise.NewHandshakeState(noise.Config{ + StaticKeypair: responderStatic, + Initiator: false, + Pattern: pattern, + CipherSuite: cipherSuite, + Prologue: prologue, + }) + if err != nil { + t.Fatalf("Failed to create responder handshake state: %v", err) + } + + var ( + initiatorSendCS *noise.CipherState + initiatorRecvCS *noise.CipherState + responderSendCS *noise.CipherState + responderRecvCS *noise.CipherState + ) + + // Simulate the handshake message exchange + + // Message 1: Initiator -> Responder + msg1, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil) + if err != nil { + t.Fatalf("Initiator failed to write handshake message 1: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Initiator should not have CipherStates after message 1") + } + + // Responder processes message 1 + _, cs0, cs1, err = responderHS.ReadMessage(nil, msg1) + if err != nil { + t.Fatalf("Responder failed to read handshake message 1: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Responder should not have CipherStates after reading message 1") + } + + // Responder writes message 2 + msg2, cs0, cs1, err := responderHS.WriteMessage(nil, nil) + if err != nil { + t.Fatalf("Responder failed to write handshake message 2: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Responder should not have CipherStates after writing message 2") + } + + // Initiator processes message 2 + _, cs0, cs1, err = initiatorHS.ReadMessage(nil, msg2) + if err != nil { + t.Fatalf("Initiator failed to read handshake message 2: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Initiator should not have CipherStates after reading message 2") + } + + // Initiator writes message 3 + msg3, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil) + if err != nil { + t.Fatalf("Initiator failed to write handshake message 3: %v", err) + } + if cs0 == nil || cs1 == nil { + t.Fatalf("Initiator did not receive CipherStates after writing message 3") + } + initiatorSendCS = cs0 + initiatorRecvCS = cs1 + + // Responder processes message 3 + _, cs0, cs1, err = responderHS.ReadMessage(nil, msg3) + if err != nil { + t.Fatalf("Responder failed to read handshake message 3: %v", err) + } + if cs0 == nil || cs1 == nil { + t.Fatalf("Responder did not receive CipherStates after reading message 3") + } + responderRecvCS = cs0 + responderSendCS = cs1 + + // Now both parties have the CipherStates + + // Initiator sends a message to Responder + initiatorSession := &NoiseSession{ + CipherState: initiatorSendCS, + } + responderSession := &NoiseSession{ + CipherState: responderRecvCS, + } + + originalData := []byte("This is a test message.") + _, encryptedPacket, err := initiatorSession.encryptPacket(originalData) + if err != nil { + t.Fatalf("Encryption failed: %v", err) + } + + _, decryptedData, err := responderSession.decryptPacket(encryptedPacket[2:]) + if err != nil { + t.Fatalf("Decryption failed: %v", err) + } + + assert.Equal(t, originalData, decryptedData, "Decrypted data does not match the original data") + + // Responder sends a message to Initiator + responderSession = &NoiseSession{ + CipherState: responderSendCS, + } + initiatorSession = &NoiseSession{ + CipherState: initiatorRecvCS, + } + + responseData := []byte("This is a response message.") + _, encryptedResponse, err := responderSession.encryptPacket(responseData) + if err != nil { + t.Fatalf("Responder encryption failed: %v", err) + } + + _, decryptedResponse, err := initiatorSession.decryptPacket(encryptedResponse[2:]) + if err != nil { + t.Fatalf("Initiator decryption failed: %v", err) + } + + assert.Equal(t, responseData, decryptedResponse, "Decrypted response does not match original data") +} diff --git a/lib/transport/noise/incoming_handshake.go b/lib/transport/noise/incoming_handshake.go index 80d8835..75abe6a 100644 --- a/lib/transport/noise/incoming_handshake.go +++ b/lib/transport/noise/incoming_handshake.go @@ -11,7 +11,7 @@ import ( "github.com/flynn/noise" ) -func ComposeRecieverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) { +func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) { if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() { return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported") } @@ -48,7 +48,7 @@ func ComposeRecieverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, e } func (c *NoiseSession) RunIncomingHandshake() error { - negData, msg, state, err := ComposeRecieverHandshakeMessage(c.HandKey, nil, nil, nil) + negData, msg, state, err := ComposeReceiverHandshakeMessage(c.HandKey, nil, nil, nil) if err != nil { return err } diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go index 5510311..da32f8b 100644 --- a/lib/transport/noise/read_session.go +++ b/lib/transport/noise/read_session.go @@ -38,7 +38,16 @@ func (c *NoiseSession) Read(b []byte) (int, error) { } func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { - m := len(data) + if c.CipherState == nil { + return 0, nil, errors.New("CipherState is nil") + } + // Decrypt + decryptedData, err := c.CipherState.Decrypt(nil, nil, data) + if err != nil { + return 0, nil, err + } + m := len(decryptedData) + return m, decryptedData, nil /*packet := c.InitializePacket() maxPayloadSize := c.maxPayloadSizeForRead(packet) if m > int(maxPayloadSize) { @@ -58,7 +67,6 @@ func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { } b := c.encryptIfNeeded(packet)*/ //c.freeBlock(packet) - return m, data, nil } func (c *NoiseSession) readPacketLocked(data []byte) (int, error) { diff --git a/lib/transport/noise/transport_test.go b/lib/transport/noise/transport_test.go index cdf972d..a6cc0c2 100644 --- a/lib/transport/noise/transport_test.go +++ b/lib/transport/noise/transport_test.go @@ -17,7 +17,10 @@ func TestTransport(t *testing.T) { if err != nil { t.Log(err) } - conn.Write([]byte("World")) + _, err = conn.Write([]byte("World")) + if err != nil { + t.Error(err) + } } }() lnn, err := net.Listen("tcp", ":42070") diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index fd5a065..7768880 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -1,7 +1,9 @@ package noise import ( + "encoding/binary" "errors" + "fmt" "sync/atomic" log "github.com/sirupsen/logrus" @@ -39,6 +41,23 @@ func (c *NoiseSession) Write(b []byte) (int, error) { func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { m := len(data) + if c.CipherState == nil { + return 0, nil, errors.New("CipherState is nil") + } + + // Encrypt the data + encryptedData, err := c.CipherState.Encrypt(nil, nil, data) + if err != nil { + return 0, nil, fmt.Errorf("failed to encrypt: '%w'", err) + } + //m := len(encryptedData) + + lengthPrefix := make([]byte, 2) + binary.BigEndian.PutUint16(lengthPrefix, uint16(len(encryptedData))) + + // Append encr data to prefix + packet := append(lengthPrefix, encryptedData...) + return m, packet, nil /*packet := c.InitializePacket() maxPayloadSize := c.maxPayloadSizeForWrite(packet) if m > int(maxPayloadSize) { @@ -58,7 +77,6 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { } b := c.encryptIfNeeded(packet)*/ //c.freeBlock(packet) - return m, data, nil } func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { From 09c7d32797c8799371cdb614c1fe5cefbc6f8e37 Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Thu, 3 Oct 2024 21:31:54 -0400 Subject: [PATCH 11/94] update the common library to the master branch --- lib/common/certificate/certificate.go | 47 ++-- lib/common/certificate/certificate_test.go | 13 +- lib/common/data/hash.go | 5 + lib/common/data/integer.go | 4 +- lib/common/data/mapping.go | 22 +- lib/common/data/mapping_test.go | 1 - lib/common/data/mapping_values.go | 78 +++--- lib/common/data/string.go | 67 ++--- lib/common/destination/destination.go | 12 +- lib/common/key_certificate/key_certificate.go | 109 ++++---- lib/common/keys_and_cert/keys_and_cert.go | 160 +++-------- .../keys_and_cert/keys_and_cert_test.go | 28 +- lib/common/lease_set/lease_set.go | 3 + lib/common/lease_set/lease_set_test.go | 6 +- lib/common/router_address/router_address.go | 256 +++++++++++++----- .../router_address/router_address_test.go | 5 +- lib/common/router_identity/router_identity.go | 12 +- lib/common/router_info/router_info.go | 210 +++++++------- lib/common/router_info/router_info_test.go | 4 +- 19 files changed, 520 insertions(+), 522 deletions(-) diff --git a/lib/common/certificate/certificate.go b/lib/common/certificate/certificate.go index 7366c2e..8ec94ce 100644 --- a/lib/common/certificate/certificate.go +++ b/lib/common/certificate/certificate.go @@ -75,7 +75,10 @@ func (c *Certificate) RawBytes() []byte { // ExcessBytes returns the excess bytes in a certificate found after the specified payload length. func (c *Certificate) ExcessBytes() []byte { - return c.payload[c.len.Int():] + if len(c.payload) >= c.len.Int() { + return c.payload[c.len.Int():] + } + return nil } // Bytes returns the entire certificate in []byte form, trims payload to specified length. @@ -116,8 +119,8 @@ func (c *Certificate) Data() (data []byte) { // NewCertificate creates a new Certficiate from []byte // returns err if the certificate is too short or if the payload doesn't match specified length. -func NewCertificate(data []byte) (certificate *Certificate, err error) { - certificate = &Certificate{} +func NewCertificate(data []byte) (certificate Certificate, err error) { + certificate = Certificate{} switch len(data) { case 0: certificate.kind = Integer([]byte{0}) @@ -126,29 +129,19 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) { "at": "(Certificate) NewCertificate", "certificate_bytes_length": len(data), "reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()), - }).Error("invalid certificate") - err = fmt.Errorf("error parsing certificate: certificate is too short") + }).Error("invalid certificate, empty") + err = fmt.Errorf("error parsing certificate: certificate is empty") return - case 1: - certificate.kind = Integer(data[0:0]) + case 1, 2: + certificate.kind = Integer(data[0 : len(data)-1]) certificate.len = Integer([]byte{0}) log.WithFields(log.Fields{ "at": "(Certificate) NewCertificate", "certificate_bytes_length": len(data), "reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()), - }).Error("invalid certificate") + }).Error("invalid certificate, too short") err = fmt.Errorf("error parsing certificate: certificate is too short") return - case 2: - certificate.kind = Integer(data[0:1]) - certificate.len = Integer([]byte{0}) - log.WithFields(log.Fields{ - "at": "(Certificate) NewCertificate", - "certificate_bytes_length": len(data), - "reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()), - }).Error("invalid certificate") - err = fmt.Errorf("error parsing certificate length: certificate is too short") - return default: certificate.kind = Integer(data[0:1]) certificate.len = Integer(data[1:3]) @@ -160,17 +153,11 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) { "at": "(Certificate) NewCertificate", "certificate_bytes_length": certificate.len.Int(), "certificate_payload_length": payleng, + "data_bytes:": string(data), + "kind_bytes": data[0:1], + "len_bytes": data[1:3], "reason": err.Error(), - }).Error("invalid certificate") - return - } else if certificate.len.Int() < len(data)-CERT_MIN_SIZE { - err = fmt.Errorf("certificate parsing warning: certificate data is longer than specified by length") - log.WithFields(log.Fields{ - "at": "(Certificate) NewCertificate", - "certificate_bytes_length": certificate.len.Int(), - "certificate_payload_length": payleng, - "reason": err.Error(), - }).Error("invalid certificate") + }).Error("invalid certificate, shorter than specified by length") return } return @@ -179,11 +166,11 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) { // ReadCertificate creates a Certificate from []byte and returns any ExcessBytes at the end of the input. // returns err if the certificate could not be read. -func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error) { +func ReadCertificate(data []byte) (certificate Certificate, remainder []byte, err error) { certificate, err = NewCertificate(data) if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" { - remainder = certificate.ExcessBytes() err = nil } + remainder = certificate.ExcessBytes() return } diff --git a/lib/common/certificate/certificate_test.go b/lib/common/certificate/certificate_test.go index 770db08..dee3653 100644 --- a/lib/common/certificate/certificate_test.go +++ b/lib/common/certificate/certificate_test.go @@ -32,12 +32,12 @@ func TestCertificateLengthErrWhenTooShort(t *testing.T) { assert := assert.New(t) bytes := []byte{0x03, 0x01} - certificate, err := NewCertificate(bytes) + certificate, _, err := ReadCertificate(bytes) cert_len := certificate.Length() assert.Equal(cert_len, 0, "certificate.Length() did not return zero length for missing length data") if assert.NotNil(err) { - assert.Equal("error parsing certificate length: certificate is too short", err.Error(), "correct error message should be returned") + assert.Equal("error parsing certificate: certificate is too short", err.Error(), "correct error message should be returned") } } @@ -71,13 +71,10 @@ func TestCertificateDataWhenTooLong(t *testing.T) { assert := assert.New(t) bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff, 0xaa, 0xaa} - certificate, err := NewCertificate(bytes) + certificate, _, _ := ReadCertificate(bytes) cert_data := certificate.Data() - if assert.NotNil(err) { - assert.Equal("certificate parsing warning: certificate data is longer than specified by length", err.Error(), "correct error message should be returned") - } - cert_len := certificate.Length() //len(cert_data) + cert_len := certificate.Length() // len(cert_data) assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was too long") if cert_data[0] != 0xff || cert_data[1] != 0xff { t.Fatal("certificate.Data() returned incorrect data when data was too long") @@ -144,6 +141,6 @@ func TestReadCertificateWithInvalidLength(t *testing.T) { assert.Equal(cert.length(), 2, "ReadCertificate() should populate the certificate with the provided data even when invalid") assert.Equal(len(remainder), 0, "ReadCertificate() returned non-zero length remainder on invalid certificate") if assert.NotNil(err) { - assert.Equal("error parsing certificate length: certificate is too short", err.Error(), "correct error message should be returned") + assert.Equal("error parsing certificate: certificate is too short", err.Error(), "correct error message should be returned") } } diff --git a/lib/common/data/hash.go b/lib/common/data/hash.go index 2559452..d50f4e9 100644 --- a/lib/common/data/hash.go +++ b/lib/common/data/hash.go @@ -23,8 +23,13 @@ Contents // https://geti2p.net/spec/common-structures#hash type Hash [32]byte +func (h Hash) Bytes() [32]byte { + return h +} + // HashData returns the SHA256 sum of a []byte input as Hash. func HashData(data []byte) (h Hash) { + // log.Println("Hashing Data:", data) h = sha256.Sum256(data) return } diff --git a/lib/common/data/integer.go b/lib/common/data/integer.go index feca45d..a7d4731 100644 --- a/lib/common/data/integer.go +++ b/lib/common/data/integer.go @@ -50,7 +50,9 @@ func NewInteger(bytes []byte, size int) (integer *Integer, remainder []byte, err if size < MAX_INTEGER_SIZE { integerSize = size } - i, remainder := ReadInteger(bytes, integerSize) + intBytes := bytes[:integerSize] + remainder = bytes[integerSize:] + i, _ := ReadInteger(intBytes, integerSize) integer = &i return } diff --git a/lib/common/data/mapping.go b/lib/common/data/mapping.go index c1c2fbf..8479f4f 100644 --- a/lib/common/data/mapping.go +++ b/lib/common/data/mapping.go @@ -126,28 +126,25 @@ func beginsWith(bytes []byte, chr byte) bool { // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) { - if len(bytes) == 0 { + if len(bytes) < 3 { log.WithFields(log.Fields{ "at": "ReadMapping", "reason": "zero length", }).Warn("mapping format violation") e := errors.New("zero length") err = append(err, e) + return } size, remainder, e := NewInteger(bytes, 2) if e != nil { err = append(err, e) } - - mapping.size = size - if e != nil { - log.WithFields(log.Fields{ - "at": "ReadMapping", - "reason": "error parsing integer", - }).Warn("mapping format violation") - e := errors.New("error parsing integer") - err = append(err, e) + if size.Int() == 0 { + return } + mapping.size = size + map_bytes := remainder[:mapping.size.Int()] + remainder = remainder[mapping.size.Int():] if len(remainder) == 0 { log.WithFields(log.Fields{ "at": "ReadMapping", @@ -156,7 +153,10 @@ func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) e := errors.New("zero length") err = append(err, e) } - vals, remainder, mappingValueErrs := ReadMappingValues(bytes) + // TODO: this should take the remainder and the length we already parsed above, as a parameter. + // Like tomorrow morning. + // ReadMappingValues should not attempt to figure out the length of the bytes it's reading over. + vals, _, mappingValueErrs := ReadMappingValues(map_bytes, *mapping.size) err = append(err, mappingValueErrs...) mapping.vals = vals diff --git a/lib/common/data/mapping_test.go b/lib/common/data/mapping_test.go index 986d2bd..563f575 100644 --- a/lib/common/data/mapping_test.go +++ b/lib/common/data/mapping_test.go @@ -27,7 +27,6 @@ func TestValuesExclusesPairWithBadData(t *testing.T) { assert.Equal(key, "a", "Values() returned by data with invalid key contains incorrect present key") assert.Equal(val, "b", "Values() returned by data with invalid key contains incorrect present key") } - } func TestValuesWarnsMissingData(t *testing.T) { diff --git a/lib/common/data/mapping_values.go b/lib/common/data/mapping_values.go index 4e46b0e..0c4f6c4 100644 --- a/lib/common/data/mapping_values.go +++ b/lib/common/data/mapping_values.go @@ -10,6 +10,17 @@ import ( // MappingValues represents the parsed key value pairs inside of an I2P Mapping. type MappingValues [][2]I2PString +func (m MappingValues) Get(key I2PString) I2PString { + keyBytes, _ := key.Data() + for _, pair := range m { + kb, _ := pair[0][0:].Data() + if kb == keyBytes { + return pair[1][1:] + } + } + return nil +} + // ValuesToMapping creates a *Mapping using MappingValues. // The values are sorted in the order defined in mappingOrder. func ValuesToMapping(values MappingValues) *Mapping { @@ -46,11 +57,11 @@ func mappingOrder(values MappingValues) { // ReadMappingValues returns *MappingValues from a []byte. // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. -func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes []byte, errs []error) { - mapping := remainder - //var remainder = mapping - //var err error - if remainder == nil || len(remainder) < 0 { +func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingValues, remainder_bytes []byte, errs []error) { + // mapping := remainder + // var remainder = mapping + // var err error + if remainder == nil || len(remainder) < 1 { log.WithFields(log.Fields{ "at": "(Mapping) Values", "reason": "data shorter than expected", @@ -59,31 +70,21 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes return } map_values := make(MappingValues, 0) - if len(remainder) < 1 { - log.WithFields(log.Fields{ - "at": "(Mapping) Values", - "reason": "data shorter than expected", - }).Error("mapping contained no data") - errs = []error{errors.New("mapping contained no data")} - return - } - l := Integer(remainder[:2]) - length := l.Int() - // - 2 bytes for map length bits - mapping_len := len(mapping) - 2 - if mapping_len > length { + int_map_length := map_length.Int() + mapping_len := len(remainder) + if mapping_len > int_map_length { log.WithFields(log.Fields{ "at": "(Mapping) Values", "mapping_bytes_length": mapping_len, - "mapping_length_field": length, + "mapping_length_field": int_map_length, "reason": "data longer than expected", }).Warn("mapping format warning") errs = append(errs, errors.New("warning parsing mapping: data exists beyond length of mapping")) - } else if length > mapping_len { + } else if int_map_length > mapping_len { log.WithFields(log.Fields{ "at": "(Mapping) Values", "mapping_bytes_length": mapping_len, - "mapping_length_field": length, + "mapping_length_field": int_map_length, "reason": "data shorter than expected", }).Warn("mapping format warning") errs = append(errs, errors.New("warning parsing mapping: mapping length exceeds provided data")) @@ -91,7 +92,7 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes encounteredKeysMap := map[string]bool{} // pop off length bytes before parsing kv pairs - remainder = remainder[2:] + // remainder = remainder[2:] for { // Read a key, breaking on fatal errors @@ -111,16 +112,16 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes break } - str, more, err := ReadI2PString(remainder) - // overwriting remainder with more as another var to prevent memory weirdness in loops - remainder = more - key_str := str + key_str, more, err := ReadI2PString(remainder) if err != nil { if stopValueRead(err) { errs = append(errs, err) - //return + // return } } + // overwriting remainder with more as another var to prevent memory weirdness in loops + remainder = more + // log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder) // Check if key has already been encountered in this mapping keyBytes, _ := key_str.Data() @@ -130,7 +131,9 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes log.WithFields(log.Fields{ "at": "(Mapping) Values", "reason": "duplicate key in mapping", + "key": string(key_str), }).Error("mapping format violation") + log.Printf("DUPE: %s", key_str) errs = append(errs, errors.New("mapping format violation, duplicate key in mapping")) // Based on other implementations this does not seem to happen often? // Java throws an exception in this case, the base object is a Hashmap so the value is overwritten and an exception is thrown. @@ -142,33 +145,39 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes log.WithFields(log.Fields{ "at": "(Mapping) Values", "reason": "expected =", + "value:": string(remainder), }).Warn("mapping format violation") errs = append(errs, errors.New("mapping format violation, expected =")) + log.Printf("ERRVAL: %s", remainder) break + } else { + remainder = remainder[1:] } - remainder = remainder[1:] // Read a value, breaking on fatal errors // and appending warnings - str, more, err = ReadI2PString(remainder) - // overwriting remainder with more as another var to prevent memory weirdness in loops - remainder = more - val_str := str + val_str, more, err := ReadI2PString(remainder) if err != nil { if stopValueRead(err) { errs = append(errs, err) - //return + // return } } + // overwriting remainder with more as another var to prevent memory weirdness in loops + remainder = more + // log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder) + // log.Printf("(MAPPING VALUES DEBUG) String: value: %s", val_str) if !beginsWith(remainder, 0x3b) { log.WithFields(log.Fields{ "at": "(Mapping) Values", "reason": "expected ;", + "value:": string(remainder), }).Warn("mapping format violation") errs = append(errs, errors.New("mapping format violation, expected ;")) break + } else { + remainder = remainder[1:] } - remainder = remainder[1:] // Append the key-value pair and break if there is no more data to read map_values = append(map_values, [2]I2PString{key_str, val_str}) @@ -181,5 +190,4 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes } values = &map_values return - } diff --git a/lib/common/data/string.go b/lib/common/data/string.go index 335fe83..96399d2 100644 --- a/lib/common/data/string.go +++ b/lib/common/data/string.go @@ -2,6 +2,7 @@ package data import ( "errors" + "fmt" log "github.com/sirupsen/logrus" ) @@ -38,28 +39,21 @@ func (str I2PString) Length() (length int, err error) { err = errors.New("error parsing string: zero length") return } - l := Integer([]byte{byte(str[0])}) + l, _, err := NewInteger(str[:], 1) + if err != nil { + return l.Int(), err + } length = l.Int() - inferred_len := length + 1 str_len := len(str) - if inferred_len > str_len { - log.WithFields(log.Fields{ - "at": "(I2PString) Length", - "string_bytes_length": str_len, - "string_length_field": length, - "expected_bytes_length": inferred_len, - "reason": "data shorter than specified", - }).Warn("string format warning") + if length > str_len { + /*log.WithFields(log.Fields{ + "at": "(I2PString) Length", + "string_bytes_length": str_len, + "string_length_field": length, + "data": string(str), + "reason": "data less than specified by length", + }).Error("string format warning")*/ err = errors.New("string parsing warning: string data is shorter than specified by length") - } else if str_len > inferred_len { - log.WithFields(log.Fields{ - "at": "(I2PString) Length", - "string_bytes_length": str_len, - "string_length_field": length, - "expected_bytes_length": inferred_len, - "reason": "data longer than specified", - }).Warn("string format warning") - err = errors.New("string parsing warning: string contains data beyond length") } return } @@ -73,14 +67,20 @@ func (str I2PString) Data() (data string, err error) { case "error parsing string: zero length": return case "string parsing warning: string data is shorter than specified by length": - data = string(str[1:]) - return + if is, e := ToI2PString(string(str[:])); e != nil { + return "", e + } else { + return is.Data() + } case "string parsing warning: string contains data beyond length": - data = string(str[1 : length+1]) + data = string(str[1:]) return } } - data = string(str[1:]) + if length == 0 { + return + } + data = string(str[1 : length+1]) return } @@ -113,20 +113,25 @@ func ToI2PString(data string) (str I2PString, err error) { // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) { - str = I2PString(data) - length, err := I2PString(data).Length() - if err != nil && err.Error() == "string parsing warning: string contains data beyond length" { - str = I2PString(data[:length+1]) - remainder = data[length+1:] - err = nil + length, _, err := NewInteger(data, 1) + if err != nil { + return + } + data_len := length.Int() + 1 + str = data[:data_len] + remainder = data[data_len:] + l, err := str.Length() + if l != data_len-1 { + err = fmt.Errorf("error reading I2P string, length does not match data") + return } return } // NewI2PString creates a new *I2PString from []byte using ReadI2PString. // Returns a pointer to I2PString unlike ReadI2PString. -func NewI2PString(data []byte) (str *I2PString, remainder []byte, err error) { +/*func NewI2PString(data []byte) (str *I2PString, remainder []byte, err error) { objstr, remainder, err := ReadI2PString(data) str = &objstr return -} +}*/ diff --git a/lib/common/destination/destination.go b/lib/common/destination/destination.go index 4e06b21..2ea420e 100644 --- a/lib/common/destination/destination.go +++ b/lib/common/destination/destination.go @@ -26,7 +26,7 @@ Identical to KeysAndCert. // // https://geti2p.net/spec/common-structures#destination type Destination struct { - *KeysAndCert + KeysAndCert } // Base32Address returns the I2P base32 address for this Destination. @@ -48,17 +48,9 @@ func (destination Destination) Base64() string { // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) { - keys_and_cert, remainder, err := NewKeysAndCert(data) + keys_and_cert, remainder, err := ReadKeysAndCert(data) destination = Destination{ keys_and_cert, } return } - -// NewDestination creates a new *Destination from []byte using ReadDestination. -// Returns a pointer to Destination unlike ReadDestination. -func NewDestination(data []byte) (destination *Destination, remainder []byte, err error) { - objdestination, remainder, err := ReadDestination(data) - destination = &objdestination - return destination, remainder, err -} diff --git a/lib/common/key_certificate/key_certificate.go b/lib/common/key_certificate/key_certificate.go index 2e94289..a8b761e 100644 --- a/lib/common/key_certificate/key_certificate.go +++ b/lib/common/key_certificate/key_certificate.go @@ -52,6 +52,10 @@ const ( // Key Certificate Public Key Types const ( KEYCERT_CRYPTO_ELG = iota + KEYCERT_CRYPTO_P256 + KEYCERT_CRYPTO_P384 + KEYCERT_CRYPTO_P521 + KEYCERT_CRYPTO_X25519 ) const ( @@ -73,7 +77,11 @@ const ( // PublicKey sizes for Public Key Types const ( - KEYCERT_CRYPTO_ELG_SIZE = 256 + KEYCERT_CRYPTO_ELG_SIZE = 256 + KEYCERT_CRYPTO_P256_SIZE = 64 + KEYCERT_CRYPTO_P384_SIZE = 96 + KEYCERT_CRYPTO_P521_SIZE = 132 + KEYCERT_CRYPTO_X25519_SIZE = 32 ) // Sizes of structures in KeyCertificates @@ -82,9 +90,9 @@ const ( KEYCERT_SPK_SIZE = 128 ) -//type KeyCertificate []byte +// type KeyCertificate []byte type KeyCertificate struct { - *Certificate + Certificate spkType Integer cpkType Integer } @@ -112,7 +120,7 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke return } data_len := len(data) - if data_len < KEYCERT_PUBKEY_SIZE { + if data_len < key_certificate.CryptoSize() { log.WithFields(log.Fields{ "at": "(KeyCertificate) ConstructPublicKey", "data_len": data_len, @@ -127,6 +135,10 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke var elg_key crypto.ElgPublicKey copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE]) public_key = elg_key + case KEYCERT_CRYPTO_X25519: + var ed25519_key crypto.Ed25519PublicKey + copy(ed25519_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE]) + public_key = ed25519_key } return } @@ -139,7 +151,7 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si return } data_len := len(data) - if data_len < KEYCERT_SPK_SIZE { + if data_len < key_certificate.SignatureSize() { log.WithFields(log.Fields{ "at": "(KeyCertificate) ConstructSigningPublicKey", "data_len": data_len, @@ -169,11 +181,11 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si copy(ec_key[KEYCERT_SPK_SIZE:], key_certificate.Certificate.RawBytes()[4:4+extra]) signing_public_key = ec_key case KEYCERT_SIGN_RSA2048: - //var rsa_key crypto.RSA2048PublicKey - //extra := KEYCERT_SIGN_RSA2048_SIZE - 128 - //copy(rsa_key[:], data) - //copy(rsa_key[128:], key_certificate[4:4+extra]) - //signing_public_key = rsa_key + // var rsa_key crypto.RSA2048PublicKey + // extra := KEYCERT_SIGN_RSA2048_SIZE - 128 + // copy(rsa_key[:], data) + // copy(rsa_key[128:], key_certificate[4:4+extra]) + // signing_public_key = rsa_key case KEYCERT_SIGN_RSA3072: case KEYCERT_SIGN_RSA4096: case KEYCERT_SIGN_ED25519: @@ -185,65 +197,60 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si // SignatureSize return the size of a Signature corresponding to the Key Certificate's SigningPublicKey type. func (key_certificate KeyCertificate) SignatureSize() (size int) { sizes := map[int]int{ - KEYCERT_SIGN_DSA_SHA1: 40, - KEYCERT_SIGN_P256: 64, - KEYCERT_SIGN_P384: 96, - KEYCERT_SIGN_P521: 132, - KEYCERT_SIGN_RSA2048: 256, - KEYCERT_SIGN_RSA3072: 384, - KEYCERT_SIGN_RSA4096: 512, - KEYCERT_SIGN_ED25519: 64, - KEYCERT_SIGN_ED25519PH: 64, + KEYCERT_SIGN_DSA_SHA1: KEYCERT_SIGN_DSA_SHA1_SIZE, + KEYCERT_SIGN_P256: KEYCERT_SIGN_P256_SIZE, + KEYCERT_SIGN_P384: KEYCERT_SIGN_P384_SIZE, + KEYCERT_SIGN_P521: KEYCERT_SIGN_P521_SIZE, + KEYCERT_SIGN_RSA2048: KEYCERT_SIGN_RSA2048_SIZE, + KEYCERT_SIGN_RSA3072: KEYCERT_SIGN_RSA3072_SIZE, + KEYCERT_SIGN_RSA4096: KEYCERT_SIGN_RSA4096_SIZE, + KEYCERT_SIGN_ED25519: KEYCERT_SIGN_ED25519_SIZE, + KEYCERT_SIGN_ED25519PH: KEYCERT_SIGN_ED25519PH_SIZE, } key_type := key_certificate.SigningPublicKeyType() return sizes[int(key_type)] } +// CryptoSize return the size of a Public Key corresponding to the Key Certificate's PublicKey type. +func (key_certificate KeyCertificate) CryptoSize() (size int) { + sizes := map[int]int{ + KEYCERT_CRYPTO_ELG: KEYCERT_CRYPTO_ELG_SIZE, + KEYCERT_CRYPTO_P256: KEYCERT_CRYPTO_P256_SIZE, + KEYCERT_CRYPTO_P384: KEYCERT_CRYPTO_P384_SIZE, + KEYCERT_CRYPTO_P521: KEYCERT_CRYPTO_P521_SIZE, + KEYCERT_CRYPTO_X25519: KEYCERT_CRYPTO_X25519_SIZE, + } + key_type := key_certificate.PublicKeyType() + return sizes[int(key_type)] +} + // NewKeyCertificate creates a new *KeyCertificate from []byte using ReadCertificate. // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) { - var certificate *Certificate + var certificate Certificate certificate, remainder, err = ReadCertificate(bytes) - //if err != nil { - // return nil, err - //} + if err != nil { + return + } if len(bytes) < KEYCERT_MIN_SIZE { err = errors.New("error parsing key certificate: not enough data") + remainder = bytes[KEYCERT_MIN_SIZE:] } - switch len(bytes) { - case 4: - key_certificate = &KeyCertificate{ - Certificate: certificate, - spkType: Integer(bytes[4:]), - cpkType: Integer([]byte{0}), - } - case 5: - key_certificate = &KeyCertificate{ - Certificate: certificate, - spkType: Integer(bytes[4:5]), - cpkType: Integer([]byte{0}), - } - case 6: - key_certificate = &KeyCertificate{ - Certificate: certificate, - spkType: Integer(bytes[4:5]), - cpkType: Integer(bytes[6:]), - } - default: - key_certificate = &KeyCertificate{ - Certificate: certificate, - spkType: Integer(bytes[4:5]), - cpkType: Integer(bytes[6:7]), - } + key_certificate = &KeyCertificate{ + Certificate: certificate, + } + if len(bytes) >= 5 { + key_certificate.spkType = Integer(bytes[4:5]) + } + if len(bytes) >= 7 { + key_certificate.cpkType = Integer(bytes[6:7]) } - remainder = bytes[7:] - //key_certificate.PublicKey = NewPublicKey(bytes) return } // KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate. -func KeyCertificateFromCertificate(certificate *Certificate) *KeyCertificate { +func KeyCertificateFromCertificate(certificate Certificate) *KeyCertificate { k, _, _ := NewKeyCertificate(certificate.RawBytes()) return k } diff --git a/lib/common/keys_and_cert/keys_and_cert.go b/lib/common/keys_and_cert/keys_and_cert.go index df033f4..72ae89c 100644 --- a/lib/common/keys_and_cert/keys_and_cert.go +++ b/lib/common/keys_and_cert/keys_and_cert.go @@ -79,103 +79,41 @@ type KeysAndCert struct { } // Bytes returns the entire KeyCertificate in []byte form, trims payload to specified length. -func (keys_and_cert *KeysAndCert) Bytes() []byte { +func (keys_and_cert KeysAndCert) Bytes() []byte { return keys_and_cert.KeyCertificate.Bytes() } // PublicKey returns the public key as a crypto.PublicKey. func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey) { - /*cert := keys_and_cert.Certificate() - cert_len := cert.Length() - if err != nil { - return - } - if cert_len == 0 { - // No Certificate is present, return the KEYS_AND_CERT_PUBKEY_SIZE byte - // PublicKey space as ElgPublicKey. - var elg_key crypto.ElgPublicKey - copy(keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], elg_key[:]) - key = elg_key - } else { - // A Certificate is present in this KeysAndCert - cert_type := cert.Type() - if cert_type == CERT_KEY { - // This KeysAndCert contains a Key Certificate, construct - // a PublicKey from the data in the KeysAndCert and - // any additional data in the Certificate. - key, err = KeyCertificateFromCertificate(cert).ConstructPublicKey( - keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], - ) - } else { - // Key Certificate is not present, return the KEYS_AND_CERT_PUBKEY_SIZE byte - // PublicKey space as ElgPublicKey. No other Certificate - // types are currently in use. - var elg_key crypto.ElgPublicKey - copy(keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], elg_key[:]) - key = elg_key - log.WithFields(log.Fields{ - "at": "(KeysAndCert) PublicKey", - "cert_type": cert_type, - }).Warn("unused certificate type observed") - } - - } - return*/ return keys_and_cert.publicKey } // SigningPublicKey returns the signing public key. func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey) { - /*cert := keys_and_cert.Certificate() - cert_len := cert.Length() - if err != nil { - return - } - if cert_len == 0 { - // No Certificate is present, return the KEYS_AND_CERT_SPK_SIZE byte - // SigningPublicKey space as legacy DSA SHA1 SigningPublicKey. - var dsa_pk crypto.DSAPublicKey - copy(dsa_pk[:], keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE:KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE]) - signing_public_key = dsa_pk - } else { - // A Certificate is present in this KeysAndCert - cert_type := cert.Type() - if cert_type == CERT_KEY { - // This KeysAndCert contains a Key Certificate, construct - // a SigningPublicKey from the data in the KeysAndCert and - // any additional data in the Certificate. - signing_public_key, err = KeyCertificateFromCertificate(cert).ConstructSigningPublicKey( - keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE], - ) - } else { - // Key Certificate is not present, return the KEYS_AND_CERT_SPK_SIZE byte - // SigningPublicKey space as legacy SHA DSA1 SigningPublicKey. - // No other Certificate types are currently in use. - var dsa_pk crypto.DSAPublicKey - copy(dsa_pk[:], keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE:KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE]) - signing_public_key = dsa_pk - } - - }*/ return keys_and_cert.signingPublicKey } // Certfificate returns the certificate. -func (keys_and_cert *KeysAndCert) Certificate() (cert *Certificate) { +func (keys_and_cert *KeysAndCert) Certificate() (cert Certificate) { return keys_and_cert.KeyCertificate.Certificate } -// -// Read a KeysAndCert from a slice of bytes, retuning it and the remaining data as well as any errors -// encoutered parsing the KeysAndCert. -// - -// ReadKeysAndCert returns KeysAndCert from a []byte. -// The remaining bytes after the specified length are also returned. -// Returns a list of errors that occurred during parsing. +// ReadKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert. +// Returns a pointer to KeysAndCert unlike ReadKeysAndCert. func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error) { - /*data_len := len(data) - if data_len < KEYS_AND_CERT_MIN_SIZE { + data_len := len(data) + // keys_and_cert = KeysAndCert{} + if data_len < KEYS_AND_CERT_MIN_SIZE && data_len > KEYS_AND_CERT_DATA_SIZE { + log.WithFields(log.Fields{ + "at": "ReadKeysAndCert", + "data_len": data_len, + "required_len": KEYS_AND_CERT_MIN_SIZE, + "reason": "not enough data", + }).Error("error parsing keys and cert") + err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size") + keys_and_cert.KeyCertificate, remainder, _ = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:]) + return + } else if data_len < KEYS_AND_CERT_DATA_SIZE { log.WithFields(log.Fields{ "at": "ReadKeysAndCert", "data_len": data_len, @@ -185,56 +123,22 @@ func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size") return } - keys_and_cert = KeysAndCert(data[:KEYS_AND_CERT_MIN_SIZE]) - cert, _ := keys_and_cert.Certificate() - cert_len := cert.Length() - if cert_len == 0 { - remainder = data[KEYS_AND_CERT_MIN_SIZE:] + keys_and_cert.KeyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:]) + if err != nil { return } - if data_len < KEYS_AND_CERT_MIN_SIZE+cert_len { - keys_and_cert = append(keys_and_cert, data[KEYS_AND_CERT_MIN_SIZE:]...) - //err = cert_len_err - } else { - keys_and_cert = append(keys_and_cert, data[KEYS_AND_CERT_MIN_SIZE:KEYS_AND_CERT_MIN_SIZE+cert_len]...) - remainder = data[KEYS_AND_CERT_MIN_SIZE+cert_len:] - }*/ - keys_and_cert_pointer, remainder, err := NewKeysAndCert(data) - keys_and_cert = *keys_and_cert_pointer + // TODO: this only supports one key type right now and it's the old key type, but the layout is the same. + // a case-switch which sets the size of the SPK and the PK should be used to replace the referenced KEYS_AND_CERT_PUBKEY_SIZE + // and KEYS_AND_CERT_SPK_SIZE constants in the future. + keys_and_cert.publicKey, err = keys_and_cert.KeyCertificate.ConstructPublicKey(data[:keys_and_cert.KeyCertificate.CryptoSize()]) + if err != nil { + return + } + keys_and_cert.signingPublicKey, err = keys_and_cert.KeyCertificate.ConstructSigningPublicKey(data[KEYS_AND_CERT_DATA_SIZE-keys_and_cert.KeyCertificate.SignatureSize() : KEYS_AND_CERT_DATA_SIZE]) + if err != nil { + return + } + padding := data[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_DATA_SIZE-KEYS_AND_CERT_SPK_SIZE] + keys_and_cert.padding = padding return } - -// NewKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert. -// Returns a pointer to KeysAndCert unlike ReadKeysAndCert. -func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte, err error) { - data_len := len(data) - keys_and_cert = &KeysAndCert{} - if data_len < KEYS_AND_CERT_MIN_SIZE { - log.WithFields(log.Fields{ - "at": "ReadKeysAndCert", - "data_len": data_len, - "required_len": KEYS_AND_CERT_MIN_SIZE, - "reason": "not enough data", - }).Error("error parsing keys and cert") - err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size") - return - } - cert, remainder, err := NewKeyCertificate(data) - keys_and_cert.KeyCertificate = cert - if err != nil { - return nil, nil, err - } - padding := data[KEYS_AND_CERT_MIN_SIZE+cert.Length():] - keys_and_cert.padding = padding - publicKey, err := cert.ConstructPublicKey(padding) - keys_and_cert.publicKey = publicKey - if err != nil { - return nil, nil, err - } - signingPublicKey, err := cert.ConstructSigningPublicKey(padding) - keys_and_cert.signingPublicKey = signingPublicKey - if err != nil { - return nil, nil, err - } - return keys_and_cert, remainder, err -} diff --git a/lib/common/keys_and_cert/keys_and_cert_test.go b/lib/common/keys_and_cert/keys_and_cert_test.go index 5182f8d..f24ea93 100644 --- a/lib/common/keys_and_cert/keys_and_cert_test.go +++ b/lib/common/keys_and_cert/keys_and_cert_test.go @@ -6,23 +6,17 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCertificateWithMissingData(t *testing.T) { +/*func TestCertificateWithMissingData(t *testing.T) { assert := assert.New(t) cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01} data := make([]byte, 128+256) data = append(data, cert_data...) - keys_and_cert, _, err := ReadKeysAndCert(data) - - cert := keys_and_cert.Certificate() + _, _, err := NewKeysAndCert(data) if assert.NotNil(err) { assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error()) } - cert_bytes := cert.Bytes() - if assert.Equal(len(cert_data), len(cert_bytes)) { - assert.Equal(cert_bytes, cert_data, "keys_and_cert.Certificate() did not return available data when cert was missing some data") - } -} +}*/ func TestCertificateWithValidData(t *testing.T) { assert := assert.New(t) @@ -31,9 +25,10 @@ func TestCertificateWithValidData(t *testing.T) { data := make([]byte, 128+256) data = append(data, cert_data...) keys_and_cert, _, err := ReadKeysAndCert(data) + assert.Nil(err) cert := keys_and_cert.Certificate() - assert.Nil(err) + cert_bytes := cert.Bytes() if assert.Equal(len(cert_data), len(cert_bytes)) { assert.Equal(cert_bytes, cert_data, "keys_and_cert.Certificate() did not return correct data with valid cert") @@ -168,7 +163,7 @@ func TestSigningPublicKeyWithKeyCertificate(t *testing.T) { assert.Equal(len(signing_pub_key_data), signing_pub_key.Len()) } -func TestReadKeysAndCertWithMissingData(t *testing.T) { +func TestNewKeysAndCertWithMissingData(t *testing.T) { assert := assert.New(t) cert_data := make([]byte, 128) @@ -177,10 +172,9 @@ func TestReadKeysAndCertWithMissingData(t *testing.T) { if assert.NotNil(err) { assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error()) } - } -func TestReadKeysAndCertWithMissingCertData(t *testing.T) { +func TestNewKeysAndCertWithMissingCertData(t *testing.T) { assert := assert.New(t) cert_data := make([]byte, 128+256) @@ -192,7 +186,7 @@ func TestReadKeysAndCertWithMissingCertData(t *testing.T) { } } -func TestReadKeysAndCertWithValidDataWithCertificate(t *testing.T) { +func TestNewKeysAndCertWithValidDataWithCertificate(t *testing.T) { assert := assert.New(t) cert_data := make([]byte, 128+256) @@ -202,7 +196,7 @@ func TestReadKeysAndCertWithValidDataWithCertificate(t *testing.T) { assert.Nil(err) } -func TestReadKeysAndCertWithValidDataWithoutCertificate(t *testing.T) { +func TestNewKeysAndCertWithValidDataWithoutCertificate(t *testing.T) { assert := assert.New(t) cert_data := make([]byte, 128+256) @@ -212,7 +206,7 @@ func TestReadKeysAndCertWithValidDataWithoutCertificate(t *testing.T) { assert.Nil(err) } -func TestReadKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) { +func TestNewKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) { assert := assert.New(t) cert_data := make([]byte, 128+256) @@ -224,7 +218,7 @@ func TestReadKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) { assert.Nil(err) } -func TestReadKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) { +func TestNewKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) { assert := assert.New(t) cert_data := make([]byte, 128+256) diff --git a/lib/common/lease_set/lease_set.go b/lib/common/lease_set/lease_set.go index c69396f..e765084 100644 --- a/lib/common/lease_set/lease_set.go +++ b/lib/common/lease_set/lease_set.go @@ -133,6 +133,9 @@ type LeaseSet struct { // Destination returns the Destination as []byte. func (lease_set LeaseSet) Destination() (destination Destination, err error) { keys_and_cert, _, err := ReadKeysAndCert(lease_set) + if err != nil { + return + } destination, _, err = ReadDestination(keys_and_cert.Bytes()) return } diff --git a/lib/common/lease_set/lease_set_test.go b/lib/common/lease_set/lease_set_test.go index 97ddf55..7851fcd 100644 --- a/lib/common/lease_set/lease_set_test.go +++ b/lib/common/lease_set/lease_set_test.go @@ -14,9 +14,9 @@ import ( func buildDestination() *router_identity.RouterIdentity { router_ident_data := make([]byte, 128+256) router_ident_data = append(router_ident_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...) - ident, _, err := router_identity.NewRouterIdentity(router_ident_data) + ident, _, err := router_identity.ReadRouterIdentity(router_ident_data) panic(err) - return ident + return &ident } func buildPublicKey() []byte { @@ -77,7 +77,7 @@ func TestDestinationIsCorrect(t *testing.T) { dest, err := lease_set.Destination() assert.Nil(err) dest_cert := dest.Certificate() - //assert.Nil(err) + // assert.Nil(err) cert_type := dest_cert.Type() assert.Nil(err) assert.Equal(certificate.CERT_KEY, cert_type) diff --git a/lib/common/router_address/router_address.go b/lib/common/router_address/router_address.go index 36a62d2..cc44ec1 100644 --- a/lib/common/router_address/router_address.go +++ b/lib/common/router_address/router_address.go @@ -3,6 +3,10 @@ package router_address import ( "errors" + "fmt" + "net" + "strconv" + "strings" . "github.com/go-i2p/go-i2p/lib/common/data" log "github.com/sirupsen/logrus" @@ -63,71 +67,215 @@ options :: Mapping // // https://geti2p.net/spec/common-structures#routeraddress type RouterAddress struct { - cost *Integer - expiration *Date - Transport_Style *I2PString - options *Mapping - parserErr error + TransportCost *Integer + ExpirationDate *Date + TransportType I2PString + TransportOptions *Mapping } +// Network implements net.Addr. It returns the transport type plus 4 or 6 +func (router_address *RouterAddress) Network() string { + if router_address.TransportType == nil { + return "" + } + str, err := router_address.TransportType.Data() + if err != nil { + return "" + } + return string(str) + router_address.IPVersion() +} + +// IPVersion returns a string "4" for IPv4 or 6 for IPv6 +func (router_address *RouterAddress) IPVersion() string { + str, err := router_address.CapsString().Data() + if err != nil { + return "" + } + if strings.HasSuffix(str, "6") { + return "6" + } + return "4" +} + +func (router_address *RouterAddress) UDP() bool { + return strings.HasPrefix(strings.ToLower(router_address.Network()), "ssu") +} + +// String implements net.Addr. It returns the IP address, followed by the options +func (router_address *RouterAddress) String() string { + var rv []string + rv = append(rv, string(router_address.TransportStyle())) + rv = append(rv, string(router_address.HostString())) + rv = append(rv, string(router_address.PortString())) + rv = append(rv, string(router_address.StaticKeyString())) + rv = append(rv, string(router_address.InitializationVectorString())) + rv = append(rv, string(router_address.ProtocolVersionString())) + if router_address.UDP() { + rv = append(rv, string(router_address.IntroducerHashString(0))) + rv = append(rv, string(router_address.IntroducerExpirationString(0))) + rv = append(rv, string(router_address.IntroducerTagString(0))) + rv = append(rv, string(router_address.IntroducerHashString(1))) + rv = append(rv, string(router_address.IntroducerExpirationString(1))) + rv = append(rv, string(router_address.IntroducerTagString(1))) + rv = append(rv, string(router_address.IntroducerHashString(2))) + rv = append(rv, string(router_address.IntroducerExpirationString(2))) + rv = append(rv, string(router_address.IntroducerTagString(2))) + } + return strings.TrimSpace(strings.Join(rv, " ")) +} + +var ex_addr net.Addr = &RouterAddress{} + // Bytes returns the router address as a []byte. func (router_address RouterAddress) Bytes() []byte { bytes := make([]byte, 0) - bytes = append(bytes, router_address.cost.Bytes()...) - bytes = append(bytes, router_address.expiration.Bytes()...) - strData, err := router_address.Transport_Style.Data() + bytes = append(bytes, router_address.TransportCost.Bytes()...) + bytes = append(bytes, router_address.ExpirationDate.Bytes()...) + strData, err := router_address.TransportType.Data() if err != nil { log.WithFields(log.Fields{ "error": err, - }).Error("RouterAddress.Bytes: error getting Transport_Style bytes") + }).Error("RouterAddress.Bytes: error getting transport_style bytes") } else { bytes = append(bytes, strData...) } - //bytes = append(bytes, router_address.options.Bytes()...) + bytes = append(bytes, router_address.TransportOptions.Data()...) return bytes } // Cost returns the cost for this RouterAddress as a Go integer. func (router_address RouterAddress) Cost() int { - return router_address.cost.Int() + return router_address.TransportCost.Int() } // Expiration returns the expiration for this RouterAddress as an I2P Date. func (router_address RouterAddress) Expiration() Date { - return *router_address.expiration + return *router_address.ExpirationDate } // TransportStyle returns the transport style for this RouterAddress as an I2PString. func (router_address RouterAddress) TransportStyle() I2PString { - return *router_address.Transport_Style + return router_address.TransportType +} + +// GetOption returns the value of the option specified by the key +func (router_address RouterAddress) GetOption(key I2PString) I2PString { + return router_address.Options().Values().Get(key) +} + +func (router_address RouterAddress) HostString() I2PString { + host, _ := ToI2PString("host") + return router_address.GetOption(host) +} + +func (router_address RouterAddress) PortString() I2PString { + port, _ := ToI2PString("port") + return router_address.GetOption(port) +} + +func (router_address RouterAddress) CapsString() I2PString { + caps, _ := ToI2PString("caps") + return router_address.GetOption(caps) +} + +func (router_address RouterAddress) StaticKeyString() I2PString { + sk, _ := ToI2PString("s") + return router_address.GetOption(sk) +} + +func (router_address RouterAddress) InitializationVectorString() I2PString { + iv, _ := ToI2PString("i") + return router_address.GetOption(iv) +} + +func (router_address RouterAddress) ProtocolVersionString() I2PString { + v, _ := ToI2PString("v") + return router_address.GetOption(v) +} + +func (router_address RouterAddress) IntroducerHashString(num int) I2PString { + if num >= 0 && num <= 2 { + val := strconv.Itoa(num) + v, _ := ToI2PString("ih" + val) + return router_address.GetOption(v) + } + v, _ := ToI2PString("ih0") + return router_address.GetOption(v) +} + +func (router_address RouterAddress) IntroducerExpirationString(num int) I2PString { + if num >= 0 && num <= 2 { + val := strconv.Itoa(num) + v, _ := ToI2PString("iexp" + val) + return router_address.GetOption(v) + } + v, _ := ToI2PString("iexp0") + return router_address.GetOption(v) +} + +func (router_address RouterAddress) IntroducerTagString(num int) I2PString { + if num >= 0 && num <= 2 { + val := strconv.Itoa(num) + v, _ := ToI2PString("itag" + val) + return router_address.GetOption(v) + } + v, _ := ToI2PString("itag0") + return router_address.GetOption(v) +} + +func (router_address RouterAddress) Host() (net.Addr, error) { + host := router_address.HostString() + hostBytes, err := host.Data() + if err != nil { + return nil, err + } + ip := net.ParseIP(hostBytes) + if ip == nil { + return nil, fmt.Errorf("null host error") + } + return net.ResolveIPAddr("", ip.String()) +} + +func (router_address RouterAddress) Port() (string, error) { + port := router_address.PortString() + portBytes, err := port.Data() + if err != nil { + return "", err + } + val, err := strconv.Atoi(portBytes) + if err != nil { + return "", err + } + return strconv.Itoa(val), nil +} + +func (router_address RouterAddress) StaticKey() ([32]byte, error) { + sk := router_address.StaticKeyString() + if len([]byte(sk)) != 32 { + return [32]byte{}, fmt.Errorf("error: invalid static key") + } + return [32]byte(sk), nil +} + +func (router_address RouterAddress) InitializationVector() ([32]byte, error) { + iv := router_address.InitializationVectorString() + if len([]byte(iv)) != 32 { + return [32]byte{}, fmt.Errorf("error: invalid static key") + } + return [32]byte(iv), nil +} + +func (router_address RouterAddress) ProtocolVersion() (string, error) { + return router_address.ProtocolVersionString().Data() } // Options returns the options for this RouterAddress as an I2P Mapping. func (router_address RouterAddress) Options() Mapping { - return *router_address.options + return *router_address.TransportOptions } // Check if the RouterAddress is empty or if it is too small to contain valid data. func (router_address RouterAddress) checkValid() (err error, exit bool) { - /*addr_len := len(router_address) - exit = false - if addr_len == 0 { - log.WithFields(log.Fields{ - "at": "(RouterAddress) checkValid", - "reason": "no data", - }).Error("invalid router address") - err = errors.New("error parsing RouterAddress: no data") - exit = true - } else if addr_len < ROUTER_ADDRESS_MIN_SIZE { - log.WithFields(log.Fields{ - "at": "(RouterAddress) checkValid", - "reason": "data too small (len < ROUTER_ADDRESS_MIN_SIZE)", - }).Warn("router address format warning") - err = errors.New("warning parsing RouterAddress: data too small") - }*/ - if router_address.parserErr != nil { - exit = true - } return } @@ -135,62 +283,40 @@ func (router_address RouterAddress) checkValid() (err error, exit bool) { // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) { - if data == nil || len(data) == 0 { - log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("no data") + if len(data) == 0 { + log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("error parsing RouterAddress: no data") err = errors.New("error parsing RouterAddress: no data") - router_address.parserErr = err return } - cost, remainder, err := NewInteger([]byte{data[0]}, 1) - router_address.cost = cost + router_address.TransportCost, remainder, err = NewInteger(data, 1) if err != nil { log.WithFields(log.Fields{ "at": "(RouterAddress) ReadNewRouterAddress", "reason": "error parsing cost", }).Warn("error parsing RouterAddress") - router_address.parserErr = err } - expiration, remainder, err := NewDate(remainder) - router_address.expiration = expiration + router_address.ExpirationDate, remainder, err = NewDate(remainder) if err != nil { log.WithFields(log.Fields{ "at": "(RouterAddress) ReadNewRouterAddress", "reason": "error parsing expiration", }).Error("error parsing RouterAddress") - router_address.parserErr = err } - Transport_Style, remainder, err := NewI2PString(remainder) - router_address.Transport_Style = Transport_Style + router_address.TransportType, remainder, err = ReadI2PString(remainder) if err != nil { log.WithFields(log.Fields{ "at": "(RouterAddress) ReadNewRouterAddress", - "reason": "error parsing Transport_Style", + "reason": "error parsing transport_style", }).Error("error parsing RouterAddress") - router_address.parserErr = err } - options, remainder, errs := NewMapping(remainder) + var errs []error + router_address.TransportOptions, remainder, errs = NewMapping(remainder) for _, err := range errs { log.WithFields(log.Fields{ "at": "(RouterAddress) ReadNewRouterAddress", "reason": "error parsing options", - }).Error("error parsing RouterAddress") - router_address.parserErr = err - } - router_address.options = options - if err != nil { - log.WithFields(log.Fields{ - "at": "(RouterAddress) ReadNewRouterAddress", - "reason": "error parsing options", - }).Error("error parsing RouterAddress") - router_address.parserErr = err + "error": err, + }).Error("error parsing RozuterAddress") } return } - -// NewRouterAddress creates a new *RouterAddress from []byte using ReadRouterAddress. -// Returns a pointer to RouterAddress unlike ReadRouterAddress. -func NewRouterAddress(data []byte) (router_address *RouterAddress, remainder []byte, err error) { - objrouteraddress, remainder, err := ReadRouterAddress(data) - router_address = &objrouteraddress - return -} diff --git a/lib/common/router_address/router_address_test.go b/lib/common/router_address/router_address_test.go index 6cb90c8..153f83b 100644 --- a/lib/common/router_address/router_address_test.go +++ b/lib/common/router_address/router_address_test.go @@ -31,7 +31,6 @@ func TestCheckRouterAddressValidReportsDataMissing(t *testing.T) { err, exit := router_address.checkValid() assert.Equal(exit, false, "checkValid indicates to stop parsing when some fields may be present") - } func TestCheckRouterAddressValidNoErrWithValidData(t *testing.T) { @@ -40,8 +39,8 @@ func TestCheckRouterAddressValidNoErrWithValidData(t *testing.T) { router_address, _, _ := ReadRouterAddress([]byte{0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}) mapping, err := GoMapToMapping(map[string]string{"host": "127.0.0.1", "port": "4567"}) assert.Nil(err, "GoMapToMapping() returned error with valid data") - router_address.options = mapping - //router_address = append(router_address, mapping...) + router_address.TransportOptions = mapping + // router_address = append(router_address, mapping...) err, exit := router_address.checkValid() assert.Nil(err, "checkValid() reported error with valid data") diff --git a/lib/common/router_identity/router_identity.go b/lib/common/router_identity/router_identity.go index 0cb6f17..86d86c9 100644 --- a/lib/common/router_identity/router_identity.go +++ b/lib/common/router_identity/router_identity.go @@ -20,24 +20,16 @@ Identical to KeysAndCert. // // https://geti2p.net/spec/common-structures#routeridentity type RouterIdentity struct { - *KeysAndCert + KeysAndCert } // ReadRouterIdentity returns RouterIdentity from a []byte. // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadRouterIdentity(data []byte) (router_identity RouterIdentity, remainder []byte, err error) { - keys_and_cert, remainder, err := NewKeysAndCert(data) + keys_and_cert, remainder, err := ReadKeysAndCert(data) router_identity = RouterIdentity{ keys_and_cert, } return } - -// NewRouterIdentity creates a new *RouterIdentity from []byte using ReadRouterIdentity. -// Returns a pointer to RouterIdentity unlike ReadRouterIdentity. -func NewRouterIdentity(data []byte) (router_identity *RouterIdentity, remainder []byte, err error) { - objrouter_identity, remainder, err := ReadRouterIdentity(data) - router_identity = &objrouter_identity - return -} diff --git a/lib/common/router_info/router_info.go b/lib/common/router_info/router_info.go index 945019d..9235f6c 100644 --- a/lib/common/router_info/router_info.go +++ b/lib/common/router_info/router_info.go @@ -3,7 +3,7 @@ package router_info import ( "errors" - "net" + "strconv" "strings" . "github.com/go-i2p/go-i2p/lib/common/data" @@ -15,6 +15,11 @@ import ( const ROUTER_INFO_MIN_SIZE = 439 +const ( + MIN_GOOD_VERSION = 58 + MAX_GOOD_VERSION = 99 +) + /* [RouterInfo] Accurate for version 0.9.49 @@ -99,7 +104,7 @@ signature :: Signature // // https://geti2p.net/spec/common-structures#routerinfo type RouterInfo struct { - router_identity *RouterIdentity + router_identity RouterIdentity published *Date size *Integer addresses []*RouterAddress @@ -108,13 +113,8 @@ type RouterInfo struct { signature *Signature } -var routerInfoTest net.Addr = &RouterInfo{} - // Bytes returns the RouterInfo as a []byte suitable for writing to a stream. -func (router_info RouterInfo) Bytes() ([]byte, error) { - var err error - var bytes []byte - +func (router_info RouterInfo) Bytes() (bytes []byte, err error) { bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...) bytes = append(bytes, router_info.published.Bytes()...) bytes = append(bytes, router_info.size.Bytes()...) @@ -122,45 +122,34 @@ func (router_info RouterInfo) Bytes() ([]byte, error) { bytes = append(bytes, router_address.Bytes()...) } bytes = append(bytes, router_info.peer_size.Bytes()...) - //bytes = append(bytes, router_info.options.Bytes()...) + bytes = append(bytes, router_info.options.Data()...) bytes = append(bytes, []byte(*router_info.signature)...) return bytes, err } -// Network Implements net.Addr, returns comma-separated list of transport types -func (router_info *RouterInfo) Network() string { - var str []string - for _, addr := range router_info.addresses { - t, err := addr.Transport_Style.Data() - if err != nil { - return strings.Join(str, ",") - } - str = append(str, t) +func (router_info RouterInfo) String() string { + str := "Certificate: " + string(router_info.router_identity.KeysAndCert.Bytes()) + str += "Published: " + string(router_info.published.Bytes()) + str += "Addresses:" + string(router_info.size.Bytes()) + for index, router_address := range router_info.addresses { + str += "Address " + strconv.Itoa(index) + ": " + router_address.String() } - return strings.Join(str, ",") -} - -// String Implements net.Addr, returns router-info `Bytes` converted to a string -func (router_info *RouterInfo) String() string { - bytes, err := router_info.Bytes() - if err != nil { - // TODO handle this issue - return "" - } - return string(bytes) + str += "Peer Size: " + string(router_info.peer_size.Bytes()) + str += "Options: " + string(router_info.options.Data()) + str += "Signature: " + string([]byte(*router_info.signature)) + return str } // RouterIdentity returns the router identity as *RouterIdentity. func (router_info *RouterInfo) RouterIdentity() *RouterIdentity { - return router_info.router_identity + return &router_info.router_identity } // IndentHash returns the identity hash (sha256 sum) for this RouterInfo. func (router_info *RouterInfo) IdentHash() Hash { - ri := router_info.RouterIdentity() - h := HashData(ri.KeysAndCert.Certificate().Data()) - return h + data, _ := router_info.RouterIdentity().KeyCertificate.Data() + return HashData(data) } // Published returns the date this RouterInfo was published as an I2P Date. @@ -190,73 +179,21 @@ func (router_info RouterInfo) Options() (mapping Mapping) { return *router_info.options } -// -// Return the signature of this router info -// - // Signature returns the signature for this RouterInfo as an I2P Signature. func (router_info RouterInfo) Signature() (signature Signature) { return *router_info.signature } -// -// Used during parsing to determine where in the RouterInfo the Mapping data begins. -// -/*func (router_info RouterInfo) optionsLocation() (location int) { - data, remainder, err := ReadRouterIdentity(router_info) - if err != nil { - return - } - location += len(data) - - remainder_len := len(remainder) - if remainder_len < 9 { - log.WithFields(log.Fields{ - "at": "(RouterInfo) optionsLocation", - "data_len": remainder_len, - "required_len": 9, - "reason": "not enough data", - }).Error("error parsing router info") - err = errors.New("error parsing router addresses: not enough data") - return - } - location += 9 - - remaining := remainder[9:] - var router_address RouterAddress - var router_addresses []RouterAddress - addr_count, cerr := router_info.RouterAddressCount() - if cerr != nil { - err = cerr - return - } - for i := 0; i < addr_count; i++ { - router_address, remaining, err = ReadRouterAddress(remaining) - if err == nil { - location += len(router_address) - router_addresses = append(router_addresses, router_address) - } - } - location += 1 - return -}*/ - -// -// Used during parsing to determine the size of the options in the RouterInfo. -// -/*func (router_info RouterInfo) optionsSize() (size int) { - head := router_info.optionsLocation() - s := Integer(router_info[head : head+2]) - size = s.Int() + 2 - return -}*/ +// Network implements net.Addr +func (router_info RouterInfo) Network() string { + return "i2p" +} // ReadRouterInfo returns RouterInfo from a []byte. // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) { - identity, remainder, err := NewRouterIdentity(bytes) - info.router_identity = identity + info.router_identity, remainder, err = ReadRouterIdentity(bytes) if err != nil { log.WithFields(log.Fields{ "at": "(RouterInfo) ReadRouterInfo", @@ -265,9 +202,9 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) "reason": "not enough data", }).Error("error parsing router info") err = errors.New("error parsing router info: not enough data") + return } - date, remainder, err := NewDate(remainder) - info.published = date + info.published, remainder, err = NewDate(remainder) if err != nil { log.WithFields(log.Fields{ "at": "(RouterInfo) ReadRouterInfo", @@ -277,36 +214,32 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) }).Error("error parsing router info") err = errors.New("error parsing router info: not enough data") } - size, remainder, err := NewInteger(remainder, 1) - info.size = size + info.size, remainder, err = NewInteger(remainder, 1) if err != nil { log.WithFields(log.Fields{ "at": "(RouterInfo) ReadRouterInfo", "data_len": len(remainder), - "required_len": size.Int(), - "reason": "not enough data", - }).Error("error parsing router info") - err = errors.New("error parsing router info: not enough data") + "required_len": info.size.Int(), + "reason": "read error", + }).Error("error parsing router info size") } - addresses := make([]*RouterAddress, size.Int()) - for i := 0; i < size.Int(); i++ { - address, remainder, err := NewRouterAddress(remainder) + for i := 0; i < info.size.Int(); i++ { + address, more, err := ReadRouterAddress(remainder) + remainder = more if err != nil { log.WithFields(log.Fields{ "at": "(RouterInfo) ReadRouterInfo", "data_len": len(remainder), //"required_len": ROUTER_ADDRESS_SIZE, "reason": "not enough data", - }).Error("error parsing router info") + }).Error("error parsing router address") err = errors.New("error parsing router info: not enough data") } - addresses = append(addresses, address) + info.addresses = append(info.addresses, &address) } - info.addresses = addresses - peer_size := Integer(remainder[:1]) - info.peer_size = &peer_size - remainder = remainder[1:] - options, remainder, errs := NewMapping(remainder) + info.peer_size, remainder, err = NewInteger(remainder, 1) + var errs []error + info.options, remainder, errs = NewMapping(remainder) if len(errs) != 0 { log.WithFields(log.Fields{ "at": "(RouterInfo) ReadRouterInfo", @@ -320,7 +253,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) } err = errors.New("error parsing router info: " + estring) } - info.options = options + info.signature, remainder, err = NewSignature(remainder) if err != nil { log.WithFields(log.Fields{ "at": "(RouterInfo) ReadRouterInfo", @@ -333,10 +266,57 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) return } -// NewRouterInfo creates a new *RouterInfo from []byte using ReadRouterInfo. -// Returns a pointer to RouterInfo unlike ReadRouterInfo. -func NewRouterInfo(data []byte) (router_info *RouterInfo, remainder []byte, err error) { - routerInfo, remainder, err := ReadRouterInfo(data) - router_info = &routerInfo - return +func (router_info *RouterInfo) RouterCapabilities() string { + str, err := ToI2PString("caps") + if err != nil { + return "" + } + return string(router_info.options.Values().Get(str)) +} + +func (router_info *RouterInfo) RouterVersion() string { + str, err := ToI2PString("router.version") + if err != nil { + return "" + } + return string(router_info.options.Values().Get(str)) +} + +func (router_info *RouterInfo) GoodVersion() bool { + version := router_info.RouterVersion() + v := strings.Split(version, ".") + if len(v) != 3 { + return false + } + if v[0] == "0" { + if v[1] == "9" { + val, _ := strconv.Atoi(v[2]) + if val >= MIN_GOOD_VERSION && val <= MAX_GOOD_VERSION { + return true + } + } + } + return false +} + +func (router_info *RouterInfo) UnCongested() bool { + caps := router_info.RouterCapabilities() + if strings.Contains(caps, "K") { + return false + } + if strings.Contains(caps, "G") { + return false + } + if strings.Contains(caps, "E") { + return false + } + return true +} + +func (router_info *RouterInfo) Reachable() bool { + caps := router_info.RouterCapabilities() + if strings.Contains(caps, "U") { + return false + } + return strings.Contains(caps, "R") } diff --git a/lib/common/router_info/router_info_test.go b/lib/common/router_info/router_info_test.go index 4aeb2e7..11fb4c4 100644 --- a/lib/common/router_info/router_info_test.go +++ b/lib/common/router_info/router_info_test.go @@ -131,7 +131,6 @@ func TestRouterAddressesReturnsAddresses(t *testing.T) { ), ) } - } func TestRouterAddressesReturnsAddressesWithMultiple(t *testing.T) { @@ -162,7 +161,6 @@ func TestRouterAddressesReturnsAddressesWithMultiple(t *testing.T) { ) } } - } func TestPeerSizeIsZero(t *testing.T) { @@ -200,7 +198,7 @@ func TestRouterIdentityIsCorrect(t *testing.T) { router_info, _ := buildFullRouterInfo() router_identity := router_info.RouterIdentity() - //assert.Nil(err) + // assert.Nil(err) assert.Equal( 0, bytes.Compare( From 524526d946a2a7ddb414c5d54d8a711efaa5a4eb Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Thu, 3 Oct 2024 21:41:31 -0400 Subject: [PATCH 12/94] Bring in crypto stubs from master --- go.mod | 23 ++++++++----- go.sum | 32 +++++++----------- lib/crypto/ed25519.go | 77 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 29 deletions(-) diff --git a/go.mod b/go.mod index f1c3ad3..3e05055 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,20 @@ module github.com/go-i2p/go-i2p -go 1.16 +go 1.22 + +toolchain go1.22.5 require ( - github.com/dchest/siphash v1.2.3 // indirect github.com/emirpasic/gods v1.18.1 - github.com/flynn/noise v1.0.0 - github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620 - github.com/pkg/errors v0.9.1 // indirect - github.com/sirupsen/logrus v1.9.0 - github.com/stretchr/testify v1.7.0 - golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa - golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect + github.com/flynn/noise v1.1.0 + github.com/sirupsen/logrus v1.9.3 + github.com/stretchr/testify v1.9.0 + golang.org/x/crypto v0.26.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/sys v0.24.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index c2f6282..a670cc9 100644 --- a/go.sum +++ b/go.sum @@ -1,45 +1,37 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= -github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= -github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620 h1:MjTFQi2DyJifqefRVjAs+P2gaoUAj2rcDpYX7ERggEA= -github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620/go.mod h1:y9SBFk2hEIPWY7Aj3bXG+K1xp8wWnQ6kVq2wsYSPByU= +github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= +github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lib/crypto/ed25519.go b/lib/crypto/ed25519.go index 3a2db82..f569677 100644 --- a/lib/crypto/ed25519.go +++ b/lib/crypto/ed25519.go @@ -2,10 +2,16 @@ package crypto import ( "crypto/ed25519" + "crypto/rand" + "crypto/sha256" "crypto/sha512" "errors" + "io" + "math/big" ) +var Ed25519EncryptTooBig = errors.New("failed to encrypt data, too big for Ed25519") + type Ed25519PublicKey []byte type Ed25519Verifier struct { @@ -19,6 +25,77 @@ func (k Ed25519PublicKey) NewVerifier() (v Verifier, err error) { return temp, nil } +func (k Ed25519PublicKey) Len() int { + return len(k) +} + +func createEd25519PublicKey(data []byte) (k *ed25519.PublicKey) { + if len(data) == 256 { + k2 := ed25519.PublicKey{} + copy(k2[:], data) + k = &k2 + } + return +} + +func createEd25519Encryption(pub *ed25519.PublicKey, rand io.Reader) (enc *Ed25519Encryption, err error) { + /*kbytes := make([]byte, 256) + k := new(big.Int) + for err == nil { + _, err = io.ReadFull(rand, kbytes) + k = new(big.Int).SetBytes(kbytes) + k = k.Mod(k, pub.P) + if k.Sign() != 0 { + break + } + } + if err == nil { + enc = &Ed25519Encryption{} + }*/ + return +} + +type Ed25519Encryption struct { + p, a, b1 *big.Int +} + +func (ed25519 *Ed25519Encryption) Encrypt(data []byte) (enc []byte, err error) { + return ed25519.EncryptPadding(data, true) +} + +func (ed25519 *Ed25519Encryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error) { + if len(data) > 222 { + err = Ed25519EncryptTooBig + return + } + mbytes := make([]byte, 255) + mbytes[0] = 0xFF + copy(mbytes[33:], data) + // do sha256 of payload + d := sha256.Sum256(mbytes[33 : len(data)+33]) + copy(mbytes[1:], d[:]) + m := new(big.Int).SetBytes(mbytes) + // do encryption + b := new(big.Int).Mod(new(big.Int).Mul(ed25519.b1, m), ed25519.p).Bytes() + + if zeroPadding { + encrypted = make([]byte, 514) + copy(encrypted[1:], ed25519.a.Bytes()) + copy(encrypted[258:], b) + } else { + encrypted = make([]byte, 512) + copy(encrypted, ed25519.a.Bytes()) + copy(encrypted[256:], b) + } + return +} + +func (elg Ed25519PublicKey) NewEncrypter() (enc Encrypter, err error) { + k := createEd25519PublicKey(elg[:]) + enc, err = createEd25519Encryption(k, rand.Reader) + return +} + func (v *Ed25519Verifier) VerifyHash(h, sig []byte) (err error) { if len(sig) != ed25519.SignatureSize { err = ErrBadSignatureSize From 08a0d9274242b1cf4ee3038680553275696113e0 Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Thu, 3 Oct 2024 21:52:49 -0400 Subject: [PATCH 13/94] gofmt --- lib/bootstrap/doc.go | 2 - lib/crypto/decrypt.go | 1 - lib/crypto/doc.go | 2 - lib/crypto/dsa_test.go | 3 +- lib/crypto/ecdsa.go | 18 ++- lib/crypto/elg.go | 21 ++-- lib/crypto/elg_test.go | 6 +- lib/crypto/encrypt.go | 1 - lib/crypto/hmac.go | 15 +-- lib/crypto/rsa.go | 18 ++- lib/crypto/sign.go | 8 +- lib/crypto/tunnel.go | 1 - lib/i2np/build_request_record.go | 6 +- lib/i2np/build_request_record_test.go | 1 - lib/i2np/build_response_record.go | 6 +- lib/netdb/doc.go | 4 - lib/netdb/std.go | 10 +- lib/router/router.go | 3 +- lib/su3/su3.go | 121 ++++++++++---------- lib/su3/su3_test.go | 15 ++- lib/transport/doc.go | 6 +- lib/transport/messages/message.go | 10 +- lib/transport/noise/encrdecr_packet_test.go | 3 +- lib/transport/noise/incoming_handshake.go | 2 +- lib/transport/noise/noise_constants.go | 2 +- lib/transport/noise/outgoing_handshake.go | 4 +- lib/transport/noise/read_session.go | 2 +- lib/transport/noise/session.go | 8 +- lib/transport/noise/transport_test.go | 2 +- lib/transport/noise/write_session.go | 4 +- lib/transport/ssu/doc.go | 2 - lib/tunnel/delivery.go | 6 +- lib/tunnel/doc.go | 2 +- lib/tunnel/message.go | 6 +- lib/tunnel/message_test.go | 6 +- lib/tunnel/pool.go | 3 +- lib/util/signals/unix.go | 2 +- lib/util/signals/windows.go | 2 +- 38 files changed, 177 insertions(+), 157 deletions(-) diff --git a/lib/bootstrap/doc.go b/lib/bootstrap/doc.go index c85b2ad..85df9c9 100644 --- a/lib/bootstrap/doc.go +++ b/lib/bootstrap/doc.go @@ -1,4 +1,2 @@ -// // provides generic interfaces for initial bootstrap into network and network reseeding -// package bootstrap diff --git a/lib/crypto/decrypt.go b/lib/crypto/decrypt.go index a22f32d..a3fd616 100644 --- a/lib/crypto/decrypt.go +++ b/lib/crypto/decrypt.go @@ -8,7 +8,6 @@ type Decrypter interface { } type PrivateEncryptionKey interface { - // create a new decryption object for this private key to decrypt data encrypted to our public key // returns decrypter or nil and error if the private key is in a bad format NewDecrypter() (Decrypter, error) diff --git a/lib/crypto/doc.go b/lib/crypto/doc.go index 5a7dfa5..0f48d76 100644 --- a/lib/crypto/doc.go +++ b/lib/crypto/doc.go @@ -1,4 +1,2 @@ -// // package for i2p specific crpytography -// package crypto diff --git a/lib/crypto/dsa_test.go b/lib/crypto/dsa_test.go index 453048a..5ca8967 100644 --- a/lib/crypto/dsa_test.go +++ b/lib/crypto/dsa_test.go @@ -2,9 +2,10 @@ package crypto import ( "crypto/rand" - log "github.com/sirupsen/logrus" "io" "testing" + + log "github.com/sirupsen/logrus" ) func TestDSA(t *testing.T) { diff --git a/lib/crypto/ecdsa.go b/lib/crypto/ecdsa.go index feadedf..1e76e0f 100644 --- a/lib/crypto/ecdsa.go +++ b/lib/crypto/ecdsa.go @@ -44,8 +44,10 @@ func createECVerifier(c elliptic.Curve, h crypto.Hash, k []byte) (ev *ECDSAVerif return } -type ECP256PublicKey [64]byte -type ECP256PrivateKey [32]byte +type ( + ECP256PublicKey [64]byte + ECP256PrivateKey [32]byte +) func (k ECP256PublicKey) Len() int { return len(k) @@ -55,8 +57,10 @@ func (k ECP256PublicKey) NewVerifier() (Verifier, error) { return createECVerifier(elliptic.P256(), crypto.SHA256, k[:]) } -type ECP384PublicKey [96]byte -type ECP384PrivateKey [48]byte +type ( + ECP384PublicKey [96]byte + ECP384PrivateKey [48]byte +) func (k ECP384PublicKey) Len() int { return len(k) @@ -66,8 +70,10 @@ func (k ECP384PublicKey) NewVerifier() (Verifier, error) { return createECVerifier(elliptic.P384(), crypto.SHA384, k[:]) } -type ECP521PublicKey [132]byte -type ECP521PrivateKey [66]byte +type ( + ECP521PublicKey [132]byte + ECP521PrivateKey [66]byte +) func (k ECP521PublicKey) Len() int { return len(k) diff --git a/lib/crypto/elg.go b/lib/crypto/elg.go index 1e93b88..853f37d 100644 --- a/lib/crypto/elg.go +++ b/lib/crypto/elg.go @@ -5,9 +5,10 @@ import ( "crypto/sha256" "crypto/subtle" "errors" - "golang.org/x/crypto/openpgp/elgamal" "io" "math/big" + + "golang.org/x/crypto/openpgp/elgamal" ) var elgp = new(big.Int).SetBytes([]byte{ @@ -29,11 +30,15 @@ var elgp = new(big.Int).SetBytes([]byte{ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }) -var one = big.NewInt(1) -var elgg = big.NewInt(2) +var ( + one = big.NewInt(1) + elgg = big.NewInt(2) +) -var ElgDecryptFail = errors.New("failed to decrypt elgamal encrypted data") -var ElgEncryptTooBig = errors.New("failed to encrypt data, too big for elgamal") +var ( + ElgDecryptFail = errors.New("failed to decrypt elgamal encrypted data") + ElgEncryptTooBig = errors.New("failed to encrypt data, too big for elgamal") +) // generate an elgamal key pair func ElgamalGenerate(priv *elgamal.PrivateKey, rand io.Reader) (err error) { @@ -183,8 +188,10 @@ func createElgamalEncryption(pub *elgamal.PublicKey, rand io.Reader) (enc *Elgam return } -type ElgPublicKey [256]byte -type ElgPrivateKey [256]byte +type ( + ElgPublicKey [256]byte + ElgPrivateKey [256]byte +) func (elg ElgPublicKey) Len() int { return len(elg) diff --git a/lib/crypto/elg_test.go b/lib/crypto/elg_test.go index 58cef06..36b7c0e 100644 --- a/lib/crypto/elg_test.go +++ b/lib/crypto/elg_test.go @@ -3,10 +3,11 @@ package crypto import ( "bytes" "crypto/rand" - log "github.com/sirupsen/logrus" - "golang.org/x/crypto/openpgp/elgamal" "io" "testing" + + log "github.com/sirupsen/logrus" + "golang.org/x/crypto/openpgp/elgamal" ) func BenchmarkElgGenerate(b *testing.B) { @@ -46,7 +47,6 @@ func BenchmarkElgDecrypt(b *testing.B) { } } log.Infof("%d fails %d rounds", fails, b.N) - } func BenchmarkElgEncrypt(b *testing.B) { diff --git a/lib/crypto/encrypt.go b/lib/crypto/encrypt.go index 835b215..e42451d 100644 --- a/lib/crypto/encrypt.go +++ b/lib/crypto/encrypt.go @@ -8,7 +8,6 @@ type Encrypter interface { } type PublicEncryptionKey interface { - // create a new encrypter to encrypt data to this public key NewEncrypter() (Encrypter, error) diff --git a/lib/crypto/hmac.go b/lib/crypto/hmac.go index 5a4e6f9..dd13e1e 100644 --- a/lib/crypto/hmac.go +++ b/lib/crypto/hmac.go @@ -4,11 +4,15 @@ import ( "crypto/md5" ) -const IPAD = byte(0x36) -const OPAD = byte(0x5C) +const ( + IPAD = byte(0x36) + OPAD = byte(0x5C) +) -type HMACKey [32]byte -type HMACDigest [16]byte +type ( + HMACKey [32]byte + HMACDigest [16]byte +) func (hk HMACKey) xor(p byte) (i []byte) { i = make([]byte, 64) @@ -23,11 +27,8 @@ func (hk HMACKey) xor(p byte) (i []byte) { return } -// // do i2p hmac -// func I2PHMAC(data []byte, k HMACKey) (d HMACDigest) { - buff := make([]byte, 64+len(data)) ip := k.xor(IPAD) copy(buff, ip) diff --git a/lib/crypto/rsa.go b/lib/crypto/rsa.go index 61c808d..7e46f7e 100644 --- a/lib/crypto/rsa.go +++ b/lib/crypto/rsa.go @@ -1,10 +1,16 @@ package crypto -type RSA2048PublicKey [256]byte -type RSA2048PrivateKey [512]byte +type ( + RSA2048PublicKey [256]byte + RSA2048PrivateKey [512]byte +) -type RSA3072PublicKey [384]byte -type RSA3072PrivateKey [786]byte +type ( + RSA3072PublicKey [384]byte + RSA3072PrivateKey [786]byte +) -type RSA4096PublicKey [512]byte -type RSA4096PrivateKey [1024]byte +type ( + RSA4096PublicKey [512]byte + RSA4096PrivateKey [1024]byte +) diff --git a/lib/crypto/sign.go b/lib/crypto/sign.go index b3b4ccb..0b88678 100644 --- a/lib/crypto/sign.go +++ b/lib/crypto/sign.go @@ -4,9 +4,11 @@ import ( "errors" ) -var ErrBadSignatureSize = errors.New("bad signature size") -var ErrInvalidKeyFormat = errors.New("invalid key format") -var ErrInvalidSignature = errors.New("invalid signature") +var ( + ErrBadSignatureSize = errors.New("bad signature size") + ErrInvalidKeyFormat = errors.New("invalid key format") + ErrInvalidSignature = errors.New("invalid signature") +) // type for verifying signatures type Verifier interface { diff --git a/lib/crypto/tunnel.go b/lib/crypto/tunnel.go index 4ce2539..e681fec 100644 --- a/lib/crypto/tunnel.go +++ b/lib/crypto/tunnel.go @@ -19,7 +19,6 @@ type Tunnel struct { } func NewTunnelCrypto(layerKey, ivKey TunnelKey) (t *Tunnel, err error) { - t = new(Tunnel) t.layerKey, err = aes.NewCipher(layerKey[:]) if err == nil { diff --git a/lib/i2np/build_request_record.go b/lib/i2np/build_request_record.go index 827f1ba..d986b06 100644 --- a/lib/i2np/build_request_record.go +++ b/lib/i2np/build_request_record.go @@ -149,8 +149,10 @@ padding :: Data total length: 222 */ -type BuildRequestRecordElGamalAES [528]byte -type BuildRequestRecordElGamal [528]byte +type ( + BuildRequestRecordElGamalAES [528]byte + BuildRequestRecordElGamal [528]byte +) type BuildRequestRecord struct { ReceiveTunnel tunnel.TunnelID diff --git a/lib/i2np/build_request_record_test.go b/lib/i2np/build_request_record_test.go index b381df1..451c0a4 100644 --- a/lib/i2np/build_request_record_test.go +++ b/lib/i2np/build_request_record_test.go @@ -14,7 +14,6 @@ func TestReadBuildRequestRecordReceiveTunnelTooLittleData(t *testing.T) { receive_tunnel, err := readBuildRequestRecordReceiveTunnel([]byte{0x01}) assert.Equal(tunnel.TunnelID(0), receive_tunnel) assert.Equal(ERR_BUILD_REQUEST_RECORD_NOT_ENOUGH_DATA, err) - } func TestReadBuildRequestRecordReceiveTunnelValidData(t *testing.T) { diff --git a/lib/i2np/build_response_record.go b/lib/i2np/build_response_record.go index 30f12c7..b405521 100644 --- a/lib/i2np/build_response_record.go +++ b/lib/i2np/build_response_record.go @@ -38,8 +38,10 @@ byte 527 :: reply total length: 528 */ -type BuildResponseRecordELGamalAES [528]byte -type BuildResponseRecordELGamal [528]byte +type ( + BuildResponseRecordELGamalAES [528]byte + BuildResponseRecordELGamal [528]byte +) type BuildResponseRecord struct { Hash common.Hash diff --git a/lib/netdb/doc.go b/lib/netdb/doc.go index 2d97085..7850708 100644 --- a/lib/netdb/doc.go +++ b/lib/netdb/doc.go @@ -1,5 +1 @@ -// -// -// -// package netdb diff --git a/lib/netdb/std.go b/lib/netdb/std.go index 2933b21..05f0ee2 100644 --- a/lib/netdb/std.go +++ b/lib/netdb/std.go @@ -50,9 +50,7 @@ func (db StdNetDB) Path() string { return string(db) } -// // return how many routers we know about in our network database -// func (db StdNetDB) Size() (routers int) { // TODO: implement this var err error @@ -102,7 +100,7 @@ func (db StdNetDB) RecalculateSize() (err error) { if err == nil { str := fmt.Sprintf("%d", count) var f *os.File - f, err = os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY, 0600) + f, err = os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY, 0o600) if err == nil { _, err = io.WriteString(f, str) f.Close() @@ -131,8 +129,8 @@ func (db StdNetDB) SaveEntry(e *Entry) (err error) { var f io.WriteCloser var h common.Hash h = e.ri.IdentHash() - //if err == nil { - f, err = os.OpenFile(db.SkiplistFile(h), os.O_WRONLY|os.O_CREATE, 0700) + // if err == nil { + f, err = os.OpenFile(db.SkiplistFile(h), os.O_WRONLY|os.O_CREATE, 0o700) if err == nil { err = e.WriteTo(f) f.Close() @@ -160,7 +158,7 @@ func (db StdNetDB) Ensure() (err error) { // create base network database directory func (db StdNetDB) Create() (err error) { - mode := os.FileMode(0700) + mode := os.FileMode(0o700) p := db.Path() log.Infof("Create network database in %s", p) diff --git a/lib/router/router.go b/lib/router/router.go index 92a3e4b..c370718 100644 --- a/lib/router/router.go +++ b/lib/router/router.go @@ -1,10 +1,11 @@ package router import ( + "time" + "github.com/go-i2p/go-i2p/lib/config" "github.com/go-i2p/go-i2p/lib/netdb" log "github.com/sirupsen/logrus" - "time" ) // i2p router type diff --git a/lib/su3/su3.go b/lib/su3/su3.go index 8540442..64d7718 100644 --- a/lib/su3/su3.go +++ b/lib/su3/su3.go @@ -14,47 +14,50 @@ // content the error ErrInvalidSignature will be returned. // // Example usage: -// // Let's say we are reading an SU3 file from an HTTP body, which is an io.Reader. -// su3File, err := su3.Read(body) -// if err != nil { -// // Handle error. -// } -// // Look up this signer's key. -// key := somehow_lookup_the_key(su3File.SignerID) -// // Read the content. -// contentReader := su3File.Content(key) -// bytes, err := ioutil.ReadAll(contentReader) -// if errors.Is(err, su3.ErrInvalidSignature) { -// // The signature is invalid, OR a nil key was provided. -// } else if err != nil { -// // Handle error. -// } +// +// // Let's say we are reading an SU3 file from an HTTP body, which is an io.Reader. +// su3File, err := su3.Read(body) +// if err != nil { +// // Handle error. +// } +// // Look up this signer's key. +// key := somehow_lookup_the_key(su3File.SignerID) +// // Read the content. +// contentReader := su3File.Content(key) +// bytes, err := ioutil.ReadAll(contentReader) +// if errors.Is(err, su3.ErrInvalidSignature) { +// // The signature is invalid, OR a nil key was provided. +// } else if err != nil { +// // Handle error. +// } // // If you want to parse from a []byte, you can wrap it like this: -// mySU3FileBytes := []byte{0x00, 0x01, 0x02, 0x03} -// su3File, err := su3.Read(bytes.NewReader(mySU3FileBytes)) +// +// mySU3FileBytes := []byte{0x00, 0x01, 0x02, 0x03} +// su3File, err := su3.Read(bytes.NewReader(mySU3FileBytes)) // // One of the advantages of this library's design is that you can avoid buffering // the file contents in memory. Here's how you would stream from an HTTP body // directly to disk: -// su3File, err := su3.Read(body) -// if err != nil { -// // Handle error. -// } -// // Look up this signer's key. -// key := somehow_lookup_the_key(su3File.SignerID) -// // Stream directly to disk. -// f, err := os.Create("my_file.txt") -// if err != nil { -// // Handle error. -// } -// _, err := io.Copy(f, su3File.Content(key)) -// if errors.Is(err, su3.ErrInvalidSignature) { -// // The signature is invalid, OR a nil key was provided. -// // Don't trust the file, delete it! -// } else if err != nil { -// // Handle error. -// } +// +// su3File, err := su3.Read(body) +// if err != nil { +// // Handle error. +// } +// // Look up this signer's key. +// key := somehow_lookup_the_key(su3File.SignerID) +// // Stream directly to disk. +// f, err := os.Create("my_file.txt") +// if err != nil { +// // Handle error. +// } +// _, err := io.Copy(f, su3File.Content(key)) +// if errors.Is(err, su3.ErrInvalidSignature) { +// // The signature is invalid, OR a nil key was provided. +// // Don't trust the file, delete it! +// } else if err != nil { +// // Handle error. +// } // // Note: if you want to read the content, the Content() io.Reader must be read // *before* the Signature() io.Reader. If you read the signature first, the @@ -143,29 +146,31 @@ var contentTypes = map[byte]ContentType{ 0x05: BLOCKLIST, } -var ErrMissingMagicBytes = errors.New("missing magic bytes") -var ErrMissingUnusedByte6 = errors.New("missing unused byte 6") -var ErrMissingFileFormatVersion = errors.New("missing or incorrect file format version") -var ErrMissingSignatureType = errors.New("missing or invalid signature type") -var ErrUnsupportedSignatureType = errors.New("unsupported signature type") -var ErrMissingSignatureLength = errors.New("missing signature length") -var ErrMissingUnusedByte12 = errors.New("missing unused byte 12") -var ErrMissingVersionLength = errors.New("missing version length") -var ErrVersionTooShort = errors.New("version length too short") -var ErrMissingUnusedByte14 = errors.New("missing unused byte 14") -var ErrMissingSignerIDLength = errors.New("missing signer ID length") -var ErrMissingContentLength = errors.New("missing content length") -var ErrMissingUnusedByte24 = errors.New("missing unused byte 24") -var ErrMissingFileType = errors.New("missing or invalid file type") -var ErrMissingUnusedByte26 = errors.New("missing unused byte 26") -var ErrMissingContentType = errors.New("missing or invalid content type") -var ErrMissingUnusedBytes28To39 = errors.New("missing unused bytes 28-39") -var ErrMissingVersion = errors.New("missing version") -var ErrMissingSignerID = errors.New("missing signer ID") -var ErrMissingContent = errors.New("missing content") -var ErrMissingSignature = errors.New("missing signature") -var ErrInvalidPublicKey = errors.New("invalid public key") -var ErrInvalidSignature = errors.New("invalid signature") +var ( + ErrMissingMagicBytes = errors.New("missing magic bytes") + ErrMissingUnusedByte6 = errors.New("missing unused byte 6") + ErrMissingFileFormatVersion = errors.New("missing or incorrect file format version") + ErrMissingSignatureType = errors.New("missing or invalid signature type") + ErrUnsupportedSignatureType = errors.New("unsupported signature type") + ErrMissingSignatureLength = errors.New("missing signature length") + ErrMissingUnusedByte12 = errors.New("missing unused byte 12") + ErrMissingVersionLength = errors.New("missing version length") + ErrVersionTooShort = errors.New("version length too short") + ErrMissingUnusedByte14 = errors.New("missing unused byte 14") + ErrMissingSignerIDLength = errors.New("missing signer ID length") + ErrMissingContentLength = errors.New("missing content length") + ErrMissingUnusedByte24 = errors.New("missing unused byte 24") + ErrMissingFileType = errors.New("missing or invalid file type") + ErrMissingUnusedByte26 = errors.New("missing unused byte 26") + ErrMissingContentType = errors.New("missing or invalid content type") + ErrMissingUnusedBytes28To39 = errors.New("missing unused bytes 28-39") + ErrMissingVersion = errors.New("missing version") + ErrMissingSignerID = errors.New("missing signer ID") + ErrMissingContent = errors.New("missing content") + ErrMissingSignature = errors.New("missing signature") + ErrInvalidPublicKey = errors.New("invalid public key") + ErrInvalidSignature = errors.New("invalid signature") +) const magicBytes = "I2Psu3" diff --git a/lib/su3/su3_test.go b/lib/su3/su3_test.go index b56e9bd..aca345c 100644 --- a/lib/su3/su3_test.go +++ b/lib/su3/su3_test.go @@ -9,11 +9,12 @@ import ( "encoding/binary" "encoding/pem" "fmt" - "github.com/stretchr/testify/assert" "io" "io/ioutil" "os" "testing" + + "github.com/stretchr/testify/assert" ) func fileReader(t *testing.T, filename string) io.Reader { @@ -60,11 +61,13 @@ func fileRSAPubKey(t *testing.T, filename string) *rsa.PublicKey { } // This fake data is generated in TestMain. -var aliceFakeKey *rsa.PrivateKey -var bobFakeKey *rsa.PrivateKey -var aliceContent []byte -var aliceSignature []byte -var aliceSU3 []byte +var ( + aliceFakeKey *rsa.PrivateKey + bobFakeKey *rsa.PrivateKey + aliceContent []byte + aliceSignature []byte + aliceSU3 []byte +) func TestRead(t *testing.T) { tests := []struct { diff --git a/lib/transport/doc.go b/lib/transport/doc.go index a1d1685..2e073f7 100644 --- a/lib/transport/doc.go +++ b/lib/transport/doc.go @@ -1,4 +1,6 @@ -/** - i2np messages transports +/* +* + + i2np messages transports */ package transport diff --git a/lib/transport/messages/message.go b/lib/transport/messages/message.go index 8e87f53..f7fc337 100644 --- a/lib/transport/messages/message.go +++ b/lib/transport/messages/message.go @@ -46,10 +46,12 @@ package ntcp type MessageType uint8 -const MessageTypeSessionRequest = 0x00 -const MessageTypeSessionCreated = 0x01 -const MessageTypeSessionConfirmed = 0x02 -const MessageTypeData = 0x03 +const ( + MessageTypeSessionRequest = 0x00 + MessageTypeSessionCreated = 0x01 + MessageTypeSessionConfirmed = 0x02 + MessageTypeData = 0x03 +) type Message interface { // Type returns the message type diff --git a/lib/transport/noise/encrdecr_packet_test.go b/lib/transport/noise/encrdecr_packet_test.go index 678a4a6..ef4dc81 100644 --- a/lib/transport/noise/encrdecr_packet_test.go +++ b/lib/transport/noise/encrdecr_packet_test.go @@ -3,9 +3,10 @@ package noise import ( "crypto/rand" "encoding/binary" + "testing" + "github.com/flynn/noise" "github.com/stretchr/testify/assert" - "testing" ) func TestEncryptDecryptPacketOffline(t *testing.T) { diff --git a/lib/transport/noise/incoming_handshake.go b/lib/transport/noise/incoming_handshake.go index 75abe6a..f9f6116 100644 --- a/lib/transport/noise/incoming_handshake.go +++ b/lib/transport/noise/incoming_handshake.go @@ -28,7 +28,7 @@ func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, e prologue := make([]byte, 2, uint16Size+len(negData)) binary.BigEndian.PutUint16(prologue, uint16(len(negData))) prologue = append(prologue, negData...) - //prologue = append(initString, prologue...) + // prologue = append(initString, prologue...) state, err = noise.NewHandshakeState(noise.Config{ StaticKeypair: s, Initiator: false, diff --git a/lib/transport/noise/noise_constants.go b/lib/transport/noise/noise_constants.go index 7fdab54..1e8a5d8 100644 --- a/lib/transport/noise/noise_constants.go +++ b/lib/transport/noise/noise_constants.go @@ -38,7 +38,7 @@ func initNegotiationData(negotiationData []byte) []byte { return negotiationData } negotiationData = make([]byte, 6) - binary.BigEndian.PutUint16(negotiationData, 1) //version + binary.BigEndian.PutUint16(negotiationData, 1) // version negotiationData[2] = NOISE_DH_CURVE25519 negotiationData[3] = NOISE_CIPHER_CHACHAPOLY negotiationData[4] = NOISE_HASH_SHA256 diff --git a/lib/transport/noise/outgoing_handshake.go b/lib/transport/noise/outgoing_handshake.go index 5786924..0303a78 100644 --- a/lib/transport/noise/outgoing_handshake.go +++ b/lib/transport/noise/outgoing_handshake.go @@ -13,9 +13,7 @@ import ( func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) { if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() { - return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported") - } negData = make([]byte, 6) copy(negData, initNegotiationData(nil)) @@ -30,7 +28,7 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, prologue := make([]byte, 2, uint16Size+len(negData)) binary.BigEndian.PutUint16(prologue, uint16(len(negData))) prologue = append(prologue, negData...) - //prologue = append(initString, prologue...) + // prologue = append(initString, prologue...) state, err = noise.NewHandshakeState(noise.Config{ StaticKeypair: s, Initiator: true, diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go index da32f8b..35c0fda 100644 --- a/lib/transport/noise/read_session.go +++ b/lib/transport/noise/read_session.go @@ -71,7 +71,7 @@ func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { func (c *NoiseSession) readPacketLocked(data []byte) (int, error) { var n int - if len(data) == 0 { //special case to answer when everything is ok during handshake + if len(data) == 0 { // special case to answer when everything is ok during handshake if _, err := c.Conn.Read(make([]byte, 2)); err != nil { return 0, err } diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index 8938039..90a8ee6 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -52,8 +52,10 @@ func (noise_session *NoiseSession) SetWriteDeadline(t time.Time) error { return noise_session.Conn.SetWriteDeadline(t) } -var exampleNoiseSession transport.TransportSession = &NoiseSession{} -var ExampleNoiseSession net.Conn = exampleNoiseSession.(*NoiseSession) +var ( + exampleNoiseSession transport.TransportSession = &NoiseSession{} + ExampleNoiseSession net.Conn = exampleNoiseSession.(*NoiseSession) +) func (s *NoiseSession) LocalAddr() net.Addr { return s.Conn.LocalAddr() @@ -81,7 +83,7 @@ func newBlock() []byte { type VerifyCallbackFunc func(publicKey []byte, data []byte) error func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSession, error) { - //socket, err := DialNoise("noise", ri) + // socket, err := DialNoise("noise", ri) for _, addr := range ri.RouterAddresses() { socket, err := net.Dial("tcp", string(addr.Bytes())) if err != nil { diff --git a/lib/transport/noise/transport_test.go b/lib/transport/noise/transport_test.go index a6cc0c2..52f06e3 100644 --- a/lib/transport/noise/transport_test.go +++ b/lib/transport/noise/transport_test.go @@ -29,5 +29,5 @@ func TestTransport(t *testing.T) { } ntt := NewNoiseTransport(lnn) t.Log(ntt.Name()) - //ntt.GetSession() + // ntt.GetSession() } diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index 7768880..35b4d29 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -50,7 +50,7 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { if err != nil { return 0, nil, fmt.Errorf("failed to encrypt: '%w'", err) } - //m := len(encryptedData) + // m := len(encryptedData) lengthPrefix := make([]byte, 2) binary.BigEndian.PutUint16(lengthPrefix, uint16(len(encryptedData))) @@ -81,7 +81,7 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { var n int - if len(data) == 0 { //special case to answer when everything is ok during handshake + if len(data) == 0 { // special case to answer when everything is ok during handshake if _, err := c.Conn.Write(make([]byte, 2)); err != nil { return 0, err } diff --git a/lib/transport/ssu/doc.go b/lib/transport/ssu/doc.go index cdb1c41..6b3b9c4 100644 --- a/lib/transport/ssu/doc.go +++ b/lib/transport/ssu/doc.go @@ -1,6 +1,4 @@ /* - i2p ssu transport implementation - */ package ssu diff --git a/lib/tunnel/delivery.go b/lib/tunnel/delivery.go index 0f57067..336940f 100644 --- a/lib/tunnel/delivery.go +++ b/lib/tunnel/delivery.go @@ -380,8 +380,9 @@ func (delivery_instructions DeliveryInstructions) TunnelID() (tunnel_id uint32, } // Return the hash for these DeliveryInstructions, which varies by hash type. -// If the type is DT_TUNNEL, hash is the SHA256 of the gateway router, if -// the type is DT_ROUTER it is the SHA256 of the router. +// +// If the type is DT_TUNNEL, hash is the SHA256 of the gateway router, if +// the type is DT_ROUTER it is the SHA256 of the router. func (delivery_instructions DeliveryInstructions) Hash() (hash common.Hash, err error) { delivery_type, err := delivery_instructions.DeliveryType() if err != nil { @@ -707,6 +708,7 @@ func maybeAppendDelay(di_flag DeliveryInstructions, data, current []byte) (now [ } return } + func maybeAppendMessageID(di_flag DeliveryInstructions, di_type int, data, current []byte) (now []byte, err error) { if di_type == FIRST_FRAGMENT { if fragmented, _ := di_flag.Fragmented(); fragmented { diff --git a/lib/tunnel/doc.go b/lib/tunnel/doc.go index a207b64..57161e6 100644 --- a/lib/tunnel/doc.go +++ b/lib/tunnel/doc.go @@ -1,4 +1,4 @@ /* - i2p garlic tunnel implementation +i2p garlic tunnel implementation */ package tunnel diff --git a/lib/tunnel/message.go b/lib/tunnel/message.go index 4148ecd..af72ed7 100644 --- a/lib/tunnel/message.go +++ b/lib/tunnel/message.go @@ -2,6 +2,7 @@ package tunnel import ( "encoding/binary" + "github.com/go-i2p/go-i2p/lib/crypto" log "github.com/sirupsen/logrus" ) @@ -153,10 +154,8 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) Checksum() crypto.TunnelI return decrypted_tunnel_message[4+16 : 4+4+16] } -// // Returns the contents of a decrypted tunnel message that contain the data for the // DeliveryInstructions. -// func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData() []byte { data_area := decrypted_tunnel_message[4+4+16:] for i := 0; i < len(data_area); i++ { @@ -167,11 +166,8 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData() return []byte{} } -// // Returns a slice of DeliveryInstructionWithFragment structures, which all of the Delivery Instructions // in the tunnel message and their corresponding MessageFragment structures. -// -// func (decrypted_tunnel_message DecryptedTunnelMessage) DeliveryInstructionsWithFragments() []DeliveryInstructionsWithFragment { set := make([]DeliveryInstructionsWithFragment, 0) data := decrypted_tunnel_message.deliveryInstructionData() diff --git a/lib/tunnel/message_test.go b/lib/tunnel/message_test.go index 3a28689..c817357 100644 --- a/lib/tunnel/message_test.go +++ b/lib/tunnel/message_test.go @@ -1,8 +1,9 @@ package tunnel import ( - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) func TestDeliveryInstructionDataWithNoPadding(t *testing.T) { @@ -33,7 +34,6 @@ func TestDeliveryInstructionDataWithSomePadding(t *testing.T) { copy(decrypted_tunnel_message[:], data) di := decrypted_tunnel_message.deliveryInstructionData() assert.Equal(1028-4-4-16-1-padding_size, len(di)) - } func TestDeliveryInstructionDataWithOnlyPadding(t *testing.T) { @@ -53,11 +53,9 @@ func TestDeliveryInstructionDataWithOnlyPadding(t *testing.T) { } func TestDeliveryInstructionsWithFragmentsWithAllPadding(t *testing.T) { - } // Test invalid delivery instructions and message fragments func TestDeliveryInstructionsWithFragmentsWithValidData(t *testing.T) { - } diff --git a/lib/tunnel/pool.go b/lib/tunnel/pool.go index de02722..611b2e1 100644 --- a/lib/tunnel/pool.go +++ b/lib/tunnel/pool.go @@ -1,5 +1,4 @@ package tunnel // a pool of tunnels which we have created -type Pool struct { -} +type Pool struct{} diff --git a/lib/util/signals/unix.go b/lib/util/signals/unix.go index fb06054..05a8d5c 100644 --- a/lib/util/signals/unix.go +++ b/lib/util/signals/unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package signals @@ -26,5 +27,4 @@ func Handle() { // wtf? } } - } diff --git a/lib/util/signals/windows.go b/lib/util/signals/windows.go index 3b75d1a..e6ea973 100644 --- a/lib/util/signals/windows.go +++ b/lib/util/signals/windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package signals @@ -24,5 +25,4 @@ func Handle() { // wtf? } } - } From 284dd7287ecb29cc732df9d142915f4a7831362c Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Thu, 3 Oct 2024 21:56:58 -0400 Subject: [PATCH 14/94] use makefile from Master --- Makefile | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index a0a8c64..ed939cd 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,8 @@ +RELEASE_TAG=0.0.1 +RELEASE_VERSION=${RELEASE_TAG} +RELEASE_DESCRIPTION=`cat PASTA.md` REPO := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) - +CGO_ENABLED=0 ifdef GOROOT GO = $(GOROOT)/bin/go @@ -16,10 +19,27 @@ endif build: clean $(EXE) $(EXE): - $(GO) build -v -o $(EXE) + $(GO) build --tags netgo,osusergo -v -o $(EXE) -test: - $(GO) test -v -failfast ./lib/transport/noise/... +test: fmt + $(GO) test -v -failfast ./lib/common/... clean: $(GO) clean -v + +fmt: + find . -name '*.go' -exec gofumpt -w {} \; + +info: + echo "GOROOT: ${GOROOT}" + echo "GO: ${GO}" + echo "REPO: ${REPO}" + +release: + github-release release -u go-i2p -r go-i2p -n "${RELEASE_VERSION}" -t "${RELEASE_TAG}" -d "${RELEASE_DESCRIPTION}" -p + +callvis: + go-callvis -format svg -focus upgrade -group pkg,type -limit github.com/go-i2p/go-i2p github.com/go-i2p/go-i2p + +godoc: + find lib -type d -exec bash -c "ls {}/*.go && godocdown -o ./{}/doc.md ./{}" \; \ No newline at end of file From de2caf499e97b4d23b4129bb55d2b2776b0587b4 Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Thu, 3 Oct 2024 21:58:16 -0400 Subject: [PATCH 15/94] use makefile from Master --- PASTA.md | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/PASTA.md b/PASTA.md index 1369fcd..9787976 100644 --- a/PASTA.md +++ b/PASTA.md @@ -1,16 +1,18 @@ -Weekly notes about what I'm working on -====================================== +At long last... something useful +================================ -I finally got back to work on go-i2p last Friday, continuing work on the Noise transport(also enhanced marek's privs as a reddit mod which has been helpful, also the Dread community does appear to have begun to step a little re: onboarding eachother) -I can now make a socket, instantiate a noise transport using the socket, and begin to use it to manage "incoming" and "outgoing" handshakes. -They don't complete yet, still working on that, but it's more like debugging now and less figuring out how to actually do it, I more or less know where the pieces go now -I'm beginning to notice drawbacks of what I've done here already, I think noiseSocket is intended at times as example of a way to use flynn/noise which is not exactly like I would do it or how a P2P application needs to do it -Some of the functions are very long and hard to break down, and they use a different Noise flavor than NTCP2 by default, so I'm breaking things down into steps until I have exactly one step of a Noise handshake, exactly one function -Which should finally give me what I've been hoping for all along, an interface where I can modify steps(i.e. add padding, eventually turn it into NTCP2) by instantiating it with different versions of that function, so I get to think about reusability now -I'm going to attempt to ask a question I don't quite know how to ask yet, and maybe won't know the answer until I try it out for myself: -Supposing: -0. Go network structures can be "nested" if they implement the common interface(`net.Conn`, `net.PacketConn`), and use the common interface to store the information about the socket in their implmentation, and only use the functions of the common interface(This is true) -1. That I can instantiate this Noise-framework Transport struct with functions to modify the process in a granular enough way that turning it into NTCP2 is a matter of writing a few custom functions and plugging them in to an instance of the struct(Sort of like what you would do with inheritance)(which I think is true) -2. that I can instantiate it with both a `net.Conn(TCP Socket interface)` and a `net.PacketConn(UDP Socket interface)` because I only use the common features of those 2 interfaces, (Which isn't true yet but I'm thinking about how to do it) -Does that potential definition of a moddable Noise-over-many-transports library mean that I can approach SSU2 mostly in terms of connection management and peer testing, because the crypto would be similar enough to NTCP2 that I could re-use the custom functions? -I'll find out the hard way eventually the first time I have to do it with SSU2, but it would be exciting to have come up with a design that has accelerating returns in such a way. \ No newline at end of file +It's been 2 years of me mostly not having time to work on go-i2p itself since my last update. +However, after much waiting, this library is actually **useful** for something. +It is now being used in the `reseed-tools` application to examine RouterInfos prior to including them in reseed bundles. +Routers that self-report as unreachable or congested will be excluded from future reseed bundles. +Additionally, routers that self-report an old version will be excluded from reseed bundles. +This should help new users build better connections faster with the existing, working router implementations. + +This is not a working release of a go-i2p router +------------------------------------------------ + +It is a numbered version of the go-i2p library, which is pre-release, expressly for use in the `reseed-tools` application. +The common library works, and so do some of the cryptographic primitives, however the API is unstable and the software itself is certain to have serious bugs outside of a few well-tested areas. +If you're using it for something other than parsing and analyzing RouterInfos and LeaseSets, you'll probably encounter bugs. +Please report them to the https://github.com/go-i2p/go-i2p +Use any part of it at your own risk. From 03c9d60ab9c4bef14fd541e139151db349d05047 Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Thu, 3 Oct 2024 22:09:16 -0400 Subject: [PATCH 16/94] update other non-transport parts of lib --- lib/config/netdb.go | 2 +- lib/config/router.go | 41 +++++++++++++++++++++++++++++++++++++---- lib/router/router.go | 18 ++++++++++++------ lib/util/checkfile.go | 14 ++++++++++++++ 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/lib/config/netdb.go b/lib/config/netdb.go index 7dd3d09..5256e47 100644 --- a/lib/config/netdb.go +++ b/lib/config/netdb.go @@ -12,5 +12,5 @@ type NetDbConfig struct { // default settings for netdb var DefaultNetDbConfig = NetDbConfig{ - Path: filepath.Join(".", "netDb"), + Path: filepath.Join(defaultConfig(), "netDb"), } diff --git a/lib/config/router.go b/lib/config/router.go index eb87ab1..163dfb6 100644 --- a/lib/config/router.go +++ b/lib/config/router.go @@ -1,15 +1,48 @@ package config +import ( + "os" + "path/filepath" +) + // router.config options type RouterConfig struct { + // the path to the base config directory where per-system defaults are stored + BaseDir string + // the path to the working config directory where files are changed + WorkingDir string // netdb configuration NetDb *NetDbConfig // configuration for bootstrapping into the network Bootstrap *BootstrapConfig } -// defaults for router -var DefaultRouterConfig = &RouterConfig{ - NetDb: &DefaultNetDbConfig, - Bootstrap: &DefaultBootstrapConfig, +func home() string { + h, err := os.UserHomeDir() + if err != nil { + panic(err) + } + return h } + +func defaultBase() string { + return filepath.Join(home(), "go-i2p", "base") +} + +func defaultConfig() string { + return filepath.Join(home(), "go-i2p", "config") +} + +// defaults for router +var defaultRouterConfig = &RouterConfig{ + NetDb: &DefaultNetDbConfig, + Bootstrap: &DefaultBootstrapConfig, + BaseDir: defaultBase(), + WorkingDir: defaultConfig(), +} + +func DefaultRouterConfig() *RouterConfig { + return defaultRouterConfig +} + +var RouterConfigProperties = DefaultRouterConfig() diff --git a/lib/router/router.go b/lib/router/router.go index c370718..a8a65fe 100644 --- a/lib/router/router.go +++ b/lib/router/router.go @@ -18,7 +18,7 @@ type Router struct { // create router with default configuration func CreateRouter() (r *Router, err error) { - cfg := config.DefaultRouterConfig + cfg := config.RouterConfigProperties r, err = FromConfig(cfg) return } @@ -62,22 +62,28 @@ func (r *Router) Start() { // run i2p router mainloop func (r *Router) mainloop() { - r.ndb = netdb.StdNetDB(r.cfg.NetDb.Path) + r.ndb = netdb.NewStdNetDB(r.cfg.NetDb.Path) // make sure the netdb is ready - err := r.ndb.Ensure() - if err == nil { + var e error + if err := r.ndb.Ensure(); err != nil { + e = err + } + if sz := r.ndb.Size(); sz >= 0 { + log.Info("NetDB Size:", sz) + } + if e == nil { // netdb ready log.WithFields(log.Fields{ "at": "(Router) mainloop", }).Info("Router ready") - for err == nil { + for e == nil { time.Sleep(time.Second) } } else { // netdb failed log.WithFields(log.Fields{ "at": "(Router) mainloop", - "reason": err.Error(), + "reason": e.Error(), }).Error("Netdb Startup failed") r.Stop() } diff --git a/lib/util/checkfile.go b/lib/util/checkfile.go index 6becc2f..a2335c1 100644 --- a/lib/util/checkfile.go +++ b/lib/util/checkfile.go @@ -2,6 +2,7 @@ package util import ( "os" + "time" ) // Check if a file exists and is readable etc @@ -10,3 +11,16 @@ func CheckFileExists(fpath string) bool { _, e := os.Stat(fpath) return e == nil } + +// Check if a file is more than maxAge minutes old +// returns false if +func CheckFileAge(fpath string, maxAge int) bool { + info, err := os.Stat(fpath) + if err != nil { + // file does not exist, return false + return false + } + xMinAgo := time.Now().Add(time.Duration(-maxAge) * time.Minute) + // Exists and is older than age, return true + return info.ModTime().Before(xMinAgo) +} From d900d7faf8112f4d48abd6ea237cb4ae5d22d48d Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Thu, 3 Oct 2024 22:10:55 -0400 Subject: [PATCH 17/94] add doc.md files from master --- .gitignore | 2 + lib/bootstrap/doc.md | 23 + lib/common/base32/doc.md | 33 + lib/common/base64/doc.md | 33 + lib/common/certificate/doc.md | 98 +++ lib/common/data/doc.md | 297 +++++++++ lib/common/destination/doc.md | 42 ++ lib/common/fuzz/certificate/doc.md | 12 + lib/common/fuzz/destination/doc.md | 12 + lib/common/fuzz/keys_and_cert/doc.md | 12 + lib/common/fuzz/router_address/doc.md | 12 + lib/common/fuzz/router_identity/doc.md | 12 + lib/common/fuzz/string/doc.md | 12 + lib/common/key_certificate/doc.md | 154 +++++ lib/common/keys_and_cert/doc.md | 66 ++ .../keys_and_cert/private_keys_and_cert.go | 18 + lib/common/lease/doc.md | 63 ++ lib/common/lease_set/doc.md | 95 +++ lib/common/router_address/doc.md | 179 +++++ lib/common/router_identity/doc.md | 28 + lib/common/router_info/doc.md | 139 ++++ lib/common/session_key/doc.md | 34 + lib/common/session_tag/doc.md | 34 + lib/common/signature/doc.md | 50 ++ lib/config/doc.md | 85 +++ lib/crypto/curve25519.go | 141 ++++ lib/crypto/doc.md | 623 ++++++++++++++++++ lib/i2np/doc.md | 343 ++++++++++ lib/i2np/fuzz/header/doc.md | 12 + lib/router/doc.md | 58 ++ lib/su3/doc.md | 189 ++++++ lib/tunnel/doc.md | 259 ++++++++ lib/util/doc.md | 39 ++ lib/util/signals/doc.md | 30 + 34 files changed, 3239 insertions(+) create mode 100644 lib/bootstrap/doc.md create mode 100644 lib/common/base32/doc.md create mode 100644 lib/common/base64/doc.md create mode 100644 lib/common/certificate/doc.md create mode 100644 lib/common/data/doc.md create mode 100644 lib/common/destination/doc.md create mode 100644 lib/common/fuzz/certificate/doc.md create mode 100644 lib/common/fuzz/destination/doc.md create mode 100644 lib/common/fuzz/keys_and_cert/doc.md create mode 100644 lib/common/fuzz/router_address/doc.md create mode 100644 lib/common/fuzz/router_identity/doc.md create mode 100644 lib/common/fuzz/string/doc.md create mode 100644 lib/common/key_certificate/doc.md create mode 100644 lib/common/keys_and_cert/doc.md create mode 100644 lib/common/keys_and_cert/private_keys_and_cert.go create mode 100644 lib/common/lease/doc.md create mode 100644 lib/common/lease_set/doc.md create mode 100644 lib/common/router_address/doc.md create mode 100644 lib/common/router_identity/doc.md create mode 100644 lib/common/router_info/doc.md create mode 100644 lib/common/session_key/doc.md create mode 100644 lib/common/session_tag/doc.md create mode 100644 lib/common/signature/doc.md create mode 100644 lib/config/doc.md create mode 100644 lib/crypto/curve25519.go create mode 100644 lib/crypto/doc.md create mode 100644 lib/i2np/doc.md create mode 100644 lib/i2np/fuzz/header/doc.md create mode 100644 lib/router/doc.md create mode 100644 lib/su3/doc.md create mode 100644 lib/tunnel/doc.md create mode 100644 lib/util/doc.md create mode 100644 lib/util/signals/doc.md diff --git a/.gitignore b/.gitignore index 80b127a..60c7ea2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ go-i2p *.exe .idea/ +router.info +log diff --git a/lib/bootstrap/doc.md b/lib/bootstrap/doc.md new file mode 100644 index 0000000..091cdcd --- /dev/null +++ b/lib/bootstrap/doc.md @@ -0,0 +1,23 @@ +# bootstrap +-- + import "github.com/go-i2p/go-i2p/lib/bootstrap" + +provides generic interfaces for initial bootstrap into network and network +### reseeding + +## Usage + +#### type Bootstrap + +```go +type Bootstrap interface { + // get more peers for bootstrap + // try obtaining at most n router infos + // if n is 0 then try obtaining as many router infos as possible + // returns nil and error if we cannot fetch ANY router infos + // returns a channel that yields 1 slice of router infos containing n or fewer router infos, caller must close channel after use + GetPeers(n int) (chan []router_info.RouterInfo, error) +} +``` + +interface defining a way to bootstrap into the i2p network diff --git a/lib/common/base32/doc.md b/lib/common/base32/doc.md new file mode 100644 index 0000000..b77c56a --- /dev/null +++ b/lib/common/base32/doc.md @@ -0,0 +1,33 @@ +# base32 +-- + import "github.com/go-i2p/go-i2p/lib/common/base32" + +Package base32 implmenets utilities for encoding and decoding text using I2P's +### alphabet + +## Usage + +```go +const I2PEncodeAlphabet = "abcdefghijklmnopqrstuvwxyz234567" +``` +I2PEncodeAlphabet is the base32 encoding used throughout I2P. RFC 3548 using +lowercase characters. + +```go +var I2PEncoding *b32.Encoding = b32.NewEncoding(I2PEncodeAlphabet) +``` +I2PEncoding is the standard base32 encoding used through I2P. + +#### func DecodeString + +```go +func DecodeString(data string) ([]byte, error) +``` +DecodeString decodes base64 string to []byte I2PEncoding + +#### func EncodeToString + +```go +func EncodeToString(data []byte) string +``` +EncodeToString encodes []byte to a base32 string using I2PEncoding diff --git a/lib/common/base64/doc.md b/lib/common/base64/doc.md new file mode 100644 index 0000000..511b4ce --- /dev/null +++ b/lib/common/base64/doc.md @@ -0,0 +1,33 @@ +# base64 +-- + import "github.com/go-i2p/go-i2p/lib/common/base64" + +Package base64 implmenets utilities for encoding and decoding text using I2P's +### alphabet + +## Usage + +```go +const I2PEncodeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~" +``` +I2PEncodeAlphabet is the base64 encoding used throughout I2P. RFC 4648 with "/"" +replaced with "~", and "+" replaced with "-". + +```go +var I2PEncoding *b64.Encoding = b64.NewEncoding(I2PEncodeAlphabet) +``` +I2PEncoding is the standard base64 encoding used through I2P. + +#### func DecodeString + +```go +func DecodeString(str string) ([]byte, error) +``` +DecodeString decodes base64 string to []byte I2PEncoding + +#### func EncodeToString + +```go +func EncodeToString(data []byte) string +``` +I2PEncoding is the standard base64 encoding used through I2P. diff --git a/lib/common/certificate/doc.md b/lib/common/certificate/doc.md new file mode 100644 index 0000000..24712f2 --- /dev/null +++ b/lib/common/certificate/doc.md @@ -0,0 +1,98 @@ +# certificate +-- + import "github.com/go-i2p/go-i2p/lib/common/certificate" + + +## Usage + +```go +const ( + CERT_NULL = iota + CERT_HASHCASH + CERT_HIDDEN + CERT_SIGNED + CERT_MULTIPLE + CERT_KEY +) +``` +Certificate Types + +```go +const CERT_MIN_SIZE = 3 +``` +CERT_MIN_SIZE is the minimum size of a valid Certificate in []byte 1 byte for +type 2 bytes for payload length + +#### type Certificate + +```go +type Certificate struct { +} +``` + +Certificate is the representation of an I2P Certificate. + +https://geti2p.net/spec/common-structures#certificate + +#### func NewCertificate + +```go +func NewCertificate(data []byte) (certificate Certificate, err error) +``` +NewCertificate creates a new Certficiate from []byte returns err if the +certificate is too short or if the payload doesn't match specified length. + +#### func ReadCertificate + +```go +func ReadCertificate(data []byte) (certificate Certificate, remainder []byte, err error) +``` +ReadCertificate creates a Certificate from []byte and returns any ExcessBytes at +the end of the input. returns err if the certificate could not be read. + +#### func (*Certificate) Bytes + +```go +func (c *Certificate) Bytes() []byte +``` +Bytes returns the entire certificate in []byte form, trims payload to specified +length. + +#### func (*Certificate) Data + +```go +func (c *Certificate) Data() (data []byte) +``` +Data returns the payload of a Certificate, payload is trimmed to the specified +length. + +#### func (*Certificate) ExcessBytes + +```go +func (c *Certificate) ExcessBytes() []byte +``` +ExcessBytes returns the excess bytes in a certificate found after the specified +payload length. + +#### func (*Certificate) Length + +```go +func (c *Certificate) Length() (length int) +``` +Length returns the payload length of a Certificate. + +#### func (*Certificate) RawBytes + +```go +func (c *Certificate) RawBytes() []byte +``` +RawBytes returns the entire certificate in []byte form, includes excess payload +data. + +#### func (*Certificate) Type + +```go +func (c *Certificate) Type() (cert_type int) +``` +Type returns the Certificate type specified in the first byte of the +Certificate, diff --git a/lib/common/data/doc.md b/lib/common/data/doc.md new file mode 100644 index 0000000..c972402 --- /dev/null +++ b/lib/common/data/doc.md @@ -0,0 +1,297 @@ +# data +-- + import "github.com/go-i2p/go-i2p/lib/common/data" + +Package data implements common data structures used in higher level structures. + +## Usage + +```go +const DATE_SIZE = 8 +``` +DATE_SIZE is the length in bytes of an I2P Date. + +```go +const MAX_INTEGER_SIZE = 8 +``` +MAX_INTEGER_SIZE is the maximum length of an I2P integer in bytes. + +```go +const STRING_MAX_SIZE = 255 +``` +STRING_MAX_SIZE is the maximum number of bytes that can be stored in an I2P +string + +#### func PrintErrors + +```go +func PrintErrors(errs []error) +``` +PrintErrors prints a formatted list of errors to the console. + +#### func WrapErrors + +```go +func WrapErrors(errs []error) error +``` +WrapErrors compiles a slice of errors and returns them wrapped together as a +single error. + +#### type Date + +```go +type Date [8]byte +``` + +Date is the represenation of an I2P Date. + +https://geti2p.net/spec/common-structures#date + +#### func NewDate + +```go +func NewDate(data []byte) (date *Date, remainder []byte, err error) +``` +NewDate creates a new Date from []byte using ReadDate. Returns a pointer to Date +unlike ReadDate. + +#### func ReadDate + +```go +func ReadDate(data []byte) (date Date, remainder []byte, err error) +``` +ReadDate creates a Date from []byte using the first DATE_SIZE bytes. Any data +after DATE_SIZE is returned as a remainder. + +#### func (Date) Bytes + +```go +func (i Date) Bytes() []byte +``` +Bytes returns the raw []byte content of a Date. + +#### func (Date) Int + +```go +func (i Date) Int() int +``` +Int returns the Date as a Go integer. + +#### func (Date) Time + +```go +func (date Date) Time() (date_time time.Time) +``` +Time takes the value stored in date as an 8 byte big-endian integer representing +the number of milliseconds since the beginning of unix time and converts it to a +Go time.Time struct. + +#### type Hash + +```go +type Hash [32]byte +``` + +Hash is the represenation of an I2P Hash. + +https://geti2p.net/spec/common-structures#hash + +#### func HashData + +```go +func HashData(data []byte) (h Hash) +``` +HashData returns the SHA256 sum of a []byte input as Hash. + +#### func HashReader + +```go +func HashReader(r io.Reader) (h Hash, err error) +``` +HashReader returns the SHA256 sum from all data read from an io.Reader. return +error if one occurs while reading from reader + +#### func (Hash) Bytes + +```go +func (h Hash) Bytes() [32]byte +``` + +#### type I2PString + +```go +type I2PString []byte +``` + +I2PString is the represenation of an I2P String. + +https://geti2p.net/spec/common-structures#string + +#### func ReadI2PString + +```go +func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) +``` +ReadI2PString returns I2PString from a []byte. The remaining bytes after the +specified length are also returned. Returns a list of errors that occurred +during parsing. + +#### func ToI2PString + +```go +func ToI2PString(data string) (str I2PString, err error) +``` +ToI2PString converts a Go string to an I2PString. Returns error if the string +exceeds STRING_MAX_SIZE. + +#### func (I2PString) Data + +```go +func (str I2PString) Data() (data string, err error) +``` +Data returns the I2PString content as a string trimmed to the specified length +and not including the length byte. Returns error encountered by Length. + +#### func (I2PString) Length + +```go +func (str I2PString) Length() (length int, err error) +``` +Length returns the length specified in the first byte. Returns error if the +specified does not match the actual length or the string is otherwise invalid. + +#### type Integer + +```go +type Integer []byte +``` + +Integer is the represenation of an I2P Integer. + +https://geti2p.net/spec/common-structures#integer + +#### func NewInteger + +```go +func NewInteger(bytes []byte, size int) (integer *Integer, remainder []byte, err error) +``` +NewInteger creates a new Integer from []byte using ReadInteger. Limits the +length of the created Integer to MAX_INTEGER_SIZE. Returns a pointer to Integer +unlike ReadInteger. + +#### func NewIntegerFromInt + +```go +func NewIntegerFromInt(value int, size int) (integer *Integer, err error) +``` +NewIntegerFromInt creates a new Integer from a Go integer of a specified []byte +length. + +#### func ReadInteger + +```go +func ReadInteger(bytes []byte, size int) (Integer, []byte) +``` +ReadInteger returns an Integer from a []byte of specified length. The remaining +bytes after the specified length are also returned. + +#### func (Integer) Bytes + +```go +func (i Integer) Bytes() []byte +``` +Bytes returns the raw []byte content of an Integer. + +#### func (Integer) Int + +```go +func (i Integer) Int() int +``` +Int returns the Date as a Go integer + +#### type Mapping + +```go +type Mapping struct { +} +``` + +Mapping is the represenation of an I2P Mapping. + +https://geti2p.net/spec/common-structures#mapping + +#### func GoMapToMapping + +```go +func GoMapToMapping(gomap map[string]string) (mapping *Mapping, err error) +``` +GoMapToMapping converts a Go map of unformatted strings to *Mapping. + +#### func NewMapping + +```go +func NewMapping(bytes []byte) (values *Mapping, remainder []byte, err []error) +``` +NewMapping creates a new *Mapping from []byte using ReadMapping. Returns a +pointer to Mapping unlike ReadMapping. + +#### func ReadMapping + +```go +func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) +``` +ReadMapping returns Mapping from a []byte. The remaining bytes after the +specified length are also returned. Returns a list of errors that occurred +during parsing. + +#### func ValuesToMapping + +```go +func ValuesToMapping(values MappingValues) *Mapping +``` +ValuesToMapping creates a *Mapping using MappingValues. The values are sorted in +the order defined in mappingOrder. + +#### func (*Mapping) Data + +```go +func (mapping *Mapping) Data() []byte +``` +Data returns a Mapping in its []byte form. + +#### func (*Mapping) HasDuplicateKeys + +```go +func (mapping *Mapping) HasDuplicateKeys() bool +``` +HasDuplicateKeys returns true if two keys in a mapping are identical. + +#### func (Mapping) Values + +```go +func (mapping Mapping) Values() MappingValues +``` +Values returns the values contained in a Mapping as MappingValues. + +#### type MappingValues + +```go +type MappingValues [][2]I2PString +``` + +MappingValues represents the parsed key value pairs inside of an I2P Mapping. + +#### func ReadMappingValues + +```go +func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingValues, remainder_bytes []byte, errs []error) +``` +ReadMappingValues returns *MappingValues from a []byte. The remaining bytes +after the specified length are also returned. Returns a list of errors that +occurred during parsing. + +#### func (MappingValues) Get + +```go +func (m MappingValues) Get(key I2PString) I2PString +``` diff --git a/lib/common/destination/doc.md b/lib/common/destination/doc.md new file mode 100644 index 0000000..fff8c39 --- /dev/null +++ b/lib/common/destination/doc.md @@ -0,0 +1,42 @@ +# destination +-- + import "github.com/go-i2p/go-i2p/lib/common/destination" + +Package destination implements the I2P Destination common data structure + +## Usage + +#### type Destination + +```go +type Destination struct { + KeysAndCert +} +``` + +Destination is the represenation of an I2P Destination. + +https://geti2p.net/spec/common-structures#destination + +#### func ReadDestination + +```go +func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) +``` +ReadDestination returns Destination from a []byte. The remaining bytes after the +specified length are also returned. Returns a list of errors that occurred +during parsing. + +#### func (Destination) Base32Address + +```go +func (destination Destination) Base32Address() (str string) +``` +Base32Address returns the I2P base32 address for this Destination. + +#### func (Destination) Base64 + +```go +func (destination Destination) Base64() string +``` +Base64 returns the I2P base64 address for this Destination. diff --git a/lib/common/fuzz/certificate/doc.md b/lib/common/fuzz/certificate/doc.md new file mode 100644 index 0000000..64dd643 --- /dev/null +++ b/lib/common/fuzz/certificate/doc.md @@ -0,0 +1,12 @@ +# exportable +-- + import "github.com/go-i2p/go-i2p/lib/common/fuzz/certificate" + + +## Usage + +#### func Fuzz + +```go +func Fuzz(data []byte) int +``` diff --git a/lib/common/fuzz/destination/doc.md b/lib/common/fuzz/destination/doc.md new file mode 100644 index 0000000..5b01e3e --- /dev/null +++ b/lib/common/fuzz/destination/doc.md @@ -0,0 +1,12 @@ +# exportable +-- + import "github.com/go-i2p/go-i2p/lib/common/fuzz/destination" + + +## Usage + +#### func Fuzz + +```go +func Fuzz(data []byte) int +``` diff --git a/lib/common/fuzz/keys_and_cert/doc.md b/lib/common/fuzz/keys_and_cert/doc.md new file mode 100644 index 0000000..bc92c71 --- /dev/null +++ b/lib/common/fuzz/keys_and_cert/doc.md @@ -0,0 +1,12 @@ +# exportable +-- + import "github.com/go-i2p/go-i2p/lib/common/fuzz/keys_and_cert" + + +## Usage + +#### func Fuzz + +```go +func Fuzz(data []byte) int +``` diff --git a/lib/common/fuzz/router_address/doc.md b/lib/common/fuzz/router_address/doc.md new file mode 100644 index 0000000..a221b33 --- /dev/null +++ b/lib/common/fuzz/router_address/doc.md @@ -0,0 +1,12 @@ +# exportable +-- + import "github.com/go-i2p/go-i2p/lib/common/fuzz/router_address" + + +## Usage + +#### func Fuzz + +```go +func Fuzz(data []byte) int +``` diff --git a/lib/common/fuzz/router_identity/doc.md b/lib/common/fuzz/router_identity/doc.md new file mode 100644 index 0000000..18208d6 --- /dev/null +++ b/lib/common/fuzz/router_identity/doc.md @@ -0,0 +1,12 @@ +# exportable +-- + import "github.com/go-i2p/go-i2p/lib/common/fuzz/router_identity" + + +## Usage + +#### func Fuzz + +```go +func Fuzz(data []byte) int +``` diff --git a/lib/common/fuzz/string/doc.md b/lib/common/fuzz/string/doc.md new file mode 100644 index 0000000..c432f87 --- /dev/null +++ b/lib/common/fuzz/string/doc.md @@ -0,0 +1,12 @@ +# exportable +-- + import "github.com/go-i2p/go-i2p/lib/common/fuzz/string" + + +## Usage + +#### func Fuzz + +```go +func Fuzz(data []byte) int +``` diff --git a/lib/common/key_certificate/doc.md b/lib/common/key_certificate/doc.md new file mode 100644 index 0000000..6d189a0 --- /dev/null +++ b/lib/common/key_certificate/doc.md @@ -0,0 +1,154 @@ +# key_certificate +-- + import "github.com/go-i2p/go-i2p/lib/common/key_certificate" + +Package key_certificate implements the I2P Destination common data structure + +## Usage + +```go +const ( + KEYCERT_SIGN_DSA_SHA1 = iota + KEYCERT_SIGN_P256 + KEYCERT_SIGN_P384 + KEYCERT_SIGN_P521 + KEYCERT_SIGN_RSA2048 + KEYCERT_SIGN_RSA3072 + KEYCERT_SIGN_RSA4096 + KEYCERT_SIGN_ED25519 + KEYCERT_SIGN_ED25519PH +) +``` +Key Certificate Signing Key Types + +```go +const ( + KEYCERT_CRYPTO_ELG = iota + KEYCERT_CRYPTO_P256 + KEYCERT_CRYPTO_P384 + KEYCERT_CRYPTO_P521 + KEYCERT_CRYPTO_X25519 +) +``` +Key Certificate Public Key Types + +```go +const ( + KEYCERT_SIGN_DSA_SHA1_SIZE = 128 + KEYCERT_SIGN_P256_SIZE = 64 + KEYCERT_SIGN_P384_SIZE = 96 + KEYCERT_SIGN_P521_SIZE = 132 + KEYCERT_SIGN_RSA2048_SIZE = 256 + KEYCERT_SIGN_RSA3072_SIZE = 384 + KEYCERT_SIGN_RSA4096_SIZE = 512 + KEYCERT_SIGN_ED25519_SIZE = 32 + KEYCERT_SIGN_ED25519PH_SIZE = 32 +) +``` +SigningPublicKey sizes for Signing Key Types + +```go +const ( + KEYCERT_CRYPTO_ELG_SIZE = 256 + KEYCERT_CRYPTO_P256_SIZE = 64 + KEYCERT_CRYPTO_P384_SIZE = 96 + KEYCERT_CRYPTO_P521_SIZE = 132 + KEYCERT_CRYPTO_X25519_SIZE = 32 +) +``` +PublicKey sizes for Public Key Types + +```go +const ( + KEYCERT_PUBKEY_SIZE = 256 + KEYCERT_SPK_SIZE = 128 +) +``` +Sizes of structures in KeyCertificates + +```go +const ( + KEYCERT_MIN_SIZE = 7 +) +``` + +#### type KeyCertificate + +```go +type KeyCertificate struct { + Certificate +} +``` + +type KeyCertificate []byte + +#### func KeyCertificateFromCertificate + +```go +func KeyCertificateFromCertificate(certificate Certificate) *KeyCertificate +``` +KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate. + +#### func NewKeyCertificate + +```go +func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) +``` +NewKeyCertificate creates a new *KeyCertificate from []byte using +ReadCertificate. The remaining bytes after the specified length are also +returned. Returns a list of errors that occurred during parsing. + +#### func (KeyCertificate) ConstructPublicKey + +```go +func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.PublicKey, err error) +``` +ConstructPublicKey returns a PublicKey constructed using any excess data that +may be stored in the KeyCertififcate. Returns enr errors encountered while +parsing. + +#### func (KeyCertificate) ConstructSigningPublicKey + +```go +func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error) +``` +ConstructSigningPublicKey returns a SingingPublicKey constructed using any +excess data that may be stored in the KeyCertificate. Returns any errors +encountered while parsing. + +#### func (KeyCertificate) CryptoSize + +```go +func (key_certificate KeyCertificate) CryptoSize() (size int) +``` +CryptoSize return the size of a Public Key corresponding to the Key +Certificate's PublicKey type. + +#### func (KeyCertificate) Data + +```go +func (key_certificate KeyCertificate) Data() ([]byte, error) +``` +Data returns the raw []byte contained in the Certificate. + +#### func (KeyCertificate) PublicKeyType + +```go +func (key_certificate KeyCertificate) PublicKeyType() (pubkey_type int) +``` +PublicKeyType returns the PublicKey type as a Go integer. + +#### func (KeyCertificate) SignatureSize + +```go +func (key_certificate KeyCertificate) SignatureSize() (size int) +``` +SignatureSize return the size of a Signature corresponding to the Key +Certificate's SigningPublicKey type. + +#### func (KeyCertificate) SigningPublicKeyType + +```go +func (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int) +``` +SigningPublicKeyType returns the SigningPublicKey type as a Go integer. diff --git a/lib/common/keys_and_cert/doc.md b/lib/common/keys_and_cert/doc.md new file mode 100644 index 0000000..a113c02 --- /dev/null +++ b/lib/common/keys_and_cert/doc.md @@ -0,0 +1,66 @@ +# keys_and_cert +-- + import "github.com/go-i2p/go-i2p/lib/common/keys_and_cert" + +Package keys_and_cert implements the I2P KeysAndCert common data structure + +## Usage + +```go +const ( + KEYS_AND_CERT_PUBKEY_SIZE = 256 + KEYS_AND_CERT_SPK_SIZE = 128 + KEYS_AND_CERT_MIN_SIZE = 387 + KEYS_AND_CERT_DATA_SIZE = 384 +) +``` +Sizes of various KeysAndCert structures and requirements + +#### type KeysAndCert + +```go +type KeysAndCert struct { + KeyCertificate *KeyCertificate +} +``` + +KeysAndCert is the represenation of an I2P KeysAndCert. + +https://geti2p.net/spec/common-structures#keysandcert + +#### func ReadKeysAndCert + +```go +func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error) +``` +ReadKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert. +Returns a pointer to KeysAndCert unlike ReadKeysAndCert. + +#### func (KeysAndCert) Bytes + +```go +func (keys_and_cert KeysAndCert) Bytes() []byte +``` +Bytes returns the entire KeyCertificate in []byte form, trims payload to +specified length. + +#### func (*KeysAndCert) Certificate + +```go +func (keys_and_cert *KeysAndCert) Certificate() (cert Certificate) +``` +Certfificate returns the certificate. + +#### func (*KeysAndCert) PublicKey + +```go +func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey) +``` +PublicKey returns the public key as a crypto.PublicKey. + +#### func (*KeysAndCert) SigningPublicKey + +```go +func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey) +``` +SigningPublicKey returns the signing public key. diff --git a/lib/common/keys_and_cert/private_keys_and_cert.go b/lib/common/keys_and_cert/private_keys_and_cert.go new file mode 100644 index 0000000..85e48f2 --- /dev/null +++ b/lib/common/keys_and_cert/private_keys_and_cert.go @@ -0,0 +1,18 @@ +package keys_and_cert + +import "crypto" + +// PrivateKeysAndCert contains a KeysAndCert along with the corresponding private keys for the +// Public Key and the Signing Public Key +type PrivateKeysAndCert struct { + KeysAndCert + PK_KEY crypto.PrivateKey + SPK_KEY crypto.PrivateKey +} + +func NewPrivateKeysAndCert() (*PrivateKeysAndCert, error) { + var pkc PrivateKeysAndCert + var err error + // pkc.PK_KEY, err = + return &pkc, err +} diff --git a/lib/common/lease/doc.md b/lib/common/lease/doc.md new file mode 100644 index 0000000..2e46edd --- /dev/null +++ b/lib/common/lease/doc.md @@ -0,0 +1,63 @@ +# lease +-- + import "github.com/go-i2p/go-i2p/lib/common/lease" + +Package lease implements the I2P lease common data structure + +## Usage + +```go +const ( + LEASE_SIZE = 44 + LEASE_HASH_SIZE = 32 + LEASE_TUNNEL_ID_SIZE = 4 +) +``` +Sizes in bytes of various components of a Lease + +#### type Lease + +```go +type Lease [LEASE_SIZE]byte +``` + +Lease is the represenation of an I2P Lease. + +https://geti2p.net/spec/common-structures#lease + +#### func NewLease + +```go +func NewLease(data []byte) (lease *Lease, remainder []byte, err error) +``` +NewLease creates a new *NewLease from []byte using ReadLease. Returns a pointer +to KeysAndCert unlike ReadLease. + +#### func ReadLease + +```go +func ReadLease(data []byte) (lease Lease, remainder []byte, err error) +``` +ReadLease returns Lease from a []byte. The remaining bytes after the specified +length are also returned. Returns a list of errors that occurred during parsing. + +#### func (Lease) Date + +```go +func (lease Lease) Date() (date Date) +``` +Date returns the date as an I2P Date. + +#### func (Lease) TunnelGateway + +```go +func (lease Lease) TunnelGateway() (hash Hash) +``` +TunnelGateway returns the tunnel gateway as a Hash. + +#### func (Lease) TunnelID + +```go +func (lease Lease) TunnelID() uint32 +``` +TunnelID returns the tunnel id as a uint23. diff --git a/lib/common/lease_set/doc.md b/lib/common/lease_set/doc.md new file mode 100644 index 0000000..6fa5410 --- /dev/null +++ b/lib/common/lease_set/doc.md @@ -0,0 +1,95 @@ +# lease_set +-- + import "github.com/go-i2p/go-i2p/lib/common/lease_set" + +Package lease_set implements the I2P LeastSet common data structure + +## Usage + +```go +const ( + LEASE_SET_PUBKEY_SIZE = 256 + LEASE_SET_SPK_SIZE = 128 + LEASE_SET_SIG_SIZE = 40 +) +``` +Sizes of various structures in an I2P LeaseSet + +#### type LeaseSet + +```go +type LeaseSet []byte +``` + +LeaseSet is the represenation of an I2P LeaseSet. + +https://geti2p.net/spec/common-structures#leaseset + +#### func (LeaseSet) Destination + +```go +func (lease_set LeaseSet) Destination() (destination Destination, err error) +``` +Destination returns the Destination as []byte. + +#### func (LeaseSet) LeaseCount + +```go +func (lease_set LeaseSet) LeaseCount() (count int, err error) +``` +LeaseCount returns the numbert of leases specified by the LeaseCount value as +int. returns errors encountered during parsing. + +#### func (LeaseSet) Leases + +```go +func (lease_set LeaseSet) Leases() (leases []Lease, err error) +``` +Leases returns the leases as []Lease. returns errors encountered during parsing. + +#### func (LeaseSet) NewestExpiration + +```go +func (lease_set LeaseSet) NewestExpiration() (newest Date, err error) +``` +NewestExpiration returns the newest lease expiration as an I2P Date. Returns +errors encountered during parsing. + +#### func (LeaseSet) OldestExpiration + +```go +func (lease_set LeaseSet) OldestExpiration() (earliest Date, err error) +``` +OldestExpiration returns the oldest lease expiration as an I2P Date. Returns +errors encountered during parsing. + +#### func (LeaseSet) PublicKey + +```go +func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error) +``` +PublicKey returns the public key as crypto.ElgPublicKey. Returns errors +encountered during parsing. + +#### func (LeaseSet) Signature + +```go +func (lease_set LeaseSet) Signature() (signature Signature, err error) +``` +Signature returns the signature as Signature. returns errors encountered during +parsing. + +#### func (LeaseSet) SigningKey + +```go +func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicKey, err error) +``` +SigningKey returns the signing public key as crypto.SigningPublicKey. returns +errors encountered during parsing. + +#### func (LeaseSet) Verify + +```go +func (lease_set LeaseSet) Verify() error +``` +Verify returns nil diff --git a/lib/common/router_address/doc.md b/lib/common/router_address/doc.md new file mode 100644 index 0000000..4491417 --- /dev/null +++ b/lib/common/router_address/doc.md @@ -0,0 +1,179 @@ +# router_address +-- + import "github.com/go-i2p/go-i2p/lib/common/router_address" + +Package router_address implements the I2P RouterAddress common data structure + +## Usage + +```go +const ( + ROUTER_ADDRESS_MIN_SIZE = 9 +) +``` +Minimum number of bytes in a valid RouterAddress + +#### type RouterAddress + +```go +type RouterAddress struct { + TransportCost *Integer + ExpirationDate *Date + TransportType I2PString + TransportOptions *Mapping +} +``` + +RouterAddress is the represenation of an I2P RouterAddress. + +https://geti2p.net/spec/common-structures#routeraddress + +#### func ReadRouterAddress + +```go +func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) +``` +ReadRouterAddress returns RouterAddress from a []byte. The remaining bytes after +the specified length are also returned. Returns a list of errors that occurred +during parsing. + +#### func (RouterAddress) Bytes + +```go +func (router_address RouterAddress) Bytes() []byte +``` +Bytes returns the router address as a []byte. + +#### func (RouterAddress) Cost + +```go +func (router_address RouterAddress) Cost() int +``` +Cost returns the cost for this RouterAddress as a Go integer. + +#### func (RouterAddress) Expiration + +```go +func (router_address RouterAddress) Expiration() Date +``` +Expiration returns the expiration for this RouterAddress as an I2P Date. + +#### func (RouterAddress) GetOption + +```go +func (router_address RouterAddress) GetOption(key I2PString) I2PString +``` +GetOption returns the value of the option specified by the key + +#### func (RouterAddress) Host + +```go +func (router_address RouterAddress) Host() (net.Addr, error) +``` + +#### func (RouterAddress) HostString + +```go +func (router_address RouterAddress) HostString() I2PString +``` + +#### func (RouterAddress) InitializationVector + +```go +func (router_address RouterAddress) InitializationVector() ([32]byte, error) +``` + +#### func (RouterAddress) InitializationVectorString + +```go +func (router_address RouterAddress) InitializationVectorString() I2PString +``` + +#### func (RouterAddress) IntroducerExpirationString + +```go +func (router_address RouterAddress) IntroducerExpirationString(num int) I2PString +``` + +#### func (RouterAddress) IntroducerHashString + +```go +func (router_address RouterAddress) IntroducerHashString(num int) I2PString +``` + +#### func (RouterAddress) IntroducerTagString + +```go +func (router_address RouterAddress) IntroducerTagString(num int) I2PString +``` + +#### func (*RouterAddress) Network + +```go +func (router_address *RouterAddress) Network() string +``` +Network implements net.Addr. It returns the transport type + +#### func (RouterAddress) Options + +```go +func (router_address RouterAddress) Options() Mapping +``` +Options returns the options for this RouterAddress as an I2P Mapping. + +#### func (RouterAddress) Port + +```go +func (router_address RouterAddress) Port() (string, error) +``` + +#### func (RouterAddress) PortString + +```go +func (router_address RouterAddress) PortString() I2PString +``` + +#### func (RouterAddress) ProtocolVersion + +```go +func (router_address RouterAddress) ProtocolVersion() (string, error) +``` + +#### func (RouterAddress) ProtocolVersionString + +```go +func (router_address RouterAddress) ProtocolVersionString() I2PString +``` + +#### func (RouterAddress) StaticKey + +```go +func (router_address RouterAddress) StaticKey() ([32]byte, error) +``` + +#### func (RouterAddress) StaticKeyString + +```go +func (router_address RouterAddress) StaticKeyString() I2PString +``` + +#### func (*RouterAddress) String + +```go +func (router_address *RouterAddress) String() string +``` +String implements net.Addr. It returns the IP address, followed by the options + +#### func (RouterAddress) TransportStyle + +```go +func (router_address RouterAddress) TransportStyle() I2PString +``` +TransportStyle returns the transport style for this RouterAddress as an +I2PString. + +#### func (*RouterAddress) UDP + +```go +func (router_address *RouterAddress) UDP() bool +``` diff --git a/lib/common/router_identity/doc.md b/lib/common/router_identity/doc.md new file mode 100644 index 0000000..37b2643 --- /dev/null +++ b/lib/common/router_identity/doc.md @@ -0,0 +1,28 @@ +# router_identity +-- + import "github.com/go-i2p/go-i2p/lib/common/router_identity" + +Package router_identity implements the I2P RouterIdentity common data structure + +## Usage + +#### type RouterIdentity + +```go +type RouterIdentity struct { + KeysAndCert +} +``` + +RouterIdentity is the represenation of an I2P RouterIdentity. + +https://geti2p.net/spec/common-structures#routeridentity + +#### func ReadRouterIdentity + +```go +func ReadRouterIdentity(data []byte) (router_identity RouterIdentity, remainder []byte, err error) +``` +ReadRouterIdentity returns RouterIdentity from a []byte. The remaining bytes +after the specified length are also returned. Returns a list of errors that +occurred during parsing. diff --git a/lib/common/router_info/doc.md b/lib/common/router_info/doc.md new file mode 100644 index 0000000..d9f50ad --- /dev/null +++ b/lib/common/router_info/doc.md @@ -0,0 +1,139 @@ +# router_info +-- + import "github.com/go-i2p/go-i2p/lib/common/router_info" + +Package router_info implements the I2P RouterInfo common data structure + +## Usage + +```go +const ( + MIN_GOOD_VERSION = 58 + MAX_GOOD_VERSION = 99 +) +``` + +```go +const ROUTER_INFO_MIN_SIZE = 439 +``` + +#### type RouterInfo + +```go +type RouterInfo struct { +} +``` + +RouterInfo is the represenation of an I2P RouterInfo. + +https://geti2p.net/spec/common-structures#routerinfo + +#### func ReadRouterInfo + +```go +func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) +``` +ReadRouterInfo returns RouterInfo from a []byte. The remaining bytes after the +specified length are also returned. Returns a list of errors that occurred +during parsing. + +#### func (RouterInfo) Bytes + +```go +func (router_info RouterInfo) Bytes() (bytes []byte, err error) +``` +Bytes returns the RouterInfo as a []byte suitable for writing to a stream. + +#### func (*RouterInfo) GoodVersion + +```go +func (router_info *RouterInfo) GoodVersion() bool +``` + +#### func (*RouterInfo) IdentHash + +```go +func (router_info *RouterInfo) IdentHash() Hash +``` +IndentHash returns the identity hash (sha256 sum) for this RouterInfo. + +#### func (RouterInfo) Options + +```go +func (router_info RouterInfo) Options() (mapping Mapping) +``` +Options returns the options for this RouterInfo as an I2P Mapping. + +#### func (*RouterInfo) PeerSize + +```go +func (router_info *RouterInfo) PeerSize() int +``` +PeerSize returns the peer size as a Go integer. + +#### func (*RouterInfo) Published + +```go +func (router_info *RouterInfo) Published() *Date +``` +Published returns the date this RouterInfo was published as an I2P Date. + +#### func (*RouterInfo) Reachable + +```go +func (router_info *RouterInfo) Reachable() bool +``` + +#### func (*RouterInfo) RouterAddressCount + +```go +func (router_info *RouterInfo) RouterAddressCount() int +``` +RouterAddressCount returns the count of RouterAddress in this RouterInfo as a Go +integer. + +#### func (*RouterInfo) RouterAddresses + +```go +func (router_info *RouterInfo) RouterAddresses() []*RouterAddress +``` +RouterAddresses returns all RouterAddresses for this RouterInfo as +[]*RouterAddress. + +#### func (*RouterInfo) RouterCapabilities + +```go +func (router_info *RouterInfo) RouterCapabilities() string +``` + +#### func (*RouterInfo) RouterIdentity + +```go +func (router_info *RouterInfo) RouterIdentity() *RouterIdentity +``` +RouterIdentity returns the router identity as *RouterIdentity. + +#### func (*RouterInfo) RouterVersion + +```go +func (router_info *RouterInfo) RouterVersion() string +``` + +#### func (RouterInfo) Signature + +```go +func (router_info RouterInfo) Signature() (signature Signature) +``` +Signature returns the signature for this RouterInfo as an I2P Signature. + +#### func (RouterInfo) String + +```go +func (router_info RouterInfo) String() string +``` + +#### func (*RouterInfo) UnCongested + +```go +func (router_info *RouterInfo) UnCongested() bool +``` diff --git a/lib/common/session_key/doc.md b/lib/common/session_key/doc.md new file mode 100644 index 0000000..c5e92ec --- /dev/null +++ b/lib/common/session_key/doc.md @@ -0,0 +1,34 @@ +# session_key +-- + import "github.com/go-i2p/go-i2p/lib/common/session_key" + +Package session_key implements the I2P SessionKey common data structure + +## Usage + +#### type SessionKey + +```go +type SessionKey [32]byte +``` + +SessionKey is the represenation of an I2P SessionKey. + +https://geti2p.net/spec/common-structures#sessionkey + +#### func NewSessionKey + +```go +func NewSessionKey(data []byte) (session_key *SessionKey, remainder []byte, err error) +``` +NewSessionKey creates a new *SessionKey from []byte using ReadSessionKey. +Returns a pointer to SessionKey unlike ReadSessionKey. + +#### func ReadSessionKey + +```go +func ReadSessionKey(bytes []byte) (info SessionKey, remainder []byte, err error) +``` +ReadSessionKey returns SessionKey from a []byte. The remaining bytes after the +specified length are also returned. Returns a list of errors that occurred +during parsing. diff --git a/lib/common/session_tag/doc.md b/lib/common/session_tag/doc.md new file mode 100644 index 0000000..03374e6 --- /dev/null +++ b/lib/common/session_tag/doc.md @@ -0,0 +1,34 @@ +# session_tag +-- + import "github.com/go-i2p/go-i2p/lib/common/session_tag" + +Package session_tag implements the I2P SessionTag common data structure + +## Usage + +#### type SessionTag + +```go +type SessionTag [32]byte +``` + +SessionTag is the represenation of an I2P SessionTag. + +https://geti2p.net/spec/common-structures#session-tag + +#### func NewSessionTag + +```go +func NewSessionTag(data []byte) (session_tag *SessionTag, remainder []byte, err error) +``` +NewSessionTag creates a new *SessionTag from []byte using ReadSessionTag. +Returns a pointer to SessionTag unlike ReadSessionTag. + +#### func ReadSessionTag + +```go +func ReadSessionTag(bytes []byte) (info SessionTag, remainder []byte, err error) +``` +ReadSessionTag returns SessionTag from a []byte. The remaining bytes after the +specified length are also returned. Returns a list of errors that occurred +during parsing. diff --git a/lib/common/signature/doc.md b/lib/common/signature/doc.md new file mode 100644 index 0000000..c43764d --- /dev/null +++ b/lib/common/signature/doc.md @@ -0,0 +1,50 @@ +# signature +-- + import "github.com/go-i2p/go-i2p/lib/common/signature" + +Package signature implements the I2P Signature common data structure + +## Usage + +```go +const ( + DSA_SHA1_SIZE = 40 + ECDSA_SHA256_P256_SIZE = 64 + ECDSA_SHA384_P384_SIZE = 96 + ECDSA_SHA512_P512_SIZE = 132 + RSA_SHA256_2048_SIZE = 256 + RSA_SHA384_3072_SIZE = 384 + RSA_SHA512_4096_SIZE = 512 + EdDSA_SHA512_Ed25519_SIZE = 64 + EdDSA_SHA512_Ed25519ph_SIZE = 64 + RedDSA_SHA512_Ed25519_SIZE = 64 +) +``` +Lengths of signature keys + +#### type Signature + +```go +type Signature []byte +``` + +Signature is the represenation of an I2P Signature. + +https://geti2p.net/spec/common-structures#signature + +#### func NewSignature + +```go +func NewSignature(data []byte) (session_tag *Signature, remainder []byte, err error) +``` +NewSignature creates a new *Signature from []byte using ReadSignature. Returns a +pointer to Signature unlike ReadSignature. + +#### func ReadSignature + +```go +func ReadSignature(bytes []byte) (info Signature, remainder []byte, err error) +``` +ReadSignature returns Signature from a []byte. The remaining bytes after the +specified length are also returned. Returns a list of errors that occurred +during parsing. diff --git a/lib/config/doc.md b/lib/config/doc.md new file mode 100644 index 0000000..5608091 --- /dev/null +++ b/lib/config/doc.md @@ -0,0 +1,85 @@ +# config +-- + import "github.com/go-i2p/go-i2p/lib/config" + + +## Usage + +```go +var DefaultBootstrapConfig = BootstrapConfig{ + LowPeerThreshold: 10, + + ReseedServers: []*ReseedConfig{}, +} +``` +default configuration for network bootstrap + +```go +var DefaultNetDbConfig = NetDbConfig{ + Path: filepath.Join(defaultConfig(), "netDb"), +} +``` +default settings for netdb + +```go +var RouterConfigProperties = DefaultRouterConfig() +``` + +#### type BootstrapConfig + +```go +type BootstrapConfig struct { + // if we have less than this many peers we should reseed + LowPeerThreshold int + // reseed servers + ReseedServers []*ReseedConfig +} +``` + + +#### type NetDbConfig + +```go +type NetDbConfig struct { + // path to network database directory + Path string +} +``` + +local network database configuration + +#### type ReseedConfig + +```go +type ReseedConfig struct { + // url of reseed server + Url string + // fingerprint of reseed su3 signing key + SU3Fingerprint string +} +``` + +configuration for 1 reseed server + +#### type RouterConfig + +```go +type RouterConfig struct { + // the path to the base config directory where per-system defaults are stored + BaseDir string + // the path to the working config directory where files are changed + WorkingDir string + // netdb configuration + NetDb *NetDbConfig + // configuration for bootstrapping into the network + Bootstrap *BootstrapConfig +} +``` + +router.config options + +#### func DefaultRouterConfig + +```go +func DefaultRouterConfig() *RouterConfig +``` diff --git a/lib/crypto/curve25519.go b/lib/crypto/curve25519.go new file mode 100644 index 0000000..d20d858 --- /dev/null +++ b/lib/crypto/curve25519.go @@ -0,0 +1,141 @@ +package crypto + +import ( + "crypto/rand" + "crypto/sha256" + "crypto/sha512" + "errors" + "io" + "math/big" + + curve25519 "go.step.sm/crypto/x25519" +) + +var Curve25519EncryptTooBig = errors.New("failed to encrypt data, too big for Curve25519") + +type Curve25519PublicKey []byte + +type Curve25519Verifier struct { + k []byte +} + +func (k Curve25519PublicKey) NewVerifier() (v Verifier, err error) { + temp := new(Curve25519Verifier) + temp.k = k + v = temp + return temp, nil +} + +func (k Curve25519PublicKey) Len() int { + return len(k) +} + +func createCurve25519PublicKey(data []byte) (k *curve25519.PublicKey) { + if len(data) == 256 { + k2 := curve25519.PublicKey{} + copy(k2[:], data) + k = &k2 + } + return +} + +func createCurve25519Encryption(pub *curve25519.PublicKey, rand io.Reader) (enc *Curve25519Encryption, err error) { + /*kbytes := make([]byte, 256) + k := new(big.Int) + for err == nil { + _, err = io.ReadFull(rand, kbytes) + k = new(big.Int).SetBytes(kbytes) + k = k.Mod(k, pub.P) + if k.Sign() != 0 { + break + } + } + if err == nil { + enc = &Curve25519Encryption{} + }*/ + return +} + +type Curve25519Encryption struct { + p, a, b1 *big.Int +} + +func (curve25519 *Curve25519Encryption) Encrypt(data []byte) (enc []byte, err error) { + return curve25519.EncryptPadding(data, true) +} + +func (curve25519 *Curve25519Encryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error) { + if len(data) > 222 { + err = Curve25519EncryptTooBig + return + } + mbytes := make([]byte, 255) + mbytes[0] = 0xFF + copy(mbytes[33:], data) + // do sha256 of payload + d := sha256.Sum256(mbytes[33 : len(data)+33]) + copy(mbytes[1:], d[:]) + m := new(big.Int).SetBytes(mbytes) + // do encryption + b := new(big.Int).Mod(new(big.Int).Mul(curve25519.b1, m), curve25519.p).Bytes() + + if zeroPadding { + encrypted = make([]byte, 514) + copy(encrypted[1:], curve25519.a.Bytes()) + copy(encrypted[258:], b) + } else { + encrypted = make([]byte, 512) + copy(encrypted, curve25519.a.Bytes()) + copy(encrypted[256:], b) + } + return +} + +func (elg Curve25519PublicKey) NewEncrypter() (enc Encrypter, err error) { + k := createCurve25519PublicKey(elg[:]) + enc, err = createCurve25519Encryption(k, rand.Reader) + return +} + +func (v *Curve25519Verifier) VerifyHash(h, sig []byte) (err error) { + if len(sig) != curve25519.SignatureSize { + err = ErrBadSignatureSize + return + } + if len(v.k) != curve25519.PublicKeySize { + err = errors.New("failed to verify: invalid curve25519 public key size") + return + } + + ok := curve25519.Verify(v.k, h, sig) + if !ok { + err = errors.New("failed to verify: invalid signature") + } + return +} + +func (v *Curve25519Verifier) Verify(data, sig []byte) (err error) { + h := sha512.Sum512(data) + err = v.VerifyHash(h[:], sig) + return +} + +type Curve25519PrivateKey curve25519.PrivateKey + +type Curve25519Signer struct { + k []byte +} + +func (s *Curve25519Signer) Sign(data []byte) (sig []byte, err error) { + if len(s.k) != curve25519.PrivateKeySize { + err = errors.New("failed to sign: invalid curve25519 private key size") + return + } + h := sha512.Sum512(data) + sig, err = s.SignHash(h[:]) + return +} + +func (s *Curve25519Signer) SignHash(h []byte) (sig []byte, err error) { + return curve25519.Sign(rand.Reader, s.k, h) +} diff --git a/lib/crypto/doc.md b/lib/crypto/doc.md new file mode 100644 index 0000000..1752e51 --- /dev/null +++ b/lib/crypto/doc.md @@ -0,0 +1,623 @@ +# crypto +-- + import "github.com/go-i2p/go-i2p/lib/crypto" + +package for i2p specific crpytography + +## Usage + +```go +const ( + IPAD = byte(0x36) + OPAD = byte(0x5C) +) +``` + +```go +var ( + ElgDecryptFail = errors.New("failed to decrypt elgamal encrypted data") + ElgEncryptTooBig = errors.New("failed to encrypt data, too big for elgamal") +) +``` + +```go +var ( + ErrBadSignatureSize = errors.New("bad signature size") + ErrInvalidKeyFormat = errors.New("invalid key format") + ErrInvalidSignature = errors.New("invalid signature") +) +``` + +```go +var Ed25519EncryptTooBig = errors.New("failed to encrypt data, too big for Ed25519") +``` + +```go +var SHA256 = sha256.Sum256 +``` + +#### func ElgamalGenerate + +```go +func ElgamalGenerate(priv *elgamal.PrivateKey, rand io.Reader) (err error) +``` +generate an elgamal key pair + +#### type DSAPrivateKey + +```go +type DSAPrivateKey [20]byte +``` + + +#### func (DSAPrivateKey) Generate + +```go +func (k DSAPrivateKey) Generate() (s DSAPrivateKey, err error) +``` + +#### func (DSAPrivateKey) Len + +```go +func (k DSAPrivateKey) Len() int +``` + +#### func (DSAPrivateKey) NewSigner + +```go +func (k DSAPrivateKey) NewSigner() (s Signer, err error) +``` +create a new dsa signer + +#### func (DSAPrivateKey) Public + +```go +func (k DSAPrivateKey) Public() (pk DSAPublicKey, err error) +``` + +#### type DSAPublicKey + +```go +type DSAPublicKey [128]byte +``` + + +#### func (DSAPublicKey) Len + +```go +func (k DSAPublicKey) Len() int +``` + +#### func (DSAPublicKey) NewVerifier + +```go +func (k DSAPublicKey) NewVerifier() (v Verifier, err error) +``` +create a new dsa verifier + +#### type DSASigner + +```go +type DSASigner struct { +} +``` + + +#### func (*DSASigner) Sign + +```go +func (ds *DSASigner) Sign(data []byte) (sig []byte, err error) +``` + +#### func (*DSASigner) SignHash + +```go +func (ds *DSASigner) SignHash(h []byte) (sig []byte, err error) +``` + +#### type DSAVerifier + +```go +type DSAVerifier struct { +} +``` + + +#### func (*DSAVerifier) Verify + +```go +func (v *DSAVerifier) Verify(data, sig []byte) (err error) +``` +verify data with a dsa public key + +#### func (*DSAVerifier) VerifyHash + +```go +func (v *DSAVerifier) VerifyHash(h, sig []byte) (err error) +``` +verify hash of data with a dsa public key + +#### type Decrypter + +```go +type Decrypter interface { + // decrypt a block of data + // return decrypted block or nil and error if error happens + Decrypt(data []byte) ([]byte, error) +} +``` + +decrypts data + +#### type ECDSAVerifier + +```go +type ECDSAVerifier struct { +} +``` + + +#### func (*ECDSAVerifier) Verify + +```go +func (v *ECDSAVerifier) Verify(data, sig []byte) (err error) +``` +verify a block of data by hashing it and comparing the hash against the +signature + +#### func (*ECDSAVerifier) VerifyHash + +```go +func (v *ECDSAVerifier) VerifyHash(h, sig []byte) (err error) +``` +verify a signature given the hash + +#### type ECP256PrivateKey + +```go +type ECP256PrivateKey [32]byte +``` + + +#### type ECP256PublicKey + +```go +type ECP256PublicKey [64]byte +``` + + +#### func (ECP256PublicKey) Len + +```go +func (k ECP256PublicKey) Len() int +``` + +#### func (ECP256PublicKey) NewVerifier + +```go +func (k ECP256PublicKey) NewVerifier() (Verifier, error) +``` + +#### type ECP384PrivateKey + +```go +type ECP384PrivateKey [48]byte +``` + + +#### type ECP384PublicKey + +```go +type ECP384PublicKey [96]byte +``` + + +#### func (ECP384PublicKey) Len + +```go +func (k ECP384PublicKey) Len() int +``` + +#### func (ECP384PublicKey) NewVerifier + +```go +func (k ECP384PublicKey) NewVerifier() (Verifier, error) +``` + +#### type ECP521PrivateKey + +```go +type ECP521PrivateKey [66]byte +``` + + +#### type ECP521PublicKey + +```go +type ECP521PublicKey [132]byte +``` + + +#### func (ECP521PublicKey) Len + +```go +func (k ECP521PublicKey) Len() int +``` + +#### func (ECP521PublicKey) NewVerifier + +```go +func (k ECP521PublicKey) NewVerifier() (Verifier, error) +``` + +#### type Ed25519Encryption + +```go +type Ed25519Encryption struct { +} +``` + + +#### func (*Ed25519Encryption) Encrypt + +```go +func (ed25519 *Ed25519Encryption) Encrypt(data []byte) (enc []byte, err error) +``` + +#### func (*Ed25519Encryption) EncryptPadding + +```go +func (ed25519 *Ed25519Encryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error) +``` + +#### type Ed25519PrivateKey + +```go +type Ed25519PrivateKey ed25519.PrivateKey +``` + + +#### type Ed25519PublicKey + +```go +type Ed25519PublicKey []byte +``` + + +#### func (Ed25519PublicKey) Len + +```go +func (k Ed25519PublicKey) Len() int +``` + +#### func (Ed25519PublicKey) NewEncrypter + +```go +func (elg Ed25519PublicKey) NewEncrypter() (enc Encrypter, err error) +``` + +#### func (Ed25519PublicKey) NewVerifier + +```go +func (k Ed25519PublicKey) NewVerifier() (v Verifier, err error) +``` + +#### type Ed25519Signer + +```go +type Ed25519Signer struct { +} +``` + + +#### func (*Ed25519Signer) Sign + +```go +func (s *Ed25519Signer) Sign(data []byte) (sig []byte, err error) +``` + +#### func (*Ed25519Signer) SignHash + +```go +func (s *Ed25519Signer) SignHash(h []byte) (sig []byte, err error) +``` + +#### type Ed25519Verifier + +```go +type Ed25519Verifier struct { +} +``` + + +#### func (*Ed25519Verifier) Verify + +```go +func (v *Ed25519Verifier) Verify(data, sig []byte) (err error) +``` + +#### func (*Ed25519Verifier) VerifyHash + +```go +func (v *Ed25519Verifier) VerifyHash(h, sig []byte) (err error) +``` + +#### type ElgPrivateKey + +```go +type ElgPrivateKey [256]byte +``` + + +#### func (ElgPrivateKey) Len + +```go +func (elg ElgPrivateKey) Len() int +``` + +#### func (ElgPrivateKey) NewDecrypter + +```go +func (elg ElgPrivateKey) NewDecrypter() (dec Decrypter, err error) +``` + +#### type ElgPublicKey + +```go +type ElgPublicKey [256]byte +``` + + +#### func (ElgPublicKey) Len + +```go +func (elg ElgPublicKey) Len() int +``` + +#### func (ElgPublicKey) NewEncrypter + +```go +func (elg ElgPublicKey) NewEncrypter() (enc Encrypter, err error) +``` + +#### type ElgamalEncryption + +```go +type ElgamalEncryption struct { +} +``` + + +#### func (*ElgamalEncryption) Encrypt + +```go +func (elg *ElgamalEncryption) Encrypt(data []byte) (enc []byte, err error) +``` + +#### func (*ElgamalEncryption) EncryptPadding + +```go +func (elg *ElgamalEncryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error) +``` + +#### type Encrypter + +```go +type Encrypter interface { + // encrypt a block of data + // return encrypted block or nil and error if an error happened + Encrypt(data []byte) (enc []byte, err error) +} +``` + +encrypts data + +#### type HMACDigest + +```go +type HMACDigest [16]byte +``` + + +#### func I2PHMAC + +```go +func I2PHMAC(data []byte, k HMACKey) (d HMACDigest) +``` +do i2p hmac + +#### type HMACKey + +```go +type HMACKey [32]byte +``` + + +#### type PrivateEncryptionKey + +```go +type PrivateEncryptionKey interface { + // create a new decryption object for this private key to decrypt data encrypted to our public key + // returns decrypter or nil and error if the private key is in a bad format + NewDecrypter() (Decrypter, error) +} +``` + + +#### type PublicEncryptionKey + +```go +type PublicEncryptionKey interface { + // create a new encrypter to encrypt data to this public key + NewEncrypter() (Encrypter, error) + + // length of this public key in bytes + Len() int +} +``` + + +#### type PublicKey + +```go +type PublicKey interface { + Len() int + NewEncrypter() (Encrypter, error) +} +``` + + +#### type RSA2048PrivateKey + +```go +type RSA2048PrivateKey [512]byte +``` + + +#### type RSA2048PublicKey + +```go +type RSA2048PublicKey [256]byte +``` + + +#### type RSA3072PrivateKey + +```go +type RSA3072PrivateKey [786]byte +``` + + +#### type RSA3072PublicKey + +```go +type RSA3072PublicKey [384]byte +``` + + +#### type RSA4096PrivateKey + +```go +type RSA4096PrivateKey [1024]byte +``` + + +#### type RSA4096PublicKey + +```go +type RSA4096PublicKey [512]byte +``` + + +#### type Signer + +```go +type Signer interface { + // sign data with our private key by calling SignHash after hashing the data we are given + // return signature or nil signature and error if an error happened + Sign(data []byte) (sig []byte, err error) + + // sign hash of data with our private key + // return signature or nil signature and error if an error happened + SignHash(h []byte) (sig []byte, err error) +} +``` + +type for signing data + +#### type SigningPrivateKey + +```go +type SigningPrivateKey interface { + // create a new signer to sign data + // return signer or nil and error if key format is invalid + NewSigner() (Signer, error) + // length of this private key + Len() int + // get public key or return nil and error if invalid key data in private key + Public() (SigningPublicKey, error) + // generate a new private key, put it into itself + // returns itself or nil and error if an error occurs + Generate() (SigningPrivateKey, error) +} +``` + +key for signing data + +#### type SigningPublicKey + +```go +type SigningPublicKey interface { + // create new Verifier to verify the validity of signatures + // return verifier or nil and error if key format is invalid + NewVerifier() (Verifier, error) + // get the size of this public key + Len() int +} +``` + +key for verifying data + +#### type Tunnel + +```go +type Tunnel struct { +} +``` + + +#### func NewTunnelCrypto + +```go +func NewTunnelCrypto(layerKey, ivKey TunnelKey) (t *Tunnel, err error) +``` + +#### func (*Tunnel) Decrypt + +```go +func (t *Tunnel) Decrypt(td *TunnelData) +``` + +#### func (*Tunnel) Encrypt + +```go +func (t *Tunnel) Encrypt(td *TunnelData) +``` +encrypt tunnel data in place + +#### type TunnelData + +```go +type TunnelData [1028]byte +``` + + +#### type TunnelIV + +```go +type TunnelIV []byte +``` + +The initialization vector for a tunnel message + +#### type TunnelKey + +```go +type TunnelKey [32]byte +``` + +A symetric key for encrypting tunnel messages + +#### type Verifier + +```go +type Verifier interface { + // verify hashed data with this signing key + // return nil on valid signature otherwise error + VerifyHash(h, sig []byte) error + // verify an unhashed piece of data by hashing it and calling VerifyHash + Verify(data, sig []byte) error +} +``` + +type for verifying signatures diff --git a/lib/i2np/doc.md b/lib/i2np/doc.md new file mode 100644 index 0000000..e63adff --- /dev/null +++ b/lib/i2np/doc.md @@ -0,0 +1,343 @@ +# i2np +-- + import "github.com/go-i2p/go-i2p/lib/i2np" + + +## Usage + +```go +const ( + I2NP_MESSAGE_TYPE_DATABASE_STORE = 1 + I2NP_MESSAGE_TYPE_DATABASE_LOOKUP = 2 + I2NP_MESSAGE_TYPE_DATABASE_SEARCH_REPLY = 3 + I2NP_MESSAGE_TYPE_DELIVERY_STATUS = 10 + I2NP_MESSAGE_TYPE_GARLIC = 11 + I2NP_MESSAGE_TYPE_TUNNEL_DATA = 18 + I2NP_MESSAGE_TYPE_TUNNEL_GATEWAY = 19 + I2NP_MESSAGE_TYPE_DATA = 20 + I2NP_MESSAGE_TYPE_TUNNEL_BUILD = 21 + I2NP_MESSAGE_TYPE_TUNNEL_BUILD_REPLY = 22 + I2NP_MESSAGE_TYPE_VARIABLE_TUNNEL_BUILD = 23 + I2NP_MESSAGE_TYPE_VARIABLE_TUNNEL_BUILD_REPLY = 24 +) +``` + +```go +var ERR_BUILD_REQUEST_RECORD_NOT_ENOUGH_DATA = errors.New("not enough i2np build request record data") +``` + +```go +var ERR_I2NP_NOT_ENOUGH_DATA = errors.New("not enough i2np header data") +``` + +#### func ReadI2NPNTCPData + +```go +func ReadI2NPNTCPData(data []byte, size int) ([]byte, error) +``` + +#### func ReadI2NPNTCPMessageChecksum + +```go +func ReadI2NPNTCPMessageChecksum(data []byte) (int, error) +``` + +#### func ReadI2NPNTCPMessageExpiration + +```go +func ReadI2NPNTCPMessageExpiration(data []byte) (datalib.Date, error) +``` + +#### func ReadI2NPNTCPMessageID + +```go +func ReadI2NPNTCPMessageID(data []byte) (int, error) +``` + +#### func ReadI2NPNTCPMessageSize + +```go +func ReadI2NPNTCPMessageSize(data []byte) (int, error) +``` + +#### func ReadI2NPSSUMessageExpiration + +```go +func ReadI2NPSSUMessageExpiration(data []byte) (datalib.Date, error) +``` + +#### func ReadI2NPType + +```go +func ReadI2NPType(data []byte) (int, error) +``` + +#### type BuildRequestRecord + +```go +type BuildRequestRecord struct { + ReceiveTunnel tunnel.TunnelID + OurIdent common.Hash + NextTunnel tunnel.TunnelID + NextIdent common.Hash + LayerKey session_key.SessionKey + IVKey session_key.SessionKey + ReplyKey session_key.SessionKey + ReplyIV [16]byte + Flag int + RequestTime time.Time + SendMessageID int + Padding [29]byte +} +``` + + +#### func ReadBuildRequestRecord + +```go +func ReadBuildRequestRecord(data []byte) (BuildRequestRecord, error) +``` + +#### type BuildRequestRecordElGamal + +```go +type BuildRequestRecordElGamal [528]byte +``` + + +#### type BuildRequestRecordElGamalAES + +```go +type BuildRequestRecordElGamalAES [528]byte +``` + + +#### type BuildResponseRecord + +```go +type BuildResponseRecord struct { + Hash common.Hash + Padding [495]byte + Reply byte +} +``` + + +#### type BuildResponseRecordELGamal + +```go +type BuildResponseRecordELGamal [528]byte +``` + + +#### type BuildResponseRecordELGamalAES + +```go +type BuildResponseRecordELGamalAES [528]byte +``` + + +#### type Data + +```go +type Data struct { + Length int + Data []byte +} +``` + + +#### type DatabaseLookup + +```go +type DatabaseLookup struct { + Key common.Hash + From common.Hash + Flags byte + ReplyTunnelID [4]byte + Size int + ExcludedPeers []common.Hash + ReplyKey session_key.SessionKey + + ReplyTags []session_tag.SessionTag +} +``` + + +#### type DatabaseSearchReply + +```go +type DatabaseSearchReply struct { + Key common.Hash + Count int + PeerHashes []common.Hash + From common.Hash +} +``` + + +#### type DatabaseStore + +```go +type DatabaseStore struct { + Key common.Hash + Type byte + ReplyToken [4]byte + ReplyTunnelID [4]byte + ReplyGateway common.Hash + Data []byte +} +``` + + +#### type DeliveryStatus + +```go +type DeliveryStatus struct { + MessageID int + Timestamp time.Time +} +``` + + +#### type Garlic + +```go +type Garlic struct { + Count int + Cloves []GarlicClove + Certificate certificate.Certificate + MessageID int + Expiration time.Time +} +``` + + +#### type GarlicClove + +```go +type GarlicClove struct { + DeliveryInstructions GarlicCloveDeliveryInstructions + I2NPMessage I2NPMessage + CloveID int + Expiration time.Time + Certificate certificate.Certificate +} +``` + + +#### type GarlicCloveDeliveryInstructions + +```go +type GarlicCloveDeliveryInstructions struct { + Flag byte + SessionKey session_key.SessionKey + Hash common.Hash + TunnelID tunnel.TunnelID + Delay int +} +``` + + +#### type GarlicElGamal + +```go +type GarlicElGamal []byte +``` + + +#### type I2NPMessage + +```go +type I2NPMessage []byte +``` + + +#### type I2NPNTCPHeader + +```go +type I2NPNTCPHeader struct { + Type int + MessageID int + Expiration time.Time + Size int + Checksum int + Data []byte +} +``` + + +#### func ReadI2NPNTCPHeader + +```go +func ReadI2NPNTCPHeader(data []byte) (I2NPNTCPHeader, error) +``` +Read an entire I2NP message and return the parsed header with embedded encrypted +data + +#### type I2NPSSUHeader + +```go +type I2NPSSUHeader struct { + Type int + Expiration time.Time +} +``` + + +#### func ReadI2NPSSUHeader + +```go +func ReadI2NPSSUHeader(data []byte) (I2NPSSUHeader, error) +``` + +#### type TunnelBuild + +```go +type TunnelBuild [8]BuildRequestRecord +``` + + +#### type TunnelBuildReply + +```go +type TunnelBuildReply [8]BuildResponseRecord +``` + + +#### type TunnelData + +```go +type TunnelData [1028]byte +``` + + +#### type TunnelGatway + +```go +type TunnelGatway struct { + TunnelID tunnel.TunnelID + Length int + Data []byte +} +``` + + +#### type VariableTunnelBuild + +```go +type VariableTunnelBuild struct { + Count int + BuildRequestRecords []BuildRequestRecord +} +``` + + +#### type VariableTunnelBuildReply + +```go +type VariableTunnelBuildReply struct { + Count int + BuildResponseRecords []BuildResponseRecord +} +``` diff --git a/lib/i2np/fuzz/header/doc.md b/lib/i2np/fuzz/header/doc.md new file mode 100644 index 0000000..5d85fcc --- /dev/null +++ b/lib/i2np/fuzz/header/doc.md @@ -0,0 +1,12 @@ +# exportable +-- + import "github.com/go-i2p/go-i2p/lib/i2np/fuzz/header" + + +## Usage + +#### func Fuzz + +```go +func Fuzz(data []byte) int +``` diff --git a/lib/router/doc.md b/lib/router/doc.md new file mode 100644 index 0000000..7cada2d --- /dev/null +++ b/lib/router/doc.md @@ -0,0 +1,58 @@ +# router +-- + import "github.com/go-i2p/go-i2p/lib/router" + + +## Usage + +#### type Router + +```go +type Router struct { +} +``` + +i2p router type + +#### func CreateRouter + +```go +func CreateRouter() (r *Router, err error) +``` +create router with default configuration + +#### func FromConfig + +```go +func FromConfig(c *config.RouterConfig) (r *Router, err error) +``` +create router from configuration + +#### func (*Router) Close + +```go +func (r *Router) Close() error +``` +Close closes any internal state and finallizes router resources so that nothing +can start up again + +#### func (*Router) Start + +```go +func (r *Router) Start() +``` +Start starts router mainloop + +#### func (*Router) Stop + +```go +func (r *Router) Stop() +``` +Stop starts stopping internal state of router + +#### func (*Router) Wait + +```go +func (r *Router) Wait() +``` +Wait blocks until router is fully stopped diff --git a/lib/su3/doc.md b/lib/su3/doc.md new file mode 100644 index 0000000..7d315f4 --- /dev/null +++ b/lib/su3/doc.md @@ -0,0 +1,189 @@ +# su3 +-- + import "github.com/go-i2p/go-i2p/lib/su3" + +Package su3 implements reading the SU3 file format. + +SU3 files provide content that is signed by a known identity. They are used to +distribute many types of data, including reseed files, plugins, blocklists, and +more. + +See: https://geti2p.net/spec/updates#su3-file-specification + +The Read() function takes an io.Reader, and it returns a *SU3. The *SU3 contains +the SU3 file metadata, such as the type of the content and the signer ID. In +order to get the file contents, one must pass in the public key associated with +the file's signer, so that the signature can be validated. The content can still +be read without passing in the key, but after returning the full content the +error ErrInvalidSignature will be returned. + +Example usage: + + // Let's say we are reading an SU3 file from an HTTP body, which is an io.Reader. + su3File, err := su3.Read(body) + if err != nil { + // Handle error. + } + // Look up this signer's key. + key := somehow_lookup_the_key(su3File.SignerID) + // Read the content. + contentReader := su3File.Content(key) + bytes, err := ioutil.ReadAll(contentReader) + if errors.Is(err, su3.ErrInvalidSignature) { + // The signature is invalid, OR a nil key was provided. + } else if err != nil { + // Handle error. + } + +If you want to parse from a []byte, you can wrap it like this: + + mySU3FileBytes := []byte{0x00, 0x01, 0x02, 0x03} + su3File, err := su3.Read(bytes.NewReader(mySU3FileBytes)) + +One of the advantages of this library's design is that you can avoid buffering +the file contents in memory. Here's how you would stream from an HTTP body +directly to disk: + + su3File, err := su3.Read(body) + if err != nil { + // Handle error. + } + // Look up this signer's key. + key := somehow_lookup_the_key(su3File.SignerID) + // Stream directly to disk. + f, err := os.Create("my_file.txt") + if err != nil { + // Handle error. + } + _, err := io.Copy(f, su3File.Content(key)) + if errors.Is(err, su3.ErrInvalidSignature) { + // The signature is invalid, OR a nil key was provided. + // Don't trust the file, delete it! + } else if err != nil { + // Handle error. + } + +Note: if you want to read the content, the Content() io.Reader must be read +*before* the Signature() io.Reader. If you read the signature first, the content +bytes will be thrown away. If you then attempt to read the content, you will get +an error. For clarification, see TestReadSignatureFirst. + +## Usage + +```go +var ( + ErrMissingMagicBytes = errors.New("missing magic bytes") + ErrMissingUnusedByte6 = errors.New("missing unused byte 6") + ErrMissingFileFormatVersion = errors.New("missing or incorrect file format version") + ErrMissingSignatureType = errors.New("missing or invalid signature type") + ErrUnsupportedSignatureType = errors.New("unsupported signature type") + ErrMissingSignatureLength = errors.New("missing signature length") + ErrMissingUnusedByte12 = errors.New("missing unused byte 12") + ErrMissingVersionLength = errors.New("missing version length") + ErrVersionTooShort = errors.New("version length too short") + ErrMissingUnusedByte14 = errors.New("missing unused byte 14") + ErrMissingSignerIDLength = errors.New("missing signer ID length") + ErrMissingContentLength = errors.New("missing content length") + ErrMissingUnusedByte24 = errors.New("missing unused byte 24") + ErrMissingFileType = errors.New("missing or invalid file type") + ErrMissingUnusedByte26 = errors.New("missing unused byte 26") + ErrMissingContentType = errors.New("missing or invalid content type") + ErrMissingUnusedBytes28To39 = errors.New("missing unused bytes 28-39") + ErrMissingVersion = errors.New("missing version") + ErrMissingSignerID = errors.New("missing signer ID") + ErrMissingContent = errors.New("missing content") + ErrMissingSignature = errors.New("missing signature") + ErrInvalidPublicKey = errors.New("invalid public key") + ErrInvalidSignature = errors.New("invalid signature") +) +``` + +#### type ContentType + +```go +type ContentType string +``` + + +```go +const ( + UNKNOWN ContentType = "unknown" + ROUTER_UPDATE ContentType = "router_update" + PLUGIN ContentType = "plugin" + RESEED ContentType = "reseed" + NEWS ContentType = "news" + BLOCKLIST ContentType = "blocklist" +) +``` + +#### type FileType + +```go +type FileType string +``` + + +```go +const ( + ZIP FileType = "zip" + XML FileType = "xml" + HTML FileType = "html" + XML_GZIP FileType = "xml.gz" + TXT_GZIP FileType = "txt.gz" + DMG FileType = "dmg" + EXE FileType = "exe" +) +``` + +#### type SU3 + +```go +type SU3 struct { + SignatureType SignatureType + SignatureLength uint16 + ContentLength uint64 + FileType FileType + ContentType ContentType + Version string + SignerID string +} +``` + + +#### func Read + +```go +func Read(reader io.Reader) (su3 *SU3, err error) +``` + +#### func (*SU3) Content + +```go +func (su3 *SU3) Content(publicKey interface{}) io.Reader +``` + +#### func (*SU3) Signature + +```go +func (su3 *SU3) Signature() io.Reader +``` + +#### type SignatureType + +```go +type SignatureType string +``` + + +```go +const ( + DSA_SHA1 SignatureType = "DSA-SHA1" + ECDSA_SHA256_P256 SignatureType = "ECDSA-SHA256-P256" + ECDSA_SHA384_P384 SignatureType = "ECDSA-SHA384-P384" + ECDSA_SHA512_P521 SignatureType = "ECDSA-SHA512-P521" + RSA_SHA256_2048 SignatureType = "RSA-SHA256-2048" + RSA_SHA384_3072 SignatureType = "RSA-SHA384-3072" + RSA_SHA512_4096 SignatureType = "RSA-SHA512-4096" + EdDSA_SHA512_Ed25519ph SignatureType = "EdDSA-SHA512-Ed25519ph" +) +``` diff --git a/lib/tunnel/doc.md b/lib/tunnel/doc.md new file mode 100644 index 0000000..a993ddc --- /dev/null +++ b/lib/tunnel/doc.md @@ -0,0 +1,259 @@ +# tunnel +-- + import "github.com/go-i2p/go-i2p/lib/tunnel" + +i2p garlic tunnel implementation + +## Usage + +```go +const ( + DT_LOCAL = iota + DT_TUNNEL + DT_ROUTER + DT_UNUSED +) +``` + +```go +const ( + FIRST_FRAGMENT = iota + FOLLOW_ON_FRAGMENT +) +``` + +```go +const ( + FLAG_SIZE = 1 + TUNNEL_ID_SIZE = 4 + HASH_SIZE = 32 + DELAY_SIZE = 1 + MESSAGE_ID_SIZE = 4 + EXTENDED_OPTIONS_MIN_SIZE = 2 + SIZE_FIELD_SIZE = 2 +) +``` + +#### type DecryptedTunnelMessage + +```go +type DecryptedTunnelMessage [1028]byte +``` + + +#### func (DecryptedTunnelMessage) Checksum + +```go +func (decrypted_tunnel_message DecryptedTunnelMessage) Checksum() crypto.TunnelIV +``` + +#### func (DecryptedTunnelMessage) DeliveryInstructionsWithFragments + +```go +func (decrypted_tunnel_message DecryptedTunnelMessage) DeliveryInstructionsWithFragments() []DeliveryInstructionsWithFragment +``` +Returns a slice of DeliveryInstructionWithFragment structures, which all of the +Delivery Instructions in the tunnel message and their corresponding +MessageFragment structures. + +#### func (DecryptedTunnelMessage) ID + +```go +func (decrypted_tunnel_message DecryptedTunnelMessage) ID() TunnelID +``` + +#### func (DecryptedTunnelMessage) IV + +```go +func (decrypted_tunnel_message DecryptedTunnelMessage) IV() crypto.TunnelIV +``` + +#### type DelayFactor + +```go +type DelayFactor byte +``` + + +#### type DeliveryInstructions + +```go +type DeliveryInstructions []byte +``` + + +#### func (DeliveryInstructions) Delay + +```go +func (delivery_instructions DeliveryInstructions) Delay() (delay_factor DelayFactor, err error) +``` +Return the DelayFactor if present and any errors encountered parsing the +DeliveryInstructions. + +#### func (DeliveryInstructions) DeliveryType + +```go +func (delivery_instructions DeliveryInstructions) DeliveryType() (byte, error) +``` +Return the delivery type for these DeliveryInstructions, can be of type +DT_LOCAL, DT_TUNNEL, DT_ROUTER, or DT_UNUSED. + +#### func (DeliveryInstructions) ExtendedOptions + +```go +func (delivery_instructions DeliveryInstructions) ExtendedOptions() (data []byte, err error) +``` +Return the Extended Options data if present, or an error if not present. +Extended Options in unimplemented in the Java router and the presence of +extended options will generate a warning. + +#### func (DeliveryInstructions) FragmentNumber + +```go +func (delivery_instructions DeliveryInstructions) FragmentNumber() (int, error) +``` +Read the integer stored in the 6-1 bits of a FOLLOW_ON_FRAGMENT's flag, +indicating the fragment number. + +#### func (DeliveryInstructions) FragmentSize + +```go +func (delivery_instructions DeliveryInstructions) FragmentSize() (frag_size uint16, err error) +``` +Return the size of the associated I2NP fragment and an error if the data is +unavailable. + +#### func (DeliveryInstructions) Fragmented + +```go +func (delivery_instructions DeliveryInstructions) Fragmented() (bool, error) +``` +Returns true if the Delivery Instructions are fragmented or false if the +following data contains the entire message + +#### func (DeliveryInstructions) HasDelay + +```go +func (delivery_instructions DeliveryInstructions) HasDelay() (bool, error) +``` +Check if the delay bit is set. This feature in unimplemented in the Java router. + +#### func (DeliveryInstructions) HasExtendedOptions + +```go +func (delivery_instructions DeliveryInstructions) HasExtendedOptions() (bool, error) +``` +Check if the extended options bit is set. This feature in unimplemented in the +Java router. + +#### func (DeliveryInstructions) HasHash + +```go +func (delivery_instructions DeliveryInstructions) HasHash() (bool, error) +``` + +#### func (DeliveryInstructions) HasTunnelID + +```go +func (delivery_instructions DeliveryInstructions) HasTunnelID() (bool, error) +``` +Check if the DeliveryInstructions is of type DT_TUNNEL. + +#### func (DeliveryInstructions) Hash + +```go +func (delivery_instructions DeliveryInstructions) Hash() (hash common.Hash, err error) +``` +Return the hash for these DeliveryInstructions, which varies by hash type. + + If the type is DT_TUNNEL, hash is the SHA256 of the gateway router, if + the type is DT_ROUTER it is the SHA256 of the router. + +#### func (DeliveryInstructions) LastFollowOnFragment + +```go +func (delivery_instructions DeliveryInstructions) LastFollowOnFragment() (bool, error) +``` +Read the value of the 0 bit of a FOLLOW_ON_FRAGMENT, which is set to 1 to +indicate the last fragment. + +#### func (DeliveryInstructions) MessageID + +```go +func (delivery_instructions DeliveryInstructions) MessageID() (msgid uint32, err error) +``` +Return the I2NP Message ID or 0 and an error if the data is not available for +this DeliveryInstructions. + +#### func (DeliveryInstructions) TunnelID + +```go +func (delivery_instructions DeliveryInstructions) TunnelID() (tunnel_id uint32, err error) +``` +Return the tunnel ID in this DeliveryInstructions or 0 and an error if the +DeliveryInstructions are not of type DT_TUNNEL. + +#### func (DeliveryInstructions) Type + +```go +func (delivery_instructions DeliveryInstructions) Type() (int, error) +``` +Return if the DeliveryInstructions are of type FIRST_FRAGMENT or +FOLLOW_ON_FRAGMENT. + +#### type DeliveryInstructionsWithFragment + +```go +type DeliveryInstructionsWithFragment struct { + DeliveryInstructions DeliveryInstructions + MessageFragment []byte +} +``` + + +#### type EncryptedTunnelMessage + +```go +type EncryptedTunnelMessage crypto.TunnelData +``` + + +#### func (EncryptedTunnelMessage) Data + +```go +func (tm EncryptedTunnelMessage) Data() crypto.TunnelIV +``` + +#### func (EncryptedTunnelMessage) ID + +```go +func (tm EncryptedTunnelMessage) ID() (tid TunnelID) +``` + +#### func (EncryptedTunnelMessage) IV + +```go +func (tm EncryptedTunnelMessage) IV() crypto.TunnelIV +``` + +#### type Participant + +```go +type Participant struct { +} +``` + + +#### type Pool + +```go +type Pool struct{} +``` + +a pool of tunnels which we have created + +#### type TunnelID + +```go +type TunnelID uint32 +``` diff --git a/lib/util/doc.md b/lib/util/doc.md new file mode 100644 index 0000000..1380e22 --- /dev/null +++ b/lib/util/doc.md @@ -0,0 +1,39 @@ +# util +-- + import "github.com/go-i2p/go-i2p/lib/util" + + +## Usage + +#### func CheckFileAge + +```go +func CheckFileAge(fpath string, maxAge int) bool +``` +Check if a file is more than maxAge minutes old returns false if + +#### func CheckFileExists + +```go +func CheckFileExists(fpath string) bool +``` +Check if a file exists and is readable etc returns false if not + +#### func CloseAll + +```go +func CloseAll() +``` + +#### func Panicf + +```go +func Panicf(format string, args ...interface{}) +``` +Panicf allows passing formated string to panic() + +#### func RegisterCloser + +```go +func RegisterCloser(c io.Closer) +``` diff --git a/lib/util/signals/doc.md b/lib/util/signals/doc.md new file mode 100644 index 0000000..643aa0d --- /dev/null +++ b/lib/util/signals/doc.md @@ -0,0 +1,30 @@ +# signals +-- + import "github.com/go-i2p/go-i2p/lib/util/signals" + + +## Usage + +#### func Handle + +```go +func Handle() +``` + +#### func RegisterInterruptHandler + +```go +func RegisterInterruptHandler(f Handler) +``` + +#### func RegisterReloadHandler + +```go +func RegisterReloadHandler(f Handler) +``` + +#### type Handler + +```go +type Handler func() +``` From 1eb29ec4abb89b964c349de60b6011af7bc4300e Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Thu, 3 Oct 2024 22:36:23 -0400 Subject: [PATCH 18/94] formatting issues only --- lib/transport/noise/encrdecr_packet_test.go | 3 +-- lib/transport/noise/incoming_handshake.go | 2 +- lib/transport/noise/noise_constants.go | 2 +- lib/transport/noise/outgoing_handshake.go | 4 +++- lib/transport/noise/read_session.go | 2 +- lib/transport/noise/session.go | 8 +++----- lib/transport/noise/transport_test.go | 2 +- lib/transport/noise/write_session.go | 4 ++-- 8 files changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/transport/noise/encrdecr_packet_test.go b/lib/transport/noise/encrdecr_packet_test.go index ef4dc81..678a4a6 100644 --- a/lib/transport/noise/encrdecr_packet_test.go +++ b/lib/transport/noise/encrdecr_packet_test.go @@ -3,10 +3,9 @@ package noise import ( "crypto/rand" "encoding/binary" - "testing" - "github.com/flynn/noise" "github.com/stretchr/testify/assert" + "testing" ) func TestEncryptDecryptPacketOffline(t *testing.T) { diff --git a/lib/transport/noise/incoming_handshake.go b/lib/transport/noise/incoming_handshake.go index f9f6116..75abe6a 100644 --- a/lib/transport/noise/incoming_handshake.go +++ b/lib/transport/noise/incoming_handshake.go @@ -28,7 +28,7 @@ func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, e prologue := make([]byte, 2, uint16Size+len(negData)) binary.BigEndian.PutUint16(prologue, uint16(len(negData))) prologue = append(prologue, negData...) - // prologue = append(initString, prologue...) + //prologue = append(initString, prologue...) state, err = noise.NewHandshakeState(noise.Config{ StaticKeypair: s, Initiator: false, diff --git a/lib/transport/noise/noise_constants.go b/lib/transport/noise/noise_constants.go index 1e8a5d8..7fdab54 100644 --- a/lib/transport/noise/noise_constants.go +++ b/lib/transport/noise/noise_constants.go @@ -38,7 +38,7 @@ func initNegotiationData(negotiationData []byte) []byte { return negotiationData } negotiationData = make([]byte, 6) - binary.BigEndian.PutUint16(negotiationData, 1) // version + binary.BigEndian.PutUint16(negotiationData, 1) //version negotiationData[2] = NOISE_DH_CURVE25519 negotiationData[3] = NOISE_CIPHER_CHACHAPOLY negotiationData[4] = NOISE_HASH_SHA256 diff --git a/lib/transport/noise/outgoing_handshake.go b/lib/transport/noise/outgoing_handshake.go index 0303a78..5786924 100644 --- a/lib/transport/noise/outgoing_handshake.go +++ b/lib/transport/noise/outgoing_handshake.go @@ -13,7 +13,9 @@ import ( func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) { if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() { + return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported") + } negData = make([]byte, 6) copy(negData, initNegotiationData(nil)) @@ -28,7 +30,7 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, prologue := make([]byte, 2, uint16Size+len(negData)) binary.BigEndian.PutUint16(prologue, uint16(len(negData))) prologue = append(prologue, negData...) - // prologue = append(initString, prologue...) + //prologue = append(initString, prologue...) state, err = noise.NewHandshakeState(noise.Config{ StaticKeypair: s, Initiator: true, diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go index 35c0fda..da32f8b 100644 --- a/lib/transport/noise/read_session.go +++ b/lib/transport/noise/read_session.go @@ -71,7 +71,7 @@ func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { func (c *NoiseSession) readPacketLocked(data []byte) (int, error) { var n int - if len(data) == 0 { // special case to answer when everything is ok during handshake + if len(data) == 0 { //special case to answer when everything is ok during handshake if _, err := c.Conn.Read(make([]byte, 2)); err != nil { return 0, err } diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index 90a8ee6..8938039 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -52,10 +52,8 @@ func (noise_session *NoiseSession) SetWriteDeadline(t time.Time) error { return noise_session.Conn.SetWriteDeadline(t) } -var ( - exampleNoiseSession transport.TransportSession = &NoiseSession{} - ExampleNoiseSession net.Conn = exampleNoiseSession.(*NoiseSession) -) +var exampleNoiseSession transport.TransportSession = &NoiseSession{} +var ExampleNoiseSession net.Conn = exampleNoiseSession.(*NoiseSession) func (s *NoiseSession) LocalAddr() net.Addr { return s.Conn.LocalAddr() @@ -83,7 +81,7 @@ func newBlock() []byte { type VerifyCallbackFunc func(publicKey []byte, data []byte) error func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSession, error) { - // socket, err := DialNoise("noise", ri) + //socket, err := DialNoise("noise", ri) for _, addr := range ri.RouterAddresses() { socket, err := net.Dial("tcp", string(addr.Bytes())) if err != nil { diff --git a/lib/transport/noise/transport_test.go b/lib/transport/noise/transport_test.go index 52f06e3..a6cc0c2 100644 --- a/lib/transport/noise/transport_test.go +++ b/lib/transport/noise/transport_test.go @@ -29,5 +29,5 @@ func TestTransport(t *testing.T) { } ntt := NewNoiseTransport(lnn) t.Log(ntt.Name()) - // ntt.GetSession() + //ntt.GetSession() } diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index 35b4d29..7768880 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -50,7 +50,7 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { if err != nil { return 0, nil, fmt.Errorf("failed to encrypt: '%w'", err) } - // m := len(encryptedData) + //m := len(encryptedData) lengthPrefix := make([]byte, 2) binary.BigEndian.PutUint16(lengthPrefix, uint16(len(encryptedData))) @@ -81,7 +81,7 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { var n int - if len(data) == 0 { // special case to answer when everything is ok during handshake + if len(data) == 0 { //special case to answer when everything is ok during handshake if _, err := c.Conn.Write(make([]byte, 2)); err != nil { return 0, err } From 3a51a1229ebd56614f70aa31eecb3f19b99e6a18 Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Thu, 3 Oct 2024 22:45:33 -0400 Subject: [PATCH 19/94] more merge conflicts --- lib/netdb/std.go | 17 ----------------- lib/transport/ntcp/session.go | 6 ------ lib/transport/ntcp/transport.go | 7 ------- 3 files changed, 30 deletions(-) diff --git a/lib/netdb/std.go b/lib/netdb/std.go index 66403f7..1465c03 100644 --- a/lib/netdb/std.go +++ b/lib/netdb/std.go @@ -75,11 +75,7 @@ func (db *StdNetDB) Path() string { } // return how many routers we know about in our network database -<<<<<<< HEAD -func (db StdNetDB) Size() (routers int) { -======= func (db *StdNetDB) Size() (routers int) { ->>>>>>> 9f4154ff457f962bc3b5d77e266b5d87b4de3742 // TODO: implement this var err error var data []byte @@ -158,11 +154,7 @@ func (db *StdNetDB) RecalculateSize() (err error) { if err == nil { str := fmt.Sprintf("%d", count) var f *os.File -<<<<<<< HEAD - f, err = os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY, 0o600) -======= f, err = os.OpenFile(db.cacheFilePath(), os.O_CREATE|os.O_WRONLY, 0o600) ->>>>>>> 9f4154ff457f962bc3b5d77e266b5d87b4de3742 if err == nil { _, err = io.WriteString(f, str) f.Close() @@ -189,12 +181,7 @@ func (db *StdNetDB) Exists() bool { func (db *StdNetDB) SaveEntry(e *Entry) (err error) { var f io.WriteCloser -<<<<<<< HEAD - var h common.Hash - h = e.ri.IdentHash() -======= h := e.RouterInfo.IdentHash() ->>>>>>> 9f4154ff457f962bc3b5d77e266b5d87b4de3742 // if err == nil { f, err = os.OpenFile(db.SkiplistFile(h), os.O_WRONLY|os.O_CREATE, 0o700) if err == nil { @@ -236,11 +223,7 @@ func (db *StdNetDB) Ensure() (err error) { } // create base network database directory -<<<<<<< HEAD -func (db StdNetDB) Create() (err error) { -======= func (db *StdNetDB) Create() (err error) { ->>>>>>> 9f4154ff457f962bc3b5d77e266b5d87b4de3742 mode := os.FileMode(0o700) p := db.Path() log.Infof("Create network database in %s", p) diff --git a/lib/transport/ntcp/session.go b/lib/transport/ntcp/session.go index ccded7d..05ef411 100644 --- a/lib/transport/ntcp/session.go +++ b/lib/transport/ntcp/session.go @@ -1,11 +1,5 @@ package ntcp -import "github.com/go-i2p/go-i2p/lib/transport/noise" - // Session implements TransportSession // An established transport session -<<<<<<< HEAD -type Session noise.NoiseSession -======= type Session struct{} ->>>>>>> 9f4154ff457f962bc3b5d77e266b5d87b4de3742 diff --git a/lib/transport/ntcp/transport.go b/lib/transport/ntcp/transport.go index b39d433..0b12900 100644 --- a/lib/transport/ntcp/transport.go +++ b/lib/transport/ntcp/transport.go @@ -1,7 +1,5 @@ package ntcp -import "github.com/go-i2p/go-i2p/lib/transport/noise" - /** * https://geti2p.net/spec/ntcp2 **/ @@ -12,10 +10,5 @@ const ( NTCP_MESSAGE_MAX_SIZE = 65537 ) -<<<<<<< HEAD -// NTCPTransport is an ntcp transport implementing transport.Transport interface -type NTCPTransport noise.NoiseTransport -======= // Transport is an ntcp transport implementing transport.Transport interface type Transport struct{} ->>>>>>> 9f4154ff457f962bc3b5d77e266b5d87b4de3742 From d7378d7b0868eb391fc5baa79f3648b4b4e90bbe Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Thu, 3 Oct 2024 22:46:39 -0400 Subject: [PATCH 20/94] more merge conflicts --- go.mod | 19 ++++--------------- go.sum | 18 ++++++------------ 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 4530c8f..633b162 100644 --- a/go.mod +++ b/go.mod @@ -1,32 +1,21 @@ module github.com/go-i2p/go-i2p -go 1.22 - -toolchain go1.22.5 +go 1.23.1 require ( -<<<<<<< HEAD github.com/emirpasic/gods v1.18.1 - github.com/flynn/noise v1.1.0 - github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.9.0 -======= github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e github.com/flynn/noise v1.1.0 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 - go.step.sm/crypto v0.51.2 ->>>>>>> 9f4154ff457f962bc3b5d77e266b5d87b4de3742 - golang.org/x/crypto v0.26.0 + go.step.sm/crypto v0.53.0 + golang.org/x/crypto v0.27.0 ) require ( -<<<<<<< HEAD -======= filippo.io/edwards25519 v1.1.0 // indirect ->>>>>>> 9f4154ff457f962bc3b5d77e266b5d87b4de3742 github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.24.0 // indirect + golang.org/x/sys v0.25.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 94d5f18..6c67222 100644 --- a/go.sum +++ b/go.sum @@ -3,13 +3,10 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -<<<<<<< HEAD github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -======= github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e h1:NMjWYVkgcQHGOy0/VxU0TU6smrcoxzj9hwDesx2sB0w= github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e/go.mod h1:fKfFM3BsOOyjtZmEty7FsGzGabXo8Eb/dHjyIhTtxsE= ->>>>>>> 9f4154ff457f962bc3b5d77e266b5d87b4de3742 github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= @@ -25,19 +22,16 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -<<<<<<< HEAD -======= -go.step.sm/crypto v0.51.2 h1:5EiCGIMg7IvQTGmJrwRosbXeprtT80OhoS/PJarg60o= -go.step.sm/crypto v0.51.2/go.mod h1:QK7czLjN2k+uqVp5CHXxJbhc70kVRSP+0CQF3zsR5M0= ->>>>>>> 9f4154ff457f962bc3b5d77e266b5d87b4de3742 +go.step.sm/crypto v0.53.0 h1:+1as1ogzuCzx15/468M4mEC5juogI5a0Fzbsyh1CuYY= +go.step.sm/crypto v0.53.0/go.mod h1:AqLU78RqNUHepLzyOWZuNN/2++Lu7dZENdO9UzWOGSk= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 9469fd83aa7b347378cf7dc86bf9cc90e04edc51 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 4 Oct 2024 22:36:32 -0400 Subject: [PATCH 21/94] AES --- lib/crypto/aes.go | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/lib/crypto/aes.go b/lib/crypto/aes.go index 5871506..288a6f2 100644 --- a/lib/crypto/aes.go +++ b/lib/crypto/aes.go @@ -1 +1,66 @@ package crypto + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "fmt" +) + +func aesEncrypt(key, iv, plaintext []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + plaintext = pkcs7Pad(plaintext, aes.BlockSize) + ciphertext := make([]byte, len(plaintext)) + mode := cipher.NewCBCEncrypter(block, iv) + mode.CryptBlocks(ciphertext, plaintext) + return ciphertext, nil +} + +func aesDecrypt(key, iv, ciphertext []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + if len(ciphertext)%aes.BlockSize != 0 { + return nil, fmt.Errorf("ciphertext is not a multiple of the block size") + } + + plaintext := make([]byte, len(ciphertext)) + mode := cipher.NewCBCDecrypter(block, iv) + mode.CryptBlocks(plaintext, ciphertext) + + plaintext, err = pkcs7Unpad(plaintext) + if err != nil { + return nil, err + } + return plaintext, nil +} + +func pkcs7Pad(data []byte, blockSize int) []byte { + padding := blockSize - (len(data) % blockSize) + padText := bytes.Repeat([]byte{byte(padding)}, padding) + return append(data, padText...) +} + +func pkcs7Unpad(data []byte) ([]byte, error) { + length := len(data) + if length == 0 { + return nil, fmt.Errorf("data is empty") + } + padding := int(data[length-1]) + if padding == 0 || padding > aes.BlockSize || length < aes.BlockSize { + return nil, fmt.Errorf("invalid padding") + } + paddingStart := length - padding + for i := paddingStart; i < length; i++ { + if data[i] != byte(padding) { + return nil, fmt.Errorf("invalid padding") + } + } + return data[:paddingStart], nil +} From 677a6b354b132be4c930cd89683092cd319d70d9 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 4 Oct 2024 22:37:57 -0400 Subject: [PATCH 22/94] AES test --- lib/crypto/aes_test.go | 146 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 lib/crypto/aes_test.go diff --git a/lib/crypto/aes_test.go b/lib/crypto/aes_test.go new file mode 100644 index 0000000..615bd9a --- /dev/null +++ b/lib/crypto/aes_test.go @@ -0,0 +1,146 @@ +package crypto + +import ( + "bytes" + "crypto/aes" + "crypto/rand" + "encoding/hex" + "testing" +) + +func TestAESEncryptDecrypt(t *testing.T) { + key := make([]byte, 32) // 256-bit key + iv := make([]byte, aes.BlockSize) + _, err := rand.Read(key) + if err != nil { + t.Fatalf("Failed to generate random key: %v", err) + } + _, err = rand.Read(iv) + if err != nil { + t.Fatalf("Failed to generate random IV: %v", err) + } + + testCases := []struct { + name string + plaintext []byte + }{ + {"Empty string", []byte("")}, + {"Short string", []byte("Hello, World!")}, + {"Long string", bytes.Repeat([]byte("A"), 1000)}, + {"Exact block size", bytes.Repeat([]byte("A"), aes.BlockSize)}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + ciphertext, err := aesEncrypt(key, iv, tc.plaintext) + if err != nil { + t.Fatalf("Encryption failed: %v", err) + } + + decrypted, err := aesDecrypt(key, iv, ciphertext) + if err != nil { + t.Fatalf("Decryption failed: %v", err) + } + + if !bytes.Equal(tc.plaintext, decrypted) { + t.Errorf("Decrypted text doesn't match original plaintext.\nOriginal: %s\nDecrypted: %s", + hex.EncodeToString(tc.plaintext), hex.EncodeToString(decrypted)) + } + }) + } +} + +func TestAESEncryptInvalidKey(t *testing.T) { + invalidKeys := [][]byte{ + make([]byte, 15), // Too short + make([]byte, 33), // Too long + make([]byte, 0), // Empty + nil, // Nil + } + + plaintext := []byte("Test plaintext") + iv := make([]byte, aes.BlockSize) + + for _, key := range invalidKeys { + _, err := aesEncrypt(key, iv, plaintext) + if err == nil { + t.Errorf("Expected error for invalid key length %d, but got none", len(key)) + } + } +} + +func TestAESDecryptInvalidInput(t *testing.T) { + key := make([]byte, 32) + iv := make([]byte, aes.BlockSize) + _, _ = rand.Read(key) + _, _ = rand.Read(iv) + + invalidCiphertexts := [][]byte{ + make([]byte, 15), // Not a multiple of block size + make([]byte, 0), // Empty + nil, // Nil + } + + for _, ciphertext := range invalidCiphertexts { + _, err := aesDecrypt(key, iv, ciphertext) + if err == nil { + t.Errorf("Expected error for invalid ciphertext length %d, but got none", len(ciphertext)) + } + } +} + +func TestPKCS7PadUnpad(t *testing.T) { + testCases := []struct { + name string + input []byte + blockSize int + }{ + {"Empty input", []byte{}, 16}, + {"Exact block size", bytes.Repeat([]byte("A"), 16), 16}, + {"One byte short", bytes.Repeat([]byte("A"), 15), 16}, + {"Multiple blocks", bytes.Repeat([]byte("A"), 32), 16}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + padded := pkcs7Pad(tc.input, tc.blockSize) + if len(padded)%tc.blockSize != 0 { + t.Errorf("Padded data length (%d) is not a multiple of block size (%d)", len(padded), tc.blockSize) + } + + unpadded, err := pkcs7Unpad(padded) + if err != nil { + t.Fatalf("Unpadding failed: %v", err) + } + + if !bytes.Equal(tc.input, unpadded) { + t.Errorf("Unpadded data doesn't match original input.\nOriginal: %s\nUnpadded: %s", + hex.EncodeToString(tc.input), hex.EncodeToString(unpadded)) + } + }) + } +} + +func TestPKCS7UnpadInvalidInput(t *testing.T) { + invalidInputs := []struct { + name string + input []byte + }{ + {"Empty slice", []byte{}}, + {"Too short", []byte{1, 2, 3}}, + {"Invalid padding value", []byte{1, 2, 3, 4, 5}}, + {"Padding larger than block size", append(bytes.Repeat([]byte{17}, 17))}, + {"Incorrect padding", append(bytes.Repeat([]byte{4}, 12))}, + {"Padding larger than data", []byte{5, 5, 5, 5, 5}}, + {"Valid block size but invalid padding", append(bytes.Repeat([]byte{1}, 15), 3)}, + } + + for _, tc := range invalidInputs { + t.Run(tc.name, func(t *testing.T) { + _, err := pkcs7Unpad(tc.input) + if err == nil { + t.Errorf("Expected error for invalid input %v, but got none", tc.input) + } + }) + } +} From 491b25022edbb26c3d5b067b0cc3df79101a990b Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 5 Oct 2024 09:00:33 -0400 Subject: [PATCH 23/94] AES -Revamped encrypt and decrypt to fit with interfaces -Adjusted test cases for TestPKCS7UnpadInvalidInput() --- lib/crypto/aes.go | 63 ++++++++++++++++++++++++++++++++++-------- lib/crypto/aes_test.go | 59 +++++++++++++++++++++++++++++++-------- 2 files changed, 100 insertions(+), 22 deletions(-) diff --git a/lib/crypto/aes.go b/lib/crypto/aes.go index 288a6f2..7ebd6fa 100644 --- a/lib/crypto/aes.go +++ b/lib/crypto/aes.go @@ -7,32 +7,52 @@ import ( "fmt" ) -func aesEncrypt(key, iv, plaintext []byte) ([]byte, error) { - block, err := aes.NewCipher(key) +// AesSymmetricKey represents a symmetric key for AES encryption/decryption +type AesSymmetricKey struct { + Key []byte // AES key (must be 16, 24, or 32 bytes for AES-128, AES-192, AES-256) + IV []byte // Initialization Vector (must be 16 bytes for AES) +} + +// AesSymmetricEncrypter implements the Encrypter interface using AES +type AesSymmetricEncrypter struct { + Key []byte + IV []byte +} + +// Encrypt encrypts data using AES-CBC with PKCS#7 padding +func (e *AesSymmetricEncrypter) Encrypt(data []byte) ([]byte, error) { + block, err := aes.NewCipher(e.Key) if err != nil { return nil, err } - plaintext = pkcs7Pad(plaintext, aes.BlockSize) + plaintext := pkcs7Pad(data, aes.BlockSize) ciphertext := make([]byte, len(plaintext)) - mode := cipher.NewCBCEncrypter(block, iv) + mode := cipher.NewCBCEncrypter(block, e.IV) mode.CryptBlocks(ciphertext, plaintext) return ciphertext, nil } -func aesDecrypt(key, iv, ciphertext []byte) ([]byte, error) { - block, err := aes.NewCipher(key) +// AesSymmetricDecrypter implements the Decrypter interface using AES +type AesSymmetricDecrypter struct { + Key []byte + IV []byte +} + +// Decrypt decrypts data using AES-CBC with PKCS#7 padding +func (d *AesSymmetricDecrypter) Decrypt(data []byte) ([]byte, error) { + block, err := aes.NewCipher(d.Key) if err != nil { return nil, err } - if len(ciphertext)%aes.BlockSize != 0 { + if len(data)%aes.BlockSize != 0 { return nil, fmt.Errorf("ciphertext is not a multiple of the block size") } - plaintext := make([]byte, len(ciphertext)) - mode := cipher.NewCBCDecrypter(block, iv) - mode.CryptBlocks(plaintext, ciphertext) + plaintext := make([]byte, len(data)) + mode := cipher.NewCBCDecrypter(block, d.IV) + mode.CryptBlocks(plaintext, data) plaintext, err = pkcs7Unpad(plaintext) if err != nil { @@ -41,6 +61,27 @@ func aesDecrypt(key, iv, ciphertext []byte) ([]byte, error) { return plaintext, nil } +// NewEncrypter creates a new AesSymmetricEncrypter +func (k *AesSymmetricKey) NewEncrypter() (Encrypter, error) { + return &AesSymmetricEncrypter{ + Key: k.Key, + IV: k.IV, + }, nil +} + +// Len returns the length of the key +func (k *AesSymmetricKey) Len() int { + return len(k.Key) +} + +// NewDecrypter creates a new AesSymmetricDecrypter +func (k *AesSymmetricKey) NewDecrypter() (Decrypter, error) { + return &AesSymmetricDecrypter{ + Key: k.Key, + IV: k.IV, + }, nil +} + func pkcs7Pad(data []byte, blockSize int) []byte { padding := blockSize - (len(data) % blockSize) padText := bytes.Repeat([]byte{byte(padding)}, padding) @@ -53,7 +94,7 @@ func pkcs7Unpad(data []byte) ([]byte, error) { return nil, fmt.Errorf("data is empty") } padding := int(data[length-1]) - if padding == 0 || padding > aes.BlockSize || length < aes.BlockSize { + if padding == 0 || padding > aes.BlockSize { return nil, fmt.Errorf("invalid padding") } paddingStart := length - padding diff --git a/lib/crypto/aes_test.go b/lib/crypto/aes_test.go index 615bd9a..a3230de 100644 --- a/lib/crypto/aes_test.go +++ b/lib/crypto/aes_test.go @@ -5,6 +5,7 @@ import ( "crypto/aes" "crypto/rand" "encoding/hex" + log "github.com/sirupsen/logrus" "testing" ) @@ -20,6 +21,21 @@ func TestAESEncryptDecrypt(t *testing.T) { t.Fatalf("Failed to generate random IV: %v", err) } + symmetricKey := AesSymmetricKey{ + Key: key, + IV: iv, + } + + encrypter, err := symmetricKey.NewEncrypter() + if err != nil { + log.Fatalf("Error creating encrypter: %v", err) + } + + decrypter, err := symmetricKey.NewDecrypter() + if err != nil { + log.Fatalf("Error creating decrypter: %v", err) + } + testCases := []struct { name string plaintext []byte @@ -32,12 +48,12 @@ func TestAESEncryptDecrypt(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - ciphertext, err := aesEncrypt(key, iv, tc.plaintext) + ciphertext, err := encrypter.Encrypt(tc.plaintext) if err != nil { t.Fatalf("Encryption failed: %v", err) } - decrypted, err := aesDecrypt(key, iv, ciphertext) + decrypted, err := decrypter.Decrypt(ciphertext) if err != nil { t.Fatalf("Decryption failed: %v", err) } @@ -53,6 +69,8 @@ func TestAESEncryptDecrypt(t *testing.T) { func TestAESEncryptInvalidKey(t *testing.T) { invalidKeys := [][]byte{ make([]byte, 15), // Too short + make([]byte, 17), // Invalid length + make([]byte, 31), // Too short for AES-256 make([]byte, 33), // Too long make([]byte, 0), // Empty nil, // Nil @@ -60,21 +78,40 @@ func TestAESEncryptInvalidKey(t *testing.T) { plaintext := []byte("Test plaintext") iv := make([]byte, aes.BlockSize) + _, _ = rand.Read(iv) for _, key := range invalidKeys { - _, err := aesEncrypt(key, iv, plaintext) + symmetricKey := &AesSymmetricKey{ + Key: key, + IV: iv, + } + encrypter, err := symmetricKey.NewEncrypter() + if err == nil { + _, err = encrypter.Encrypt(plaintext) + } if err == nil { t.Errorf("Expected error for invalid key length %d, but got none", len(key)) + } else { + t.Logf("Correctly got error for key length %d: %v", len(key), err) } } } func TestAESDecryptInvalidInput(t *testing.T) { - key := make([]byte, 32) + key := make([]byte, 32) // Valid key length for AES-256 iv := make([]byte, aes.BlockSize) _, _ = rand.Read(key) _, _ = rand.Read(iv) + symmetricKey := &AesSymmetricKey{ + Key: key, + IV: iv, + } + decrypter, err := symmetricKey.NewDecrypter() + if err != nil { + t.Fatalf("Failed to create decrypter: %v", err) + } + invalidCiphertexts := [][]byte{ make([]byte, 15), // Not a multiple of block size make([]byte, 0), // Empty @@ -82,9 +119,11 @@ func TestAESDecryptInvalidInput(t *testing.T) { } for _, ciphertext := range invalidCiphertexts { - _, err := aesDecrypt(key, iv, ciphertext) + _, err := decrypter.Decrypt(ciphertext) if err == nil { t.Errorf("Expected error for invalid ciphertext length %d, but got none", len(ciphertext)) + } else { + t.Logf("Correctly got error for ciphertext length %d: %v", len(ciphertext), err) } } } @@ -127,12 +166,10 @@ func TestPKCS7UnpadInvalidInput(t *testing.T) { input []byte }{ {"Empty slice", []byte{}}, - {"Too short", []byte{1, 2, 3}}, - {"Invalid padding value", []byte{1, 2, 3, 4, 5}}, - {"Padding larger than block size", append(bytes.Repeat([]byte{17}, 17))}, - {"Incorrect padding", append(bytes.Repeat([]byte{4}, 12))}, - {"Padding larger than data", []byte{5, 5, 5, 5, 5}}, - {"Valid block size but invalid padding", append(bytes.Repeat([]byte{1}, 15), 3)}, + {"Invalid padding value", []byte{1, 2, 3, 4, 0}}, // Padding value 0 is invalid + {"Padding larger than block size", append(bytes.Repeat([]byte{17}, 17))}, // Padding value 17 (>16) is invalid + {"Incorrect padding bytes", []byte{1, 2, 3, 4, 5, 6, 2, 3, 3}}, // Last padding bytes do not match padding value + {"Valid block size but invalid padding", append(bytes.Repeat([]byte{1}, 15), 3)}, // Padding value 3, but bytes are 1 } for _, tc := range invalidInputs { From 50fa9fc37482e880e9edf7b4e9e8248f2a7b4405 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 5 Oct 2024 09:43:58 -0400 Subject: [PATCH 24/94] gofumpt adjustment --- lib/crypto/aes_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/crypto/aes_test.go b/lib/crypto/aes_test.go index a3230de..d3e3ebf 100644 --- a/lib/crypto/aes_test.go +++ b/lib/crypto/aes_test.go @@ -5,8 +5,9 @@ import ( "crypto/aes" "crypto/rand" "encoding/hex" - log "github.com/sirupsen/logrus" "testing" + + log "github.com/sirupsen/logrus" ) func TestAESEncryptDecrypt(t *testing.T) { From 684e89c957cc3cd9bd441bc5d2afa1a584c71315 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 5 Oct 2024 10:15:31 -0400 Subject: [PATCH 25/94] minor typo --- lib/transport/doc.md | 10 +++++----- lib/transport/multi.go | 6 +++--- lib/transport/transport.go | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/transport/doc.md b/lib/transport/doc.md index bb80315..c3269c1 100644 --- a/lib/transport/doc.md +++ b/lib/transport/doc.md @@ -35,8 +35,8 @@ type Transport interface { // returns nil and an error on error GetSession(routerInfo router_info.RouterInfo) (TransportSession, error) - // return true if a routerInfo is compatable with this transport - Compatable(routerInfo router_info.RouterInfo) bool + // return true if a routerInfo is compatible with this transport + Compatible(routerInfo router_info.RouterInfo) bool // close the transport cleanly // blocks until done @@ -72,12 +72,12 @@ func (tmux *TransportMuxer) Close() (err error) ``` close every transport that this transport muxer has -#### func (*TransportMuxer) Compatable +#### func (*TransportMuxer) Compatible ```go -func (tmux *TransportMuxer) Compatable(routerInfo router_info.RouterInfo) (compat bool) +func (tmux *TransportMuxer) Compatible(routerInfo router_info.RouterInfo) (compat bool) ``` -is there a transport that we mux that is compatable with this router info? +is there a transport that we mux that is compatible with this router info? #### func (*TransportMuxer) GetSession diff --git a/lib/transport/multi.go b/lib/transport/multi.go index 65617ad..1d3331c 100644 --- a/lib/transport/multi.go +++ b/lib/transport/multi.go @@ -57,7 +57,7 @@ func (tmux *TransportMuxer) Name() string { func (tmux *TransportMuxer) GetSession(routerInfo router_info.RouterInfo) (s TransportSession, err error) { for _, t := range tmux.trans { // pick the first one that is compatable - if t.Compatable(routerInfo) { + if t.Compatible(routerInfo) { // try to get a session s, err = t.GetSession(routerInfo) if err != nil { @@ -75,9 +75,9 @@ func (tmux *TransportMuxer) GetSession(routerInfo router_info.RouterInfo) (s Tra } // is there a transport that we mux that is compatable with this router info? -func (tmux *TransportMuxer) Compatable(routerInfo router_info.RouterInfo) (compat bool) { +func (tmux *TransportMuxer) Compatible(routerInfo router_info.RouterInfo) (compat bool) { for _, t := range tmux.trans { - if t.Compatable(routerInfo) { + if t.Compatible(routerInfo) { compat = true return } diff --git a/lib/transport/transport.go b/lib/transport/transport.go index 79321f7..9233fcd 100644 --- a/lib/transport/transport.go +++ b/lib/transport/transport.go @@ -43,8 +43,8 @@ type Transport interface { // returns nil and an error on error GetSession(routerInfo router_info.RouterInfo) (TransportSession, error) - // return true if a routerInfo is compatable with this transport - Compatable(routerInfo router_info.RouterInfo) bool + // return true if a routerInfo is compatible with this transport + Compatible(routerInfo router_info.RouterInfo) bool // close the transport cleanly // blocks until done From 278bdee277995a8176aaa0b11c13cae5b34fabe5 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sun, 6 Oct 2024 10:45:26 -0400 Subject: [PATCH 26/94] Various changes -Aes -> AES -doc.md --- lib/crypto/aes.go | 30 +++++++++---------- lib/crypto/aes_test.go | 6 ++-- lib/crypto/doc.md | 65 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 18 deletions(-) diff --git a/lib/crypto/aes.go b/lib/crypto/aes.go index 7ebd6fa..8465615 100644 --- a/lib/crypto/aes.go +++ b/lib/crypto/aes.go @@ -7,20 +7,20 @@ import ( "fmt" ) -// AesSymmetricKey represents a symmetric key for AES encryption/decryption -type AesSymmetricKey struct { +// AESSymmetricKey represents a symmetric key for AES encryption/decryption +type AESSymmetricKey struct { Key []byte // AES key (must be 16, 24, or 32 bytes for AES-128, AES-192, AES-256) IV []byte // Initialization Vector (must be 16 bytes for AES) } -// AesSymmetricEncrypter implements the Encrypter interface using AES -type AesSymmetricEncrypter struct { +// AESSymmetricEncrypter implements the Encrypter interface using AES +type AESSymmetricEncrypter struct { Key []byte IV []byte } // Encrypt encrypts data using AES-CBC with PKCS#7 padding -func (e *AesSymmetricEncrypter) Encrypt(data []byte) ([]byte, error) { +func (e *AESSymmetricEncrypter) Encrypt(data []byte) ([]byte, error) { block, err := aes.NewCipher(e.Key) if err != nil { return nil, err @@ -33,14 +33,14 @@ func (e *AesSymmetricEncrypter) Encrypt(data []byte) ([]byte, error) { return ciphertext, nil } -// AesSymmetricDecrypter implements the Decrypter interface using AES -type AesSymmetricDecrypter struct { +// AESSymmetricDecrypter implements the Decrypter interface using AES +type AESSymmetricDecrypter struct { Key []byte IV []byte } // Decrypt decrypts data using AES-CBC with PKCS#7 padding -func (d *AesSymmetricDecrypter) Decrypt(data []byte) ([]byte, error) { +func (d *AESSymmetricDecrypter) Decrypt(data []byte) ([]byte, error) { block, err := aes.NewCipher(d.Key) if err != nil { return nil, err @@ -61,22 +61,22 @@ func (d *AesSymmetricDecrypter) Decrypt(data []byte) ([]byte, error) { return plaintext, nil } -// NewEncrypter creates a new AesSymmetricEncrypter -func (k *AesSymmetricKey) NewEncrypter() (Encrypter, error) { - return &AesSymmetricEncrypter{ +// NewEncrypter creates a new AESSymmetricEncrypter +func (k *AESSymmetricKey) NewEncrypter() (Encrypter, error) { + return &AESSymmetricEncrypter{ Key: k.Key, IV: k.IV, }, nil } // Len returns the length of the key -func (k *AesSymmetricKey) Len() int { +func (k *AESSymmetricKey) Len() int { return len(k.Key) } -// NewDecrypter creates a new AesSymmetricDecrypter -func (k *AesSymmetricKey) NewDecrypter() (Decrypter, error) { - return &AesSymmetricDecrypter{ +// NewDecrypter creates a new AESSymmetricDecrypter +func (k *AESSymmetricKey) NewDecrypter() (Decrypter, error) { + return &AESSymmetricDecrypter{ Key: k.Key, IV: k.IV, }, nil diff --git a/lib/crypto/aes_test.go b/lib/crypto/aes_test.go index d3e3ebf..a2311a7 100644 --- a/lib/crypto/aes_test.go +++ b/lib/crypto/aes_test.go @@ -22,7 +22,7 @@ func TestAESEncryptDecrypt(t *testing.T) { t.Fatalf("Failed to generate random IV: %v", err) } - symmetricKey := AesSymmetricKey{ + symmetricKey := AESSymmetricKey{ Key: key, IV: iv, } @@ -82,7 +82,7 @@ func TestAESEncryptInvalidKey(t *testing.T) { _, _ = rand.Read(iv) for _, key := range invalidKeys { - symmetricKey := &AesSymmetricKey{ + symmetricKey := &AESSymmetricKey{ Key: key, IV: iv, } @@ -104,7 +104,7 @@ func TestAESDecryptInvalidInput(t *testing.T) { _, _ = rand.Read(key) _, _ = rand.Read(iv) - symmetricKey := &AesSymmetricKey{ + symmetricKey := &AESSymmetricKey{ Key: key, IV: iv, } diff --git a/lib/crypto/doc.md b/lib/crypto/doc.md index 1752e51..ecb87b3 100644 --- a/lib/crypto/doc.md +++ b/lib/crypto/doc.md @@ -12,7 +12,72 @@ const ( OPAD = byte(0x5C) ) ``` +#### type AESSymmetricKey +```go +type AESSymmetricKey struct { + Key []byte // AES key (must be 16, 24, or 32 bytes for AES-128, AES-192, AES-256) + IV []byte // Initialization Vector (must be 16 bytes for AES) +} +``` +AESSymmetricKey represents a symmetric key for AES encryption/decryption + +#### func (AESSymmetricKey) NewEncrypter + +```go +func (k *AESSymmetricKey) NewEncrypter() (Encrypter, error) +``` +NewEncrypter creates a new AESSymmetricEncrypter + +#### func (AESSymmetricKey) NewDecrypter + +```go +func (k *AESSymmetricKey) NewDecrypter() (Decrypter, error) +``` +NewDecrypter creates a new AESSymmetricDecrypter + +#### func (AESSymmetricKey) Len + +```go +func (k *AESSymmetricKey) Len() int +``` +Len returns the length of the key + +#### type AESSymmetricEncrypter + +```go +type AESSymmetricEncrypter struct { + Key []byte + IV []byte +} +``` + +AESSymmetricEncrypter implements the Encrypter interface using AES + +#### func (*AESSymmetricEncrypter) Encrypt + +```go +func (e *AESSymmetricEncrypter) Encrypt(data []byte) ([]byte, error) +``` +Encrypt encrypts data using AES-CBC with PKCS#7 padding + +#### type AESSymmetricDecrypter + +```go +type AESSymmetricDecrypter struct { + Key []byte + IV []byte +} +``` + +AESSymmetricDecrypter implements the Decrypter interface using AES + +#### func (*AESSymmetricDecrypter) Decrypt + +```go +func (d *AESSymmetricDecrypter) Decrypt(data []byte) ([]byte, error) +``` +Decrypt decrypts data using AES-CBC with PKCS#7 padding ```go var ( ElgDecryptFail = errors.New("failed to decrypt elgamal encrypted data") From a7689e801ab22a9fc62245fb7d31dfdc3bcf8492 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sun, 6 Oct 2024 12:13:04 -0400 Subject: [PATCH 27/94] minor typo --- lib/crypto/doc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/crypto/doc.md b/lib/crypto/doc.md index ecb87b3..3f7ede8 100644 --- a/lib/crypto/doc.md +++ b/lib/crypto/doc.md @@ -2,7 +2,7 @@ -- import "github.com/go-i2p/go-i2p/lib/crypto" -package for i2p specific crpytography +package for i2p specific cryptography ## Usage From 4496c113940beb56eeb45341294962b12e1355c2 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 17 Oct 2024 22:03:46 -0400 Subject: [PATCH 28/94] added lib/util/logger/log.go --- lib/util/logger/log.go | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 lib/util/logger/log.go diff --git a/lib/util/logger/log.go b/lib/util/logger/log.go new file mode 100644 index 0000000..8bb33b2 --- /dev/null +++ b/lib/util/logger/log.go @@ -0,0 +1,50 @@ +package logger + +import ( + "github.com/sirupsen/logrus" + "io/ioutil" + "os" + "strings" + "sync" +) + +var ( + log *logrus.Logger + once sync.Once +) + +func InitializeLogger() { + once.Do(func() { + log = logrus.New() + // We do not want to log by default + log.SetOutput(ioutil.Discard) + log.SetLevel(logrus.PanicLevel) + // Check if DEBUG_I2P is set + if logLevel := os.Getenv("DEBUG_I2P"); logLevel != "" { + log.SetOutput(os.Stdout) + switch strings.ToLower(logLevel) { + case "debug": + log.SetLevel(logrus.DebugLevel) + case "warn": + log.SetLevel(logrus.WarnLevel) + case "error": + log.SetLevel(logrus.ErrorLevel) + default: + log.SetLevel(logrus.DebugLevel) + } + log.WithField("level", log.GetLevel()).Debug("Logging enabled.") + } + }) +} + +// GetLogger returns the initialized logger +func GetLogger() *logrus.Logger { + if log == nil { + InitializeLogger() + } + return log +} + +func init() { + InitializeLogger() +} From 2f2cd2249c81d7d0959ba73bc169736b59fe3f35 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 11:48:56 -0400 Subject: [PATCH 29/94] expanded logging to certificate.go --- lib/common/certificate/certificate.go | 43 +++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/common/certificate/certificate.go b/lib/common/certificate/certificate.go index 8ec94ce..bc8db58 100644 --- a/lib/common/certificate/certificate.go +++ b/lib/common/certificate/certificate.go @@ -4,12 +4,16 @@ package certificate import ( "fmt" + "github.com/sirupsen/logrus" - log "github.com/sirupsen/logrus" + //log "github.com/sirupsen/logrus" + "github.com/go-i2p/go-i2p/lib/util/logger" . "github.com/go-i2p/go-i2p/lib/common/data" ) +var log = logger.GetLogger() + // Certificate Types const ( CERT_NULL = iota @@ -70,14 +74,22 @@ func (c *Certificate) RawBytes() []byte { bytes := c.kind.Bytes() bytes = append(bytes, c.len.Bytes()...) bytes = append(bytes, c.payload...) + log.WithFields(logrus.Fields{ + "raw_bytes_length": len(bytes), + }).Debug("Generated raw bytes for certificate") return bytes } // ExcessBytes returns the excess bytes in a certificate found after the specified payload length. func (c *Certificate) ExcessBytes() []byte { if len(c.payload) >= c.len.Int() { - return c.payload[c.len.Int():] + excess := c.payload[c.len.Int():] + log.WithFields(logrus.Fields{ + "excess_bytes_length": len(excess), + }).Debug("Found excess bytes in certificate") + return excess } + log.Debug("No excess bytes found in certificate") return nil } @@ -86,6 +98,9 @@ func (c *Certificate) Bytes() []byte { bytes := c.kind.Bytes() bytes = append(bytes, c.len.Bytes()...) bytes = append(bytes, c.Data()...) + log.WithFields(logrus.Fields{ + "bytes_length": len(bytes), + }).Debug("Generated bytes for certificate") return bytes } @@ -97,12 +112,18 @@ func (c *Certificate) length() (cert_len int) { // Type returns the Certificate type specified in the first byte of the Certificate, func (c *Certificate) Type() (cert_type int) { cert_type = c.kind.Int() + log.WithFields(logrus.Fields{ + "cert_type": cert_type, + }).Debug("Retrieved certificate type") return } // Length returns the payload length of a Certificate. func (c *Certificate) Length() (length int) { length = c.len.Int() + log.WithFields(logrus.Fields{ + "length": length, + }).Debug("Retrieved certificate length") return } @@ -111,9 +132,13 @@ func (c *Certificate) Data() (data []byte) { lastElement := c.Length() if lastElement > len(c.payload) { data = c.payload + log.Warn("Certificate payload shorter than specified length") } else { data = c.payload[0:lastElement] } + log.WithFields(logrus.Fields{ + "data_length": len(data), + }).Debug("Retrieved certificate data") return } @@ -125,7 +150,7 @@ func NewCertificate(data []byte) (certificate Certificate, err error) { case 0: certificate.kind = Integer([]byte{0}) certificate.len = Integer([]byte{0}) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Certificate) NewCertificate", "certificate_bytes_length": len(data), "reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()), @@ -135,7 +160,7 @@ func NewCertificate(data []byte) (certificate Certificate, err error) { case 1, 2: certificate.kind = Integer(data[0 : len(data)-1]) certificate.len = Integer([]byte{0}) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Certificate) NewCertificate", "certificate_bytes_length": len(data), "reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()), @@ -149,7 +174,7 @@ func NewCertificate(data []byte) (certificate Certificate, err error) { certificate.payload = data[CERT_MIN_SIZE:] if certificate.len.Int() > len(data)-CERT_MIN_SIZE { err = fmt.Errorf("certificate parsing warning: certificate data is shorter than specified by length") - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Certificate) NewCertificate", "certificate_bytes_length": certificate.len.Int(), "certificate_payload_length": payleng, @@ -160,6 +185,10 @@ func NewCertificate(data []byte) (certificate Certificate, err error) { }).Error("invalid certificate, shorter than specified by length") return } + log.WithFields(logrus.Fields{ + "type": certificate.kind.Int(), + "length": certificate.len.Int(), + }).Debug("Successfully created new certificate") return } } @@ -169,8 +198,12 @@ func NewCertificate(data []byte) (certificate Certificate, err error) { func ReadCertificate(data []byte) (certificate Certificate, remainder []byte, err error) { certificate, err = NewCertificate(data) if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" { + log.Warn("Certificate data longer than specified length") err = nil } remainder = certificate.ExcessBytes() + log.WithFields(logrus.Fields{ + "remainder_length": len(remainder), + }).Debug("Read certificate and extracted remainder") return } From 53e902f491c1a17e36046b7a02d6f2d40d58cf4a Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 11:49:10 -0400 Subject: [PATCH 30/94] expanded logging to date.go --- lib/common/data/date.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/common/data/date.go b/lib/common/data/date.go index 85979d4..e6fc683 100644 --- a/lib/common/data/date.go +++ b/lib/common/data/date.go @@ -3,11 +3,13 @@ package data import ( "errors" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" "time" - - log "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + // DATE_SIZE is the length in bytes of an I2P Date. const DATE_SIZE = 8 @@ -51,7 +53,7 @@ func (date Date) Time() (date_time time.Time) { // Any data after DATE_SIZE is returned as a remainder. func ReadDate(data []byte) (date Date, remainder []byte, err error) { if len(data) < 8 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "data": data, }).Error("ReadDate: data is too short") err = errors.New("ReadDate: data is too short") @@ -59,6 +61,10 @@ func ReadDate(data []byte) (date Date, remainder []byte, err error) { } copy(date[:], data[:8]) remainder = data[8:] + log.WithFields(logrus.Fields{ + "date_value": date.Int(), + "remainder_length": len(remainder), + }).Debug("Successfully read Date from data") return } @@ -66,6 +72,15 @@ func ReadDate(data []byte) (date Date, remainder []byte, err error) { // Returns a pointer to Date unlike ReadDate. func NewDate(data []byte) (date *Date, remainder []byte, err error) { objdate, remainder, err := ReadDate(data) + if err != nil { + log.WithError(err).Error("Failed to create new Date") + return nil, remainder, err + } + date = &objdate + log.WithFields(logrus.Fields{ + "date_value": date.Int(), + "remainder_length": len(remainder), + }).Debug("Successfully created new Date") return } From 73db39ae5081d56b3858e0e4968d31b88a13c798 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 11:52:39 -0400 Subject: [PATCH 31/94] expanded logging in mapping.go --- lib/common/data/mapping.go | 68 +++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/lib/common/data/mapping.go b/lib/common/data/mapping.go index 8479f4f..372c981 100644 --- a/lib/common/data/mapping.go +++ b/lib/common/data/mapping.go @@ -2,8 +2,7 @@ package data import ( "errors" - - log "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus" ) /* @@ -48,8 +47,12 @@ type Mapping struct { // Values returns the values contained in a Mapping as MappingValues. func (mapping Mapping) Values() MappingValues { if mapping.vals == nil { + log.Debug("Mapping values are nil, returning empty MappingValues") return MappingValues{} } + log.WithFields(logrus.Fields{ + "values_count": len(*mapping.vals), + }).Debug("Retrieved Mapping values") return *mapping.vals } @@ -74,30 +77,40 @@ func (mapping *Mapping) Data() []byte { // HasDuplicateKeys returns true if two keys in a mapping are identical. func (mapping *Mapping) HasDuplicateKeys() bool { + log.Debug("Checking for duplicate keys in Mapping") seen_values := make(map[string]bool) values := mapping.Values() for _, pair := range values { key, _ := pair[0].Data() if _, present := seen_values[key]; present { + log.WithFields(logrus.Fields{ + "duplicate_key": key, + }).Warn("Found duplicate key in Mapping") return true } else { seen_values[key] = true } } + log.Debug("No duplicate keys found in Mapping") return false } // GoMapToMapping converts a Go map of unformatted strings to *Mapping. func GoMapToMapping(gomap map[string]string) (mapping *Mapping, err error) { + log.WithFields(logrus.Fields{ + "input_map_size": len(gomap), + }).Debug("Converting Go map to Mapping") map_vals := MappingValues{} for k, v := range gomap { key_str, kerr := ToI2PString(k) if kerr != nil { + log.WithError(kerr).Error("Failed to convert key to I2PString") err = kerr return } val_str, verr := ToI2PString(v) if verr != nil { + log.WithError(verr).Error("Failed to convert value to I2PString") err = verr return } @@ -107,27 +120,46 @@ func GoMapToMapping(gomap map[string]string) (mapping *Mapping, err error) { ) } mapping = ValuesToMapping(map_vals) + log.WithFields(logrus.Fields{ + "mapping_size": len(map_vals), + }).Debug("Successfully converted Go map to Mapping") return } // Check if the string parsing error indicates that the Mapping // should no longer be parsed. func stopValueRead(err error) bool { - return err.Error() == "error parsing string: zero length" + result := err.Error() == "error parsing string: zero length" + if result { + log.WithError(err).Debug("Stopping value read due to zero length error") + } + return result } // Determine if the first byte in a slice of bytes is the provided byte. func beginsWith(bytes []byte, chr byte) bool { - return len(bytes) != 0 && - bytes[0] == chr + /* + return len(bytes) != 0 && + bytes[0] == chr + */ + result := len(bytes) != 0 && bytes[0] == chr + log.WithFields(logrus.Fields{ + "bytes_length": len(bytes), + "expected_char": string(chr), + "result": result, + }).Debug("Checked if bytes begin with specific character") + return result } // ReadMapping returns Mapping from a []byte. // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) { + log.WithFields(logrus.Fields{ + "input_length": len(bytes), + }).Debug("Reading Mapping from bytes") if len(bytes) < 3 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "ReadMapping", "reason": "zero length", }).Warn("mapping format violation") @@ -137,16 +169,18 @@ func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) } size, remainder, e := NewInteger(bytes, 2) if e != nil { + log.WithError(e).Error("Failed to read Mapping size") err = append(err, e) } if size.Int() == 0 { + log.Warn("Mapping size is zero") return } mapping.size = size map_bytes := remainder[:mapping.size.Int()] remainder = remainder[mapping.size.Int():] if len(remainder) == 0 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "ReadMapping", "reason": "zero length", }).Warn("mapping format violation") @@ -161,20 +195,38 @@ func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) err = append(err, mappingValueErrs...) mapping.vals = vals if len(mappingValueErrs) > 0 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "ReadMapping", "reason": "error parsing mapping values", }).Warn("mapping format violation") e := errors.New("error parsing mapping values") err = append(err, e) } + + log.WithFields(logrus.Fields{ + "mapping_size": mapping.size.Int(), + "values_count": len(*mapping.vals), + "remainder_length": len(remainder), + "error_count": len(err), + }).Debug("Finished reading Mapping") + return } // NewMapping creates a new *Mapping from []byte using ReadMapping. // Returns a pointer to Mapping unlike ReadMapping. func NewMapping(bytes []byte) (values *Mapping, remainder []byte, err []error) { + log.WithFields(logrus.Fields{ + "input_length": len(bytes), + }).Debug("Creating new Mapping") + objvalues, remainder, err := ReadMapping(bytes) values = &objvalues + + log.WithFields(logrus.Fields{ + "values_count": len(values.Values()), + "remainder_length": len(remainder), + "error_count": len(err), + }).Debug("Finished creating new Mapping") return } From 1d1d8126c22ccba2105ca15c4c2d760be4f2d4eb Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 11:53:01 -0400 Subject: [PATCH 32/94] adjusted logging in main.go --- main.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/main.go b/main.go index 4d7ccde..f6dbfc6 100644 --- a/main.go +++ b/main.go @@ -2,21 +2,23 @@ package main import ( "flag" - "github.com/go-i2p/go-i2p/lib/config" "github.com/go-i2p/go-i2p/lib/router" + "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/go-i2p/go-i2p/lib/util/signals" - log "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + func main() { + netDbPath := flag.String("netDb", config.DefaultNetDbConfig.Path, "Path to the netDb") flag.Parse() config.RouterConfigProperties.NetDb.Path = *netDbPath go signals.Handle() - log.Info("parsing i2p router configuration") - log.Info("using netDb in:", config.RouterConfigProperties.NetDb.Path) - log.Info("starting up i2p router") + log.Debug("parsing i2p router configuration") + log.Debug("using netDb in:", config.RouterConfigProperties.NetDb.Path) + log.Debug("starting up i2p router") r, err := router.CreateRouter() if err == nil { signals.RegisterReloadHandler(func() { From dda4f90b6f3b5bb5a7c49a51cd48b3c27d1c3bb5 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 12:00:58 -0400 Subject: [PATCH 33/94] expanded logging in mapping_values.go --- lib/common/data/mapping_values.go | 46 +++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/lib/common/data/mapping_values.go b/lib/common/data/mapping_values.go index 0c4f6c4..c43fc0d 100644 --- a/lib/common/data/mapping_values.go +++ b/lib/common/data/mapping_values.go @@ -2,9 +2,8 @@ package data import ( "errors" + "github.com/sirupsen/logrus" "sort" - - log "github.com/sirupsen/logrus" ) // MappingValues represents the parsed key value pairs inside of an I2P Mapping. @@ -12,12 +11,22 @@ type MappingValues [][2]I2PString func (m MappingValues) Get(key I2PString) I2PString { keyBytes, _ := key.Data() + log.WithFields(logrus.Fields{ + "key": string(keyBytes), + }).Debug("Searching for key in MappingValues") for _, pair := range m { kb, _ := pair[0][0:].Data() if kb == keyBytes { + log.WithFields(logrus.Fields{ + "key": string(keyBytes), + "value": string(pair[1][1:]), + }).Debug("Found matching key in MappingValues") return pair[1][1:] } } + log.WithFields(logrus.Fields{ + "key": string(keyBytes), + }).Debug("Key not found in MappingValues") return nil } @@ -27,6 +36,9 @@ func ValuesToMapping(values MappingValues) *Mapping { // Default length to 2 * len // 1 byte for ; // 1 byte for = + log.WithFields(logrus.Fields{ + "values_count": len(values), + }).Debug("Converting MappingValues to Mapping") baseLength := 2 * len(values) for _, mappingVals := range values { for _, keyOrVal := range mappingVals { @@ -34,6 +46,10 @@ func ValuesToMapping(values MappingValues) *Mapping { } } + log.WithFields(logrus.Fields{ + "mapping_size": baseLength, + }).Debug("Created Mapping from MappingValues") + mappingSize, _ := NewIntegerFromInt(baseLength, 2) return &Mapping{ size: mappingSize, @@ -61,8 +77,13 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal // mapping := remainder // var remainder = mapping // var err error + log.WithFields(logrus.Fields{ + "input_length": len(remainder), + "map_length": map_length.Int(), + }).Debug("Reading MappingValues") + if remainder == nil || len(remainder) < 1 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Mapping) Values", "reason": "data shorter than expected", }).Error("mapping contained no data") @@ -73,7 +94,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal int_map_length := map_length.Int() mapping_len := len(remainder) if mapping_len > int_map_length { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Mapping) Values", "mapping_bytes_length": mapping_len, "mapping_length_field": int_map_length, @@ -81,7 +102,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal }).Warn("mapping format warning") errs = append(errs, errors.New("warning parsing mapping: data exists beyond length of mapping")) } else if int_map_length > mapping_len { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Mapping) Values", "mapping_bytes_length": mapping_len, "mapping_length_field": int_map_length, @@ -105,7 +126,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal // One byte for ; if len(remainder) < 6 { // Not returning an error here as the issue is already flagged by mapping length being wrong. - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Mapping) Values", "reason": "mapping format violation", }).Warn("mapping format violation, too few bytes for a kv pair") @@ -128,7 +149,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal keyAsString := string(keyBytes) _, ok := encounteredKeysMap[keyAsString] if ok { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Mapping) Values", "reason": "duplicate key in mapping", "key": string(key_str), @@ -142,7 +163,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal } if !beginsWith(remainder, 0x3d) { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Mapping) Values", "reason": "expected =", "value:": string(remainder), @@ -168,7 +189,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal // log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder) // log.Printf("(MAPPING VALUES DEBUG) String: value: %s", val_str) if !beginsWith(remainder, 0x3b) { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Mapping) Values", "reason": "expected ;", "value:": string(remainder), @@ -189,5 +210,12 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal encounteredKeysMap[keyAsString] = true } values = &map_values + + log.WithFields(logrus.Fields{ + "values_count": len(map_values), + "remainder_length": len(remainder_bytes), + "error_count": len(errs), + }).Debug("Finished reading MappingValues") + return } From a72b61a886b61921c198946a922ca6ec8854733e Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 12:08:27 -0400 Subject: [PATCH 34/94] expanded logging in string.go --- lib/common/data/string.go | 40 +++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/common/data/string.go b/lib/common/data/string.go index 96399d2..c847194 100644 --- a/lib/common/data/string.go +++ b/lib/common/data/string.go @@ -3,8 +3,7 @@ package data import ( "errors" "fmt" - - log "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus" ) // STRING_MAX_SIZE is the maximum number of bytes that can be stored in an I2P string @@ -32,7 +31,7 @@ type I2PString []byte // Returns error if the specified does not match the actual length or the string is otherwise invalid. func (str I2PString) Length() (length int, err error) { if len(str) == 0 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(I2PString) Length", "reason": "no data", }).Error("error parsing string") @@ -41,6 +40,7 @@ func (str I2PString) Length() (length int, err error) { } l, _, err := NewInteger(str[:], 1) if err != nil { + log.WithError(err).Error("Failed to create Integer from I2PString") return l.Int(), err } length = l.Int() @@ -53,6 +53,12 @@ func (str I2PString) Length() (length int, err error) { "data": string(str), "reason": "data less than specified by length", }).Error("string format warning")*/ + log.WithFields(logrus.Fields{ + "at": "(I2PString) Length", + "string_bytes_length": str_len, + "string_length_field": length, + "reason": "data less than specified by length", + }).Warn("string format warning") err = errors.New("string parsing warning: string data is shorter than specified by length") } return @@ -65,31 +71,42 @@ func (str I2PString) Data() (data string, err error) { if err != nil { switch err.Error() { case "error parsing string: zero length": + log.WithError(err).Warn("Zero length I2PString") return case "string parsing warning: string data is shorter than specified by length": + log.WithError(err).Warn("I2PString data shorter than specified length") if is, e := ToI2PString(string(str[:])); e != nil { + log.WithError(e).Error("Failed to convert short I2PString") return "", e } else { return is.Data() } case "string parsing warning: string contains data beyond length": + log.WithError(err).Warn("I2PString contains data beyond specified length") data = string(str[1:]) return } } if length == 0 { + log.Debug("I2PString is empty") return } data = string(str[1 : length+1]) + log.WithFields(logrus.Fields{ + "data_length": len(data), + }).Debug("Retrieved I2PString data") return } // ToI2PString converts a Go string to an I2PString. // Returns error if the string exceeds STRING_MAX_SIZE. func ToI2PString(data string) (str I2PString, err error) { + log.WithFields(logrus.Fields{ + "input_length": len(data), + }).Debug("Converting string to I2PString") data_len := len(data) if data_len > STRING_MAX_SIZE { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "ToI2PI2PString", "string_len": data_len, "max_len": STRING_MAX_SIZE, @@ -101,6 +118,9 @@ func ToI2PString(data string) (str I2PString, err error) { i2p_string := []byte{byte(data_len)} i2p_string = append(i2p_string, []byte(data)...) str = I2PString(i2p_string) + log.WithFields(logrus.Fields{ + "i2pstring_length": len(str), + }).Debug("Successfully converted string to I2PString") return } @@ -113,8 +133,12 @@ func ToI2PString(data string) (str I2PString, err error) { // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) { + log.WithFields(logrus.Fields{ + "input_length": len(data), + }).Debug("Reading I2PString from bytes") length, _, err := NewInteger(data, 1) if err != nil { + log.WithError(err).Error("Failed to read I2PString length") return } data_len := length.Int() + 1 @@ -123,8 +147,16 @@ func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) { l, err := str.Length() if l != data_len-1 { err = fmt.Errorf("error reading I2P string, length does not match data") + log.WithFields(logrus.Fields{ + "expected_length": data_len - 1, + "actual_length": l, + }).Error("I2PString length mismatch") return } + log.WithFields(logrus.Fields{ + "string_length": l, + "remainder_length": len(remainder), + }).Debug("Successfully read I2PString from bytes") return } From b6544ad194c836f9cff6d2f6a6c96c776aa62572 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 12:16:36 -0400 Subject: [PATCH 35/94] expanded logging in destination.go --- lib/common/destination/destination.go | 30 ++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/common/destination/destination.go b/lib/common/destination/destination.go index 2ea420e..4ff54c3 100644 --- a/lib/common/destination/destination.go +++ b/lib/common/destination/destination.go @@ -2,6 +2,8 @@ package destination import ( + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" "strings" . "github.com/go-i2p/go-i2p/lib/common/keys_and_cert" @@ -11,6 +13,8 @@ import ( "github.com/go-i2p/go-i2p/lib/crypto" ) +var log = logger.GetLogger() + /* [Destination] Accurate for version 0.9.49 @@ -31,26 +35,50 @@ type Destination struct { // Base32Address returns the I2P base32 address for this Destination. func (destination Destination) Base32Address() (str string) { + log.Debug("Generating Base32 address for Destination") + dest := destination.KeysAndCert.KeyCertificate.Bytes() hash := crypto.SHA256(dest) str = strings.Trim(base32.EncodeToString(hash[:]), "=") str = str + ".b32.i2p" + + log.WithFields(logrus.Fields{ + "base32_address": str, + }).Debug("Generated Base32 address for Destination") + return } // Base64 returns the I2P base64 address for this Destination. func (destination Destination) Base64() string { + log.Debug("Generating Base64 address for Destination") + dest := destination.KeysAndCert.KeyCertificate.Bytes() - return base64.EncodeToString(dest) + base64Address := base64.EncodeToString(dest) + + log.WithFields(logrus.Fields{ + "base64_address_length": len(base64Address), + }).Debug("Generated Base64 address for Destination") + + return base64Address } // ReadDestination returns Destination from a []byte. // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) { + log.WithFields(logrus.Fields{ + "input_length": len(data), + }).Debug("Reading Destination from bytes") + keys_and_cert, remainder, err := ReadKeysAndCert(data) destination = Destination{ keys_and_cert, } + + log.WithFields(logrus.Fields{ + "remainder_length": len(remainder), + }).Debug("Successfully read Destination from bytes") + return } From 93a71c7398dc4f1c5fe2279528bd6fd49f34a846 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 12:27:42 -0400 Subject: [PATCH 36/94] expanded logging in key_certificate.go --- lib/common/key_certificate/key_certificate.go | 90 ++++++++++++++++++- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/lib/common/key_certificate/key_certificate.go b/lib/common/key_certificate/key_certificate.go index a8b761e..34a9acd 100644 --- a/lib/common/key_certificate/key_certificate.go +++ b/lib/common/key_certificate/key_certificate.go @@ -29,13 +29,16 @@ payload :: data import ( "errors" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" . "github.com/go-i2p/go-i2p/lib/common/certificate" . "github.com/go-i2p/go-i2p/lib/common/data" "github.com/go-i2p/go-i2p/lib/crypto" - log "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + // Key Certificate Signing Key Types const ( KEYCERT_SIGN_DSA_SHA1 = iota @@ -99,29 +102,44 @@ type KeyCertificate struct { // Data returns the raw []byte contained in the Certificate. func (key_certificate KeyCertificate) Data() ([]byte, error) { + data := key_certificate.Certificate.RawBytes() + log.WithFields(logrus.Fields{ + "data_length": len(data), + }).Debug("Retrieved raw data from KeyCertificate") return key_certificate.Certificate.RawBytes(), nil } // SigningPublicKeyType returns the SigningPublicKey type as a Go integer. func (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int) { + signing_pubkey_type = key_certificate.spkType.Int() + log.WithFields(logrus.Fields{ + "signing_pubkey_type": signing_pubkey_type, + }).Debug("Retrieved SigningPublicKey type") return key_certificate.spkType.Int() } // PublicKeyType returns the PublicKey type as a Go integer. func (key_certificate KeyCertificate) PublicKeyType() (pubkey_type int) { + pubkey_type = key_certificate.cpkType.Int() + log.WithFields(logrus.Fields{ + "pubkey_type": pubkey_type, + }).Debug("Retrieved PublicKey type") return key_certificate.cpkType.Int() } // ConstructPublicKey returns a PublicKey constructed using any excess data that may be stored in the KeyCertififcate. // Returns enr errors encountered while parsing. func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.PublicKey, err error) { + log.WithFields(logrus.Fields{ + "input_length": len(data), + }).Debug("Constructing PublicKey from KeyCertificate") key_type := key_certificate.PublicKeyType() if err != nil { return } data_len := len(data) if data_len < key_certificate.CryptoSize() { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(KeyCertificate) ConstructPublicKey", "data_len": data_len, "required_len": KEYCERT_PUBKEY_SIZE, @@ -135,24 +153,34 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke var elg_key crypto.ElgPublicKey copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE]) public_key = elg_key + log.Debug("Constructed ElgPublicKey") case KEYCERT_CRYPTO_X25519: var ed25519_key crypto.Ed25519PublicKey copy(ed25519_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE]) public_key = ed25519_key + log.Debug("Constructed Ed25519PublicKey") + default: + log.WithFields(logrus.Fields{ + "key_type": key_type, + }).Warn("Unknown public key type") } + return } // ConstructSigningPublicKey returns a SingingPublicKey constructed using any excess data that may be stored in the KeyCertificate. // Returns any errors encountered while parsing. func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error) { + log.WithFields(logrus.Fields{ + "input_length": len(data), + }).Debug("Constructing SigningPublicKey from KeyCertificate") signing_key_type := key_certificate.PublicKeyType() if err != nil { return } data_len := len(data) if data_len < key_certificate.SignatureSize() { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(KeyCertificate) ConstructSigningPublicKey", "data_len": data_len, "required_len": KEYCERT_SPK_SIZE, @@ -166,31 +194,55 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si var dsa_key crypto.DSAPublicKey copy(dsa_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_DSA_SHA1_SIZE:KEYCERT_SPK_SIZE]) signing_public_key = dsa_key + log.Debug("Constructed DSAPublicKey") case KEYCERT_SIGN_P256: var ec_key crypto.ECP256PublicKey copy(ec_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P256_SIZE:KEYCERT_SPK_SIZE]) signing_public_key = ec_key + log.Debug("Constructed ECP256PublicKey") case KEYCERT_SIGN_P384: var ec_key crypto.ECP384PublicKey copy(ec_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P384_SIZE:KEYCERT_SPK_SIZE]) signing_public_key = ec_key + log.Debug("Constructed ECP384PublicKey") case KEYCERT_SIGN_P521: var ec_key crypto.ECP521PublicKey extra := KEYCERT_SIGN_P521_SIZE - KEYCERT_SPK_SIZE copy(ec_key[:], data) copy(ec_key[KEYCERT_SPK_SIZE:], key_certificate.Certificate.RawBytes()[4:4+extra]) signing_public_key = ec_key + log.Debug("Constructed ECP521PublicKey") case KEYCERT_SIGN_RSA2048: // var rsa_key crypto.RSA2048PublicKey // extra := KEYCERT_SIGN_RSA2048_SIZE - 128 // copy(rsa_key[:], data) // copy(rsa_key[128:], key_certificate[4:4+extra]) // signing_public_key = rsa_key + log.WithFields(logrus.Fields{ + "signing_key_type": signing_key_type, + }).Warn("Signing key type KEYCERT_SIGN_RSA2048 not implemented") case KEYCERT_SIGN_RSA3072: + log.WithFields(logrus.Fields{ + "signing_key_type": signing_key_type, + }).Warn("Signing key type KEYCERT_SIGN_RSA3072 not implemented") case KEYCERT_SIGN_RSA4096: + log.WithFields(logrus.Fields{ + "signing_key_type": signing_key_type, + }).Warn("Signing key type KEYCERT_SIGN_RSA4096 not implemented") case KEYCERT_SIGN_ED25519: + log.WithFields(logrus.Fields{ + "signing_key_type": signing_key_type, + }).Warn("Signing key type KEYCERT_SIGN_ED25519 not implemented") case KEYCERT_SIGN_ED25519PH: + log.WithFields(logrus.Fields{ + "signing_key_type": signing_key_type, + }).Warn("Signing key type KEYCERT_SIGN_ED25519PH not implemented") + default: + log.WithFields(logrus.Fields{ + "signing_key_type": signing_key_type, + }).Warn("Unknown signing key type") } + return } @@ -208,6 +260,11 @@ func (key_certificate KeyCertificate) SignatureSize() (size int) { KEYCERT_SIGN_ED25519PH: KEYCERT_SIGN_ED25519PH_SIZE, } key_type := key_certificate.SigningPublicKeyType() + size = sizes[int(key_type)] + log.WithFields(logrus.Fields{ + "key_type": key_type, + "signature_size": size, + }).Debug("Retrieved signature size") return sizes[int(key_type)] } @@ -221,6 +278,11 @@ func (key_certificate KeyCertificate) CryptoSize() (size int) { KEYCERT_CRYPTO_X25519: KEYCERT_CRYPTO_X25519_SIZE, } key_type := key_certificate.PublicKeyType() + size = sizes[int(key_type)] + log.WithFields(logrus.Fields{ + "key_type": key_type, + "crypto_size": size, + }).Debug("Retrieved crypto size") return sizes[int(key_type)] } @@ -228,14 +290,20 @@ func (key_certificate KeyCertificate) CryptoSize() (size int) { // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) { + log.WithFields(logrus.Fields{ + "input_length": len(bytes), + }).Debug("Creating new KeyCertificate") + var certificate Certificate certificate, remainder, err = ReadCertificate(bytes) if err != nil { + log.WithError(err).Error("Failed to read Certificate") return } if len(bytes) < KEYCERT_MIN_SIZE { err = errors.New("error parsing key certificate: not enough data") remainder = bytes[KEYCERT_MIN_SIZE:] + log.WithError(err).Error("KeyCertificate data too short") } key_certificate = &KeyCertificate{ Certificate: certificate, @@ -246,11 +314,25 @@ func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder if len(bytes) >= 7 { key_certificate.cpkType = Integer(bytes[6:7]) } + + log.WithFields(logrus.Fields{ + "spk_type": key_certificate.spkType.Int(), + "cpk_type": key_certificate.cpkType.Int(), + "remainder_length": len(remainder), + }).Debug("Successfully created new KeyCertificate") + return } // KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate. func KeyCertificateFromCertificate(certificate Certificate) *KeyCertificate { - k, _, _ := NewKeyCertificate(certificate.RawBytes()) + log.Debug("Creating KeyCertificate from Certificate") + //k, _, _ := NewKeyCertificate(certificate.RawBytes()) + k, _, err := NewKeyCertificate(certificate.RawBytes()) + if err != nil { + log.WithError(err).Error("Failed to create KeyCertificate from Certificate") + } else { + log.Debug("Successfully created KeyCertificate from Certificate") + } return k } From b894e8fb17d57e9c36e966cd4788144d3a66729c Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 12:41:48 -0400 Subject: [PATCH 37/94] expanded logging in keys_and_cert.go --- lib/common/keys_and_cert/keys_and_cert.go | 30 ++++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/common/keys_and_cert/keys_and_cert.go b/lib/common/keys_and_cert/keys_and_cert.go index 72ae89c..7c25496 100644 --- a/lib/common/keys_and_cert/keys_and_cert.go +++ b/lib/common/keys_and_cert/keys_and_cert.go @@ -3,13 +3,16 @@ package keys_and_cert import ( "errors" + "github.com/go-i2p/go-i2p/lib/util/logger" . "github.com/go-i2p/go-i2p/lib/common/certificate" . "github.com/go-i2p/go-i2p/lib/common/key_certificate" "github.com/go-i2p/go-i2p/lib/crypto" - log "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + // Sizes of various KeysAndCert structures and requirements const ( KEYS_AND_CERT_PUBKEY_SIZE = 256 @@ -80,7 +83,11 @@ type KeysAndCert struct { // Bytes returns the entire KeyCertificate in []byte form, trims payload to specified length. func (keys_and_cert KeysAndCert) Bytes() []byte { - return keys_and_cert.KeyCertificate.Bytes() + bytes := keys_and_cert.KeyCertificate.Bytes() + log.WithFields(logrus.Fields{ + "bytes_length": len(bytes), + }).Debug("Retrieved bytes from KeysAndCert") + return bytes } // PublicKey returns the public key as a crypto.PublicKey. @@ -101,10 +108,14 @@ func (keys_and_cert *KeysAndCert) Certificate() (cert Certificate) { // ReadKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert. // Returns a pointer to KeysAndCert unlike ReadKeysAndCert. func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error) { + log.WithFields(logrus.Fields{ + "input_length": len(data), + }).Debug("Reading KeysAndCert from data") + data_len := len(data) // keys_and_cert = KeysAndCert{} if data_len < KEYS_AND_CERT_MIN_SIZE && data_len > KEYS_AND_CERT_DATA_SIZE { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "ReadKeysAndCert", "data_len": data_len, "required_len": KEYS_AND_CERT_MIN_SIZE, @@ -114,7 +125,7 @@ func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, keys_and_cert.KeyCertificate, remainder, _ = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:]) return } else if data_len < KEYS_AND_CERT_DATA_SIZE { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "ReadKeysAndCert", "data_len": data_len, "required_len": KEYS_AND_CERT_MIN_SIZE, @@ -125,6 +136,7 @@ func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, } keys_and_cert.KeyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:]) if err != nil { + log.WithError(err).Error("Failed to create KeyCertificate") return } // TODO: this only supports one key type right now and it's the old key type, but the layout is the same. @@ -132,13 +144,23 @@ func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, // and KEYS_AND_CERT_SPK_SIZE constants in the future. keys_and_cert.publicKey, err = keys_and_cert.KeyCertificate.ConstructPublicKey(data[:keys_and_cert.KeyCertificate.CryptoSize()]) if err != nil { + log.WithError(err).Error("Failed to construct PublicKey") return } keys_and_cert.signingPublicKey, err = keys_and_cert.KeyCertificate.ConstructSigningPublicKey(data[KEYS_AND_CERT_DATA_SIZE-keys_and_cert.KeyCertificate.SignatureSize() : KEYS_AND_CERT_DATA_SIZE]) if err != nil { + log.WithError(err).Error("Failed to construct SigningPublicKey") return } padding := data[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_DATA_SIZE-KEYS_AND_CERT_SPK_SIZE] keys_and_cert.padding = padding + + log.WithFields(logrus.Fields{ + "public_key_type": keys_and_cert.KeyCertificate.PublicKeyType(), + "signing_public_key_type": keys_and_cert.KeyCertificate.SigningPublicKeyType(), + "padding_length": len(padding), + "remainder_length": len(remainder), + }).Debug("Successfully read KeysAndCert") + return } From a2fd65ee32ad8d93cf35e6c2e1a2ed88de7251cc Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 12:55:35 -0400 Subject: [PATCH 38/94] expanded logging in lease_set.go --- lib/common/lease_set/lease_set.go | 55 ++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/lib/common/lease_set/lease_set.go b/lib/common/lease_set/lease_set.go index e765084..ff841ef 100644 --- a/lib/common/lease_set/lease_set.go +++ b/lib/common/lease_set/lease_set.go @@ -3,6 +3,8 @@ package lease_set import ( "errors" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" . "github.com/go-i2p/go-i2p/lib/common/certificate" . "github.com/go-i2p/go-i2p/lib/common/data" @@ -12,9 +14,10 @@ import ( . "github.com/go-i2p/go-i2p/lib/common/lease" . "github.com/go-i2p/go-i2p/lib/common/signature" "github.com/go-i2p/go-i2p/lib/crypto" - log "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + // Sizes of various structures in an I2P LeaseSet const ( LEASE_SET_PUBKEY_SIZE = 256 @@ -134,9 +137,15 @@ type LeaseSet struct { func (lease_set LeaseSet) Destination() (destination Destination, err error) { keys_and_cert, _, err := ReadKeysAndCert(lease_set) if err != nil { + log.WithError(err).Error("Failed to read KeysAndCert from LeaseSet") return } destination, _, err = ReadDestination(keys_and_cert.Bytes()) + if err != nil { + log.WithError(err).Error("Failed to read Destination from KeysAndCert") + } else { + log.Debug("Successfully retrieved Destination from LeaseSet") + } return } @@ -146,7 +155,7 @@ func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error _, remainder, err := ReadKeysAndCert(lease_set) remainder_len := len(remainder) if remainder_len < LEASE_SET_PUBKEY_SIZE { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(LeaseSet) PublicKey", "data_len": remainder_len, "required_len": LEASE_SET_PUBKEY_SIZE, @@ -157,25 +166,29 @@ func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error return } copy(public_key[:], remainder[:LEASE_SET_PUBKEY_SIZE]) + log.Debug("Successfully retrieved PublicKey from LeaseSet") return } // SigningKey returns the signing public key as crypto.SigningPublicKey. // returns errors encountered during parsing. func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicKey, err error) { + log.Debug("Retrieving SigningKey from LeaseSet") destination, err := lease_set.Destination() if err != nil { + log.WithError(err).Error("Failed to retrieve Destination for SigningKey") return } offset := len(destination.Bytes()) + LEASE_SET_PUBKEY_SIZE cert := destination.Certificate() cert_len := cert.Length() if err != nil { + log.WithError(err).Error("Failed to get Certificate length") return } lease_set_len := len(lease_set) if lease_set_len < offset+LEASE_SET_SPK_SIZE { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(LeaseSet) SigningKey", "data_len": lease_set_len, "required_len": offset + LEASE_SET_SPK_SIZE, @@ -190,6 +203,7 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK var dsa_pk crypto.DSAPublicKey copy(dsa_pk[:], lease_set[offset:offset+LEASE_SET_SPK_SIZE]) signing_public_key = dsa_pk + log.Debug("Retrieved legacy DSA SHA1 SigningPublicKey") } else { // A Certificate is present in this LeaseSet's Destination cert_type := cert.Type() @@ -200,14 +214,19 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK signing_public_key, err = KeyCertificateFromCertificate(cert).ConstructSigningPublicKey( lease_set[offset : offset+LEASE_SET_SPK_SIZE], ) + if err != nil { + log.WithError(err).Error("Failed to construct SigningPublicKey from KeyCertificate") + } else { + log.Debug("Retrieved SigningPublicKey from KeyCertificate") + } } else { // No Certificate is present, return the LEASE_SET_SPK_SIZE byte // SigningPublicKey space as legacy DSA SHA1 SigningPublicKey. var dsa_pk crypto.DSAPublicKey copy(dsa_pk[:], lease_set[offset:offset+LEASE_SET_SPK_SIZE]) signing_public_key = dsa_pk + log.Debug("Retrieved legacy DSA SHA1 SigningPublicKey (Certificate present but not Key Certificate)") } - } return } @@ -215,13 +234,15 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK // LeaseCount returns the numbert of leases specified by the LeaseCount value as int. // returns errors encountered during parsing. func (lease_set LeaseSet) LeaseCount() (count int, err error) { + log.Debug("Retrieving LeaseCount from LeaseSet") _, remainder, err := ReadKeysAndCert(lease_set) if err != nil { + log.WithError(err).Error("Failed to read KeysAndCert for LeaseCount") return } remainder_len := len(remainder) if remainder_len < LEASE_SET_PUBKEY_SIZE+LEASE_SET_SPK_SIZE+1 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(LeaseSet) LeaseCount", "data_len": remainder_len, "required_len": LEASE_SET_PUBKEY_SIZE + LEASE_SET_SPK_SIZE + 1, @@ -233,12 +254,14 @@ func (lease_set LeaseSet) LeaseCount() (count int, err error) { c := Integer([]byte{remainder[LEASE_SET_PUBKEY_SIZE+LEASE_SET_SPK_SIZE]}) count = c.Int() if count > 16 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(LeaseSet) LeaseCount", "lease_count": count, "reason": "more than 16 leases", }).Warn("invalid lease set") err = errors.New("invalid lease set: more than 16 leases") + } else { + log.WithField("lease_count", count).Debug("Retrieved LeaseCount from LeaseSet") } return } @@ -246,13 +269,16 @@ func (lease_set LeaseSet) LeaseCount() (count int, err error) { // Leases returns the leases as []Lease. // returns errors encountered during parsing. func (lease_set LeaseSet) Leases() (leases []Lease, err error) { + log.Debug("Retrieving Leases from LeaseSet") destination, err := lease_set.Destination() if err != nil { + log.WithError(err).Error("Failed to retrieve Destination for Leases") return } offset := len(destination.Bytes()) + LEASE_SET_PUBKEY_SIZE + LEASE_SET_SPK_SIZE + 1 count, err := lease_set.LeaseCount() if err != nil { + log.WithError(err).Error("Failed to retrieve LeaseCount for Leases") return } for i := 0; i < count; i++ { @@ -260,7 +286,7 @@ func (lease_set LeaseSet) Leases() (leases []Lease, err error) { end := start + LEASE_SIZE lease_set_len := len(lease_set) if lease_set_len < end { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(LeaseSet) Leases", "data_len": lease_set_len, "required_len": end, @@ -273,18 +299,22 @@ func (lease_set LeaseSet) Leases() (leases []Lease, err error) { copy(lease[:], lease_set[start:end]) leases = append(leases, lease) } + log.WithField("lease_count", len(leases)).Debug("Retrieved Leases from LeaseSet") return } // Signature returns the signature as Signature. // returns errors encountered during parsing. func (lease_set LeaseSet) Signature() (signature Signature, err error) { + log.Debug("Retrieving Signature from LeaseSet") destination, err := lease_set.Destination() if err != nil { + log.WithError(err).Error("Failed to retrieve Destination for Signature") return } lease_count, err := lease_set.LeaseCount() if err != nil { + log.WithError(err).Error("Failed to retrieve LeaseCount for Signature") return } start := len(destination.Bytes()) + @@ -302,7 +332,7 @@ func (lease_set LeaseSet) Signature() (signature Signature, err error) { } lease_set_len := len(lease_set) if lease_set_len < end { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(LeaseSet) Signature", "data_len": lease_set_len, "required_len": end, @@ -312,11 +342,13 @@ func (lease_set LeaseSet) Signature() (signature Signature, err error) { return } signature = []byte(lease_set[start:end]) + log.WithField("signature_length", len(signature)).Debug("Retrieved Signature from LeaseSet") return } // Verify returns nil func (lease_set LeaseSet) Verify() error { + log.Debug("Verifying LeaseSet") //data_end := len(destination) + // LEASE_SET_PUBKEY_SIZE + // LEASE_SET_SPK_SIZE + @@ -330,14 +362,17 @@ func (lease_set LeaseSet) Verify() error { //if err != nil { // return err //} + log.Warn("LeaseSet verification not implemented") return nil // verifier.Verify(data, lease_set.Signature()) } // NewestExpiration returns the newest lease expiration as an I2P Date. // Returns errors encountered during parsing. func (lease_set LeaseSet) NewestExpiration() (newest Date, err error) { + log.Debug("Finding newest expiration in LeaseSet") leases, err := lease_set.Leases() if err != nil { + log.WithError(err).Error("Failed to retrieve Leases for NewestExpiration") return } newest = Date{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} @@ -347,14 +382,17 @@ func (lease_set LeaseSet) NewestExpiration() (newest Date, err error) { newest = date } } + log.WithField("newest_expiration", newest.Time()).Debug("Found newest expiration in LeaseSet") return } // OldestExpiration returns the oldest lease expiration as an I2P Date. // Returns errors encountered during parsing. func (lease_set LeaseSet) OldestExpiration() (earliest Date, err error) { + log.Debug("Finding oldest expiration in LeaseSet") leases, err := lease_set.Leases() if err != nil { + log.WithError(err).Error("Failed to retrieve Leases for OldestExpiration") return } earliest = Date{0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} @@ -364,5 +402,6 @@ func (lease_set LeaseSet) OldestExpiration() (earliest Date, err error) { earliest = date } } + log.WithField("oldest_expiration", earliest.Time()).Debug("Found oldest expiration in LeaseSet") return } From 3bca467f288318ddaa1fe28aa838ed57fef6642f Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 12:59:49 -0400 Subject: [PATCH 39/94] updated README.md to reflect new logging paradigm. --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 9595fb1..67c6f43 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,26 @@ please keep up with these changes, as they will not be backward compatible and r - [X] Data Types - [X] Session Tag +## Verbosity ## +Logging can be enabled and configured using the DEBUG_I2P environment variable. By default, logging is disabled. + +There are three available log levels: + +- Debug +```shell +export DEBUG_I2P=debug +``` +- Warn +```shell +export DEBUG_I2P=warn +``` +- Error +```shell +export DEBUG_I2P=error +``` + +If in case I2P_DEBUG is set to an unrecognized variable, it will fall back to "debug". + ## Contributing See CONTRIBUTING.md for more information. From 2191c40ac61e55feeb77c30bbb77b07b23933fa8 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 13:22:36 -0400 Subject: [PATCH 40/94] expanded logging to router_address.go + gofumpt adjustment --- lib/common/certificate/certificate.go | 3 +- lib/common/data/date.go | 3 +- lib/common/data/mapping.go | 1 + lib/common/data/mapping_values.go | 3 +- lib/common/data/string.go | 1 + lib/common/destination/destination.go | 3 +- lib/common/key_certificate/key_certificate.go | 3 +- lib/common/keys_and_cert/keys_and_cert.go | 1 + lib/common/lease_set/lease_set.go | 1 + lib/common/router_address/router_address.go | 61 +++++++++++++++---- lib/transport/noise/encrdecr_packet_test.go | 3 +- lib/transport/noise/incoming_handshake.go | 2 +- lib/transport/noise/noise_constants.go | 2 +- lib/transport/noise/outgoing_handshake.go | 4 +- lib/transport/noise/read_session.go | 2 +- lib/transport/noise/session.go | 8 ++- lib/transport/noise/transport_test.go | 2 +- lib/transport/noise/write_session.go | 4 +- lib/util/logger/log.go | 3 +- main.go | 2 +- 20 files changed, 81 insertions(+), 31 deletions(-) diff --git a/lib/common/certificate/certificate.go b/lib/common/certificate/certificate.go index bc8db58..1834faf 100644 --- a/lib/common/certificate/certificate.go +++ b/lib/common/certificate/certificate.go @@ -4,9 +4,10 @@ package certificate import ( "fmt" + "github.com/sirupsen/logrus" - //log "github.com/sirupsen/logrus" + // log "github.com/sirupsen/logrus" "github.com/go-i2p/go-i2p/lib/util/logger" . "github.com/go-i2p/go-i2p/lib/common/data" diff --git a/lib/common/data/date.go b/lib/common/data/date.go index e6fc683..f543e1c 100644 --- a/lib/common/data/date.go +++ b/lib/common/data/date.go @@ -3,9 +3,10 @@ package data import ( "errors" + "time" + "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/sirupsen/logrus" - "time" ) var log = logger.GetLogger() diff --git a/lib/common/data/mapping.go b/lib/common/data/mapping.go index 372c981..ce94943 100644 --- a/lib/common/data/mapping.go +++ b/lib/common/data/mapping.go @@ -2,6 +2,7 @@ package data import ( "errors" + "github.com/sirupsen/logrus" ) diff --git a/lib/common/data/mapping_values.go b/lib/common/data/mapping_values.go index c43fc0d..739164e 100644 --- a/lib/common/data/mapping_values.go +++ b/lib/common/data/mapping_values.go @@ -2,8 +2,9 @@ package data import ( "errors" - "github.com/sirupsen/logrus" "sort" + + "github.com/sirupsen/logrus" ) // MappingValues represents the parsed key value pairs inside of an I2P Mapping. diff --git a/lib/common/data/string.go b/lib/common/data/string.go index c847194..45b8b7e 100644 --- a/lib/common/data/string.go +++ b/lib/common/data/string.go @@ -3,6 +3,7 @@ package data import ( "errors" "fmt" + "github.com/sirupsen/logrus" ) diff --git a/lib/common/destination/destination.go b/lib/common/destination/destination.go index 4ff54c3..2a1a316 100644 --- a/lib/common/destination/destination.go +++ b/lib/common/destination/destination.go @@ -2,9 +2,10 @@ package destination import ( + "strings" + "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/sirupsen/logrus" - "strings" . "github.com/go-i2p/go-i2p/lib/common/keys_and_cert" diff --git a/lib/common/key_certificate/key_certificate.go b/lib/common/key_certificate/key_certificate.go index 34a9acd..2748fa7 100644 --- a/lib/common/key_certificate/key_certificate.go +++ b/lib/common/key_certificate/key_certificate.go @@ -29,6 +29,7 @@ payload :: data import ( "errors" + "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/sirupsen/logrus" @@ -327,7 +328,7 @@ func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder // KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate. func KeyCertificateFromCertificate(certificate Certificate) *KeyCertificate { log.Debug("Creating KeyCertificate from Certificate") - //k, _, _ := NewKeyCertificate(certificate.RawBytes()) + // k, _, _ := NewKeyCertificate(certificate.RawBytes()) k, _, err := NewKeyCertificate(certificate.RawBytes()) if err != nil { log.WithError(err).Error("Failed to create KeyCertificate from Certificate") diff --git a/lib/common/keys_and_cert/keys_and_cert.go b/lib/common/keys_and_cert/keys_and_cert.go index 7c25496..bc46c5e 100644 --- a/lib/common/keys_and_cert/keys_and_cert.go +++ b/lib/common/keys_and_cert/keys_and_cert.go @@ -3,6 +3,7 @@ package keys_and_cert import ( "errors" + "github.com/go-i2p/go-i2p/lib/util/logger" . "github.com/go-i2p/go-i2p/lib/common/certificate" diff --git a/lib/common/lease_set/lease_set.go b/lib/common/lease_set/lease_set.go index ff841ef..a6d1b69 100644 --- a/lib/common/lease_set/lease_set.go +++ b/lib/common/lease_set/lease_set.go @@ -3,6 +3,7 @@ package lease_set import ( "errors" + "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/sirupsen/logrus" diff --git a/lib/common/router_address/router_address.go b/lib/common/router_address/router_address.go index cc44ec1..81479d8 100644 --- a/lib/common/router_address/router_address.go +++ b/lib/common/router_address/router_address.go @@ -8,8 +8,10 @@ import ( "strconv" "strings" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" + . "github.com/go-i2p/go-i2p/lib/common/data" - log "github.com/sirupsen/logrus" ) // Minimum number of bytes in a valid RouterAddress @@ -17,6 +19,8 @@ const ( ROUTER_ADDRESS_MIN_SIZE = 9 ) +var log = logger.GetLogger() + /* [RouterAddress] Accurate for version 0.9.49 @@ -75,34 +79,48 @@ type RouterAddress struct { // Network implements net.Addr. It returns the transport type plus 4 or 6 func (router_address *RouterAddress) Network() string { + log.Debug("Getting network for RouterAddress") if router_address.TransportType == nil { + log.Warn("TransportType is nil in RouterAddress") return "" } str, err := router_address.TransportType.Data() if err != nil { + log.WithError(err).Error("Failed to get TransportType data") return "" } - return string(str) + router_address.IPVersion() + network := string(str) + router_address.IPVersion() + log.WithField("network", network).Debug("Retrieved network for RouterAddress") + return network } // IPVersion returns a string "4" for IPv4 or 6 for IPv6 func (router_address *RouterAddress) IPVersion() string { + log.Debug("Getting IP version for RouterAddress") str, err := router_address.CapsString().Data() if err != nil { + log.WithError(err).Error("Failed to get CapsString data") return "" } if strings.HasSuffix(str, "6") { + log.Debug("IP version is IPv6") return "6" } + log.Debug("IP version is IPv4") return "4" } func (router_address *RouterAddress) UDP() bool { - return strings.HasPrefix(strings.ToLower(router_address.Network()), "ssu") + // return strings.HasPrefix(strings.ToLower(router_address.Network()), "ssu") + log.Debug("Checking if RouterAddress is UDP") + isUDP := strings.HasPrefix(strings.ToLower(router_address.Network()), "ssu") + log.WithField("is_udp", isUDP).Debug("Checked if RouterAddress is UDP") + return isUDP } // String implements net.Addr. It returns the IP address, followed by the options func (router_address *RouterAddress) String() string { + log.Debug("Converting RouterAddress to string") var rv []string rv = append(rv, string(router_address.TransportStyle())) rv = append(rv, string(router_address.HostString())) @@ -121,25 +139,29 @@ func (router_address *RouterAddress) String() string { rv = append(rv, string(router_address.IntroducerExpirationString(2))) rv = append(rv, string(router_address.IntroducerTagString(2))) } - return strings.TrimSpace(strings.Join(rv, " ")) + str := strings.TrimSpace(strings.Join(rv, " ")) + log.WithField("router_address_string", str).Debug("Converted RouterAddress to string") + return str } var ex_addr net.Addr = &RouterAddress{} // Bytes returns the router address as a []byte. func (router_address RouterAddress) Bytes() []byte { + log.Debug("Converting RouterAddress to bytes") bytes := make([]byte, 0) bytes = append(bytes, router_address.TransportCost.Bytes()...) bytes = append(bytes, router_address.ExpirationDate.Bytes()...) strData, err := router_address.TransportType.Data() if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "error": err, }).Error("RouterAddress.Bytes: error getting transport_style bytes") } else { bytes = append(bytes, strData...) } bytes = append(bytes, router_address.TransportOptions.Data()...) + log.WithField("bytes_length", len(bytes)).Debug("Converted RouterAddress to bytes") return bytes } @@ -224,29 +246,45 @@ func (router_address RouterAddress) IntroducerTagString(num int) I2PString { } func (router_address RouterAddress) Host() (net.Addr, error) { + log.Debug("Getting host from RouterAddress") host := router_address.HostString() hostBytes, err := host.Data() if err != nil { + log.WithError(err).Error("Failed to get host data") return nil, err } ip := net.ParseIP(hostBytes) if ip == nil { + log.Error("Failed to parse IP address") return nil, fmt.Errorf("null host error") } - return net.ResolveIPAddr("", ip.String()) + // return net.ResolveIPAddr("", ip.String()) + addr, err := net.ResolveIPAddr("", ip.String()) + if err != nil { + log.WithError(err).Error("Failed to resolve IP address") + } else { + log.WithField("addr", addr).Debug("Retrieved host from RouterAddress") + } + return addr, err } func (router_address RouterAddress) Port() (string, error) { + log.Debug("Getting port from RouterAddress") port := router_address.PortString() portBytes, err := port.Data() if err != nil { + log.WithError(err).Error("Failed to get port data") return "", err } val, err := strconv.Atoi(portBytes) if err != nil { + log.WithError(err).Error("Failed to convert port to integer") return "", err } - return strconv.Itoa(val), nil + // return strconv.Itoa(val), nil + portStr := strconv.Itoa(val) + log.WithField("port", portStr).Debug("Retrieved port from RouterAddress") + return portStr, nil } func (router_address RouterAddress) StaticKey() ([32]byte, error) { @@ -283,6 +321,7 @@ func (router_address RouterAddress) checkValid() (err error, exit bool) { // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) { + log.WithField("data_length", len(data)).Debug("Reading RouterAddress from data") if len(data) == 0 { log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("error parsing RouterAddress: no data") err = errors.New("error parsing RouterAddress: no data") @@ -290,21 +329,21 @@ func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []b } router_address.TransportCost, remainder, err = NewInteger(data, 1) if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(RouterAddress) ReadNewRouterAddress", "reason": "error parsing cost", }).Warn("error parsing RouterAddress") } router_address.ExpirationDate, remainder, err = NewDate(remainder) if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(RouterAddress) ReadNewRouterAddress", "reason": "error parsing expiration", }).Error("error parsing RouterAddress") } router_address.TransportType, remainder, err = ReadI2PString(remainder) if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(RouterAddress) ReadNewRouterAddress", "reason": "error parsing transport_style", }).Error("error parsing RouterAddress") @@ -312,7 +351,7 @@ func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []b var errs []error router_address.TransportOptions, remainder, errs = NewMapping(remainder) for _, err := range errs { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(RouterAddress) ReadNewRouterAddress", "reason": "error parsing options", "error": err, diff --git a/lib/transport/noise/encrdecr_packet_test.go b/lib/transport/noise/encrdecr_packet_test.go index 678a4a6..ef4dc81 100644 --- a/lib/transport/noise/encrdecr_packet_test.go +++ b/lib/transport/noise/encrdecr_packet_test.go @@ -3,9 +3,10 @@ package noise import ( "crypto/rand" "encoding/binary" + "testing" + "github.com/flynn/noise" "github.com/stretchr/testify/assert" - "testing" ) func TestEncryptDecryptPacketOffline(t *testing.T) { diff --git a/lib/transport/noise/incoming_handshake.go b/lib/transport/noise/incoming_handshake.go index 75abe6a..f9f6116 100644 --- a/lib/transport/noise/incoming_handshake.go +++ b/lib/transport/noise/incoming_handshake.go @@ -28,7 +28,7 @@ func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, e prologue := make([]byte, 2, uint16Size+len(negData)) binary.BigEndian.PutUint16(prologue, uint16(len(negData))) prologue = append(prologue, negData...) - //prologue = append(initString, prologue...) + // prologue = append(initString, prologue...) state, err = noise.NewHandshakeState(noise.Config{ StaticKeypair: s, Initiator: false, diff --git a/lib/transport/noise/noise_constants.go b/lib/transport/noise/noise_constants.go index 7fdab54..1e8a5d8 100644 --- a/lib/transport/noise/noise_constants.go +++ b/lib/transport/noise/noise_constants.go @@ -38,7 +38,7 @@ func initNegotiationData(negotiationData []byte) []byte { return negotiationData } negotiationData = make([]byte, 6) - binary.BigEndian.PutUint16(negotiationData, 1) //version + binary.BigEndian.PutUint16(negotiationData, 1) // version negotiationData[2] = NOISE_DH_CURVE25519 negotiationData[3] = NOISE_CIPHER_CHACHAPOLY negotiationData[4] = NOISE_HASH_SHA256 diff --git a/lib/transport/noise/outgoing_handshake.go b/lib/transport/noise/outgoing_handshake.go index 5786924..0303a78 100644 --- a/lib/transport/noise/outgoing_handshake.go +++ b/lib/transport/noise/outgoing_handshake.go @@ -13,9 +13,7 @@ import ( func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) { if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() { - return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported") - } negData = make([]byte, 6) copy(negData, initNegotiationData(nil)) @@ -30,7 +28,7 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, prologue := make([]byte, 2, uint16Size+len(negData)) binary.BigEndian.PutUint16(prologue, uint16(len(negData))) prologue = append(prologue, negData...) - //prologue = append(initString, prologue...) + // prologue = append(initString, prologue...) state, err = noise.NewHandshakeState(noise.Config{ StaticKeypair: s, Initiator: true, diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go index da32f8b..35c0fda 100644 --- a/lib/transport/noise/read_session.go +++ b/lib/transport/noise/read_session.go @@ -71,7 +71,7 @@ func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { func (c *NoiseSession) readPacketLocked(data []byte) (int, error) { var n int - if len(data) == 0 { //special case to answer when everything is ok during handshake + if len(data) == 0 { // special case to answer when everything is ok during handshake if _, err := c.Conn.Read(make([]byte, 2)); err != nil { return 0, err } diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index 8938039..90a8ee6 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -52,8 +52,10 @@ func (noise_session *NoiseSession) SetWriteDeadline(t time.Time) error { return noise_session.Conn.SetWriteDeadline(t) } -var exampleNoiseSession transport.TransportSession = &NoiseSession{} -var ExampleNoiseSession net.Conn = exampleNoiseSession.(*NoiseSession) +var ( + exampleNoiseSession transport.TransportSession = &NoiseSession{} + ExampleNoiseSession net.Conn = exampleNoiseSession.(*NoiseSession) +) func (s *NoiseSession) LocalAddr() net.Addr { return s.Conn.LocalAddr() @@ -81,7 +83,7 @@ func newBlock() []byte { type VerifyCallbackFunc func(publicKey []byte, data []byte) error func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSession, error) { - //socket, err := DialNoise("noise", ri) + // socket, err := DialNoise("noise", ri) for _, addr := range ri.RouterAddresses() { socket, err := net.Dial("tcp", string(addr.Bytes())) if err != nil { diff --git a/lib/transport/noise/transport_test.go b/lib/transport/noise/transport_test.go index a6cc0c2..52f06e3 100644 --- a/lib/transport/noise/transport_test.go +++ b/lib/transport/noise/transport_test.go @@ -29,5 +29,5 @@ func TestTransport(t *testing.T) { } ntt := NewNoiseTransport(lnn) t.Log(ntt.Name()) - //ntt.GetSession() + // ntt.GetSession() } diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index 7768880..35b4d29 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -50,7 +50,7 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { if err != nil { return 0, nil, fmt.Errorf("failed to encrypt: '%w'", err) } - //m := len(encryptedData) + // m := len(encryptedData) lengthPrefix := make([]byte, 2) binary.BigEndian.PutUint16(lengthPrefix, uint16(len(encryptedData))) @@ -81,7 +81,7 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { var n int - if len(data) == 0 { //special case to answer when everything is ok during handshake + if len(data) == 0 { // special case to answer when everything is ok during handshake if _, err := c.Conn.Write(make([]byte, 2)); err != nil { return 0, err } diff --git a/lib/util/logger/log.go b/lib/util/logger/log.go index 8bb33b2..442cbf3 100644 --- a/lib/util/logger/log.go +++ b/lib/util/logger/log.go @@ -1,11 +1,12 @@ package logger import ( - "github.com/sirupsen/logrus" "io/ioutil" "os" "strings" "sync" + + "github.com/sirupsen/logrus" ) var ( diff --git a/main.go b/main.go index f6dbfc6..4d28046 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "flag" + "github.com/go-i2p/go-i2p/lib/config" "github.com/go-i2p/go-i2p/lib/router" "github.com/go-i2p/go-i2p/lib/util/logger" @@ -11,7 +12,6 @@ import ( var log = logger.GetLogger() func main() { - netDbPath := flag.String("netDb", config.DefaultNetDbConfig.Path, "Path to the netDb") flag.Parse() config.RouterConfigProperties.NetDb.Path = *netDbPath From f022522ad521fd868266ed7a61c66f564d062c9d Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 14:27:41 -0400 Subject: [PATCH 41/94] expanded logging to router_identity.go --- lib/common/router_identity/router_identity.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/common/router_identity/router_identity.go b/lib/common/router_identity/router_identity.go index 86d86c9..032e560 100644 --- a/lib/common/router_identity/router_identity.go +++ b/lib/common/router_identity/router_identity.go @@ -3,8 +3,12 @@ package router_identity import ( . "github.com/go-i2p/go-i2p/lib/common/keys_and_cert" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + /* [RouterIdentity] Accurate for version 0.9.49 @@ -27,9 +31,19 @@ type RouterIdentity struct { // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadRouterIdentity(data []byte) (router_identity RouterIdentity, remainder []byte, err error) { + log.WithFields(logrus.Fields{ + "input_length": len(data), + }).Debug("Reading RouterIdentity from data") keys_and_cert, remainder, err := ReadKeysAndCert(data) + if err != nil { + log.WithError(err).Error("Failed to read KeysAndCert for RouterIdentity") + return + } router_identity = RouterIdentity{ keys_and_cert, } + log.WithFields(logrus.Fields{ + "remainder_length": len(remainder), + }).Debug("Successfully read RouterIdentity") return } From beb533a09bb45883fa6a46db16aac200ad7bd5b8 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 14:40:52 -0400 Subject: [PATCH 42/94] expanded logging to router_info.go --- lib/common/router_info/router_info.go | 76 ++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/lib/common/router_info/router_info.go b/lib/common/router_info/router_info.go index 9235f6c..3283f06 100644 --- a/lib/common/router_info/router_info.go +++ b/lib/common/router_info/router_info.go @@ -3,6 +3,8 @@ package router_info import ( "errors" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" "strconv" "strings" @@ -10,9 +12,10 @@ import ( . "github.com/go-i2p/go-i2p/lib/common/router_address" . "github.com/go-i2p/go-i2p/lib/common/router_identity" . "github.com/go-i2p/go-i2p/lib/common/signature" - log "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + const ROUTER_INFO_MIN_SIZE = 439 const ( @@ -115,6 +118,7 @@ type RouterInfo struct { // Bytes returns the RouterInfo as a []byte suitable for writing to a stream. func (router_info RouterInfo) Bytes() (bytes []byte, err error) { + log.Debug("Converting RouterInfo to bytes") bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...) bytes = append(bytes, router_info.published.Bytes()...) bytes = append(bytes, router_info.size.Bytes()...) @@ -124,11 +128,12 @@ func (router_info RouterInfo) Bytes() (bytes []byte, err error) { bytes = append(bytes, router_info.peer_size.Bytes()...) bytes = append(bytes, router_info.options.Data()...) bytes = append(bytes, []byte(*router_info.signature)...) - + log.WithField("bytes_length", len(bytes)).Debug("Converted RouterInfo to bytes") return bytes, err } func (router_info RouterInfo) String() string { + log.Debug("Converting RouterInfo to string") str := "Certificate: " + string(router_info.router_identity.KeysAndCert.Bytes()) str += "Published: " + string(router_info.published.Bytes()) str += "Addresses:" + string(router_info.size.Bytes()) @@ -138,6 +143,7 @@ func (router_info RouterInfo) String() string { str += "Peer Size: " + string(router_info.peer_size.Bytes()) str += "Options: " + string(router_info.options.Data()) str += "Signature: " + string([]byte(*router_info.signature)) + log.WithField("string_length", len(str)).Debug("Converted RouterInfo to string") return str } @@ -148,7 +154,10 @@ func (router_info *RouterInfo) RouterIdentity() *RouterIdentity { // IndentHash returns the identity hash (sha256 sum) for this RouterInfo. func (router_info *RouterInfo) IdentHash() Hash { + log.Debug("Calculating IdentHash for RouterInfo") data, _ := router_info.RouterIdentity().KeyCertificate.Data() + hash := HashData(data) + log.WithField("hash", hash).Debug("Calculated IdentHash for RouterInfo") return HashData(data) } @@ -159,11 +168,14 @@ func (router_info *RouterInfo) Published() *Date { // RouterAddressCount returns the count of RouterAddress in this RouterInfo as a Go integer. func (router_info *RouterInfo) RouterAddressCount() int { - return router_info.size.Int() + count := router_info.size.Int() + log.WithField("count", count).Debug("Retrieved RouterAddressCount from RouterInfo") + return count } // RouterAddresses returns all RouterAddresses for this RouterInfo as []*RouterAddress. func (router_info *RouterInfo) RouterAddresses() []*RouterAddress { + log.WithField("address_count", len(router_info.addresses)).Debug("Retrieved RouterAddresses from RouterInfo") return router_info.addresses } @@ -193,9 +205,11 @@ func (router_info RouterInfo) Network() string { // The remaining bytes after the specified length are also returned. // Returns a list of errors that occurred during parsing. func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) { + log.WithField("input_length", len(bytes)).Debug("Reading RouterInfo from bytes") + info.router_identity, remainder, err = ReadRouterIdentity(bytes) if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(RouterInfo) ReadRouterInfo", "data_len": len(bytes), "required_len": ROUTER_INFO_MIN_SIZE, @@ -206,7 +220,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) } info.published, remainder, err = NewDate(remainder) if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(RouterInfo) ReadRouterInfo", "data_len": len(remainder), "required_len": DATE_SIZE, @@ -216,7 +230,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) } info.size, remainder, err = NewInteger(remainder, 1) if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(RouterInfo) ReadRouterInfo", "data_len": len(remainder), "required_len": info.size.Int(), @@ -227,7 +241,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) address, more, err := ReadRouterAddress(remainder) remainder = more if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(RouterInfo) ReadRouterInfo", "data_len": len(remainder), //"required_len": ROUTER_ADDRESS_SIZE, @@ -238,10 +252,14 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) info.addresses = append(info.addresses, &address) } info.peer_size, remainder, err = NewInteger(remainder, 1) + if err != nil { + log.WithError(err).Error("Failed to read PeerSize") + return + } var errs []error info.options, remainder, errs = NewMapping(remainder) if len(errs) != 0 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(RouterInfo) ReadRouterInfo", "data_len": len(remainder), //"required_len": MAPPING_SIZE, @@ -255,7 +273,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) } info.signature, remainder, err = NewSignature(remainder) if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(RouterInfo) ReadRouterInfo", "data_len": len(remainder), //"required_len": MAPPING_SIZE, @@ -263,29 +281,49 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) }).Error("error parsing router info") err = errors.New("error parsing router info: not enough data") } + + log.WithFields(logrus.Fields{ + "router_identity": info.router_identity, + "published": info.published, + "address_count": len(info.addresses), + "remainder_length": len(remainder), + }).Debug("Successfully read RouterInfo") + return } func (router_info *RouterInfo) RouterCapabilities() string { + log.Debug("Retrieving RouterCapabilities") str, err := ToI2PString("caps") if err != nil { + log.WithError(err).Error("Failed to create I2PString for 'caps'") return "" } - return string(router_info.options.Values().Get(str)) + //return string(router_info.options.Values().Get(str)) + caps := string(router_info.options.Values().Get(str)) + log.WithField("capabilities", caps).Debug("Retrieved RouterCapabilities") + return caps } func (router_info *RouterInfo) RouterVersion() string { + log.Debug("Retrieving RouterVersion") str, err := ToI2PString("router.version") if err != nil { + log.WithError(err).Error("Failed to create I2PString for 'router.version'") return "" } - return string(router_info.options.Values().Get(str)) + //return string(router_info.options.Values().Get(str)) + version := string(router_info.options.Values().Get(str)) + log.WithField("version", version).Debug("Retrieved RouterVersion") + return version } func (router_info *RouterInfo) GoodVersion() bool { + log.Debug("Checking if RouterVersion is good") version := router_info.RouterVersion() v := strings.Split(version, ".") if len(v) != 3 { + log.WithField("version", version).Warn("Invalid version format") return false } if v[0] == "0" { @@ -296,27 +334,41 @@ func (router_info *RouterInfo) GoodVersion() bool { } } } + log.WithField("version", version).Warn("Version not in good range") return false } func (router_info *RouterInfo) UnCongested() bool { + log.Debug("Checking if RouterInfo is uncongested") caps := router_info.RouterCapabilities() if strings.Contains(caps, "K") { + log.WithField("reason", "K capability").Warn("RouterInfo is congested") return false } if strings.Contains(caps, "G") { + log.WithField("reason", "G capability").Warn("RouterInfo is congested") return false } if strings.Contains(caps, "E") { + log.WithField("reason", "E capability").Warn("RouterInfo is congested") return false } + log.Debug("RouterInfo is uncongested") return true } func (router_info *RouterInfo) Reachable() bool { + log.Debug("Checking if RouterInfo is reachable") caps := router_info.RouterCapabilities() if strings.Contains(caps, "U") { + log.WithField("reason", "U capability").Debug("RouterInfo is unreachable") return false } - return strings.Contains(caps, "R") + //return strings.Contains(caps, "R") + reachable := strings.Contains(caps, "R") + log.WithFields(logrus.Fields{ + "reachable": reachable, + "reason": "R capability", + }).Debug("Checked RouterInfo reachability") + return reachable } From 5c2b408f65656bf86722e89e9919719e5ccb7051 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 14:43:59 -0400 Subject: [PATCH 43/94] expanded logging to session_key.go --- lib/common/session_key/session_key.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/common/session_key/session_key.go b/lib/common/session_key/session_key.go index a912019..54868b3 100644 --- a/lib/common/session_key/session_key.go +++ b/lib/common/session_key/session_key.go @@ -1,6 +1,8 @@ // Package session_key implements the I2P SessionKey common data structure package session_key +import log "github.com/sirupsen/logrus" + /* [SessionKey] Accurate for version 0.9.49 @@ -22,13 +24,20 @@ type SessionKey [32]byte // Returns a list of errors that occurred during parsing. func ReadSessionKey(bytes []byte) (info SessionKey, remainder []byte, err error) { // TODO: stub + log.Warn("ReadSessionKey is not implemented") return } // NewSessionKey creates a new *SessionKey from []byte using ReadSessionKey. // Returns a pointer to SessionKey unlike ReadSessionKey. func NewSessionKey(data []byte) (session_key *SessionKey, remainder []byte, err error) { + log.WithField("input_length", len(data)).Debug("Creating new SessionKey") sessionKey, remainder, err := ReadSessionKey(data) + if err != nil { + log.WithError(err).Error("Failed to create new SessionKey") + return nil, remainder, err + } session_key = &sessionKey + log.Debug("Successfully created new SessionKey") return } From 1c4f937002e3d99ed2d0c1ae8f543d65171bbced Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 14:51:53 -0400 Subject: [PATCH 44/94] expanded logging to session_tag.go --- lib/common/session_tag/session_tag.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/common/session_tag/session_tag.go b/lib/common/session_tag/session_tag.go index 5574602..6509836 100644 --- a/lib/common/session_tag/session_tag.go +++ b/lib/common/session_tag/session_tag.go @@ -1,6 +1,13 @@ // Package session_tag implements the I2P SessionTag common data structure package session_tag +import ( + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" +) + +var log = logger.GetLogger() + /* [SessionKey] Accurate for version 0.9.49 @@ -22,13 +29,22 @@ type SessionTag [32]byte // Returns a list of errors that occurred during parsing. func ReadSessionTag(bytes []byte) (info SessionTag, remainder []byte, err error) { // TODO: stub + log.Warn("ReadSessionTag is not implemented") return } // NewSessionTag creates a new *SessionTag from []byte using ReadSessionTag. // Returns a pointer to SessionTag unlike ReadSessionTag. func NewSessionTag(data []byte) (session_tag *SessionTag, remainder []byte, err error) { + log.WithField("input_length", len(data)).Debug("Creating new SessionTag") sessionTag, remainder, err := ReadSessionTag(data) + if err != nil { + log.WithError(err).Error("Failed to read SessionTag") + return nil, remainder, err + } session_tag = &sessionTag + log.WithFields(logrus.Fields{ + "remainder_length": len(remainder), + }).Debug("Successfully created new SessionTag") return } From 4b2600a0655bf7df89356c10ac44075f97767ce7 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 14:55:30 -0400 Subject: [PATCH 45/94] expanded logging to signature.go -changed sessionTag -> sig --- lib/common/signature/signature.go | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/common/signature/signature.go b/lib/common/signature/signature.go index 1247ed3..1e9492e 100644 --- a/lib/common/signature/signature.go +++ b/lib/common/signature/signature.go @@ -1,6 +1,13 @@ // Package signature implements the I2P Signature common data structure package signature +import ( + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" +) + +var log = logger.GetLogger() + // Lengths of signature keys const ( DSA_SHA1_SIZE = 40 @@ -37,13 +44,25 @@ type Signature []byte // Returns a list of errors that occurred during parsing. func ReadSignature(bytes []byte) (info Signature, remainder []byte, err error) { // TODO: stub + log.Warn("ReadSignature is not implemented") return } // NewSignature creates a new *Signature from []byte using ReadSignature. // Returns a pointer to Signature unlike ReadSignature. func NewSignature(data []byte) (session_tag *Signature, remainder []byte, err error) { - sessionTag, remainder, err := ReadSignature(data) - session_tag = &sessionTag + log.WithField("input_length", len(data)).Debug("Creating new Signature") + //sessionTag, remainder, err := ReadSignature(data) + sig, remainder, err := ReadSignature(data) + if err != nil { + log.WithError(err).Error("Failed to read Signature") + return nil, remainder, err + } + session_tag = &sig + log.WithFields(logrus.Fields{ + "signature_length": len(sig), + "remainder_length": len(remainder), + }).Debug("Successfully created new Signature") + return } From df37d4944400343f4134b92074b8beed3589f8d2 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 15:10:16 -0400 Subject: [PATCH 46/94] expanded logging to aes.go --- lib/crypto/aes.go | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/crypto/aes.go b/lib/crypto/aes.go index 8465615..f805b46 100644 --- a/lib/crypto/aes.go +++ b/lib/crypto/aes.go @@ -5,8 +5,12 @@ import ( "crypto/aes" "crypto/cipher" "fmt" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + // AESSymmetricKey represents a symmetric key for AES encryption/decryption type AESSymmetricKey struct { Key []byte // AES key (must be 16, 24, or 32 bytes for AES-128, AES-192, AES-256) @@ -21,8 +25,11 @@ type AESSymmetricEncrypter struct { // Encrypt encrypts data using AES-CBC with PKCS#7 padding func (e *AESSymmetricEncrypter) Encrypt(data []byte) ([]byte, error) { + log.WithField("data_length", len(data)).Debug("Encrypting data") + block, err := aes.NewCipher(e.Key) if err != nil { + log.WithError(err).Error("Failed to create AES cipher") return nil, err } @@ -30,6 +37,8 @@ func (e *AESSymmetricEncrypter) Encrypt(data []byte) ([]byte, error) { ciphertext := make([]byte, len(plaintext)) mode := cipher.NewCBCEncrypter(block, e.IV) mode.CryptBlocks(ciphertext, plaintext) + + log.WithField("ciphertext_length", len(ciphertext)).Debug("Data encrypted successfully") return ciphertext, nil } @@ -41,12 +50,16 @@ type AESSymmetricDecrypter struct { // Decrypt decrypts data using AES-CBC with PKCS#7 padding func (d *AESSymmetricDecrypter) Decrypt(data []byte) ([]byte, error) { + log.WithField("data_length", len(data)).Debug("Decrypting data") + block, err := aes.NewCipher(d.Key) if err != nil { + log.WithError(err).Error("Failed to create AES cipher") return nil, err } if len(data)%aes.BlockSize != 0 { + log.Error("Ciphertext is not a multiple of the block size") return nil, fmt.Errorf("ciphertext is not a multiple of the block size") } @@ -56,13 +69,17 @@ func (d *AESSymmetricDecrypter) Decrypt(data []byte) ([]byte, error) { plaintext, err = pkcs7Unpad(plaintext) if err != nil { + log.WithError(err).Error("Failed to unpad plaintext") return nil, err } + + log.WithField("plaintext_length", len(plaintext)).Debug("Data decrypted successfully") return plaintext, nil } // NewEncrypter creates a new AESSymmetricEncrypter func (k *AESSymmetricKey) NewEncrypter() (Encrypter, error) { + log.Debug("Creating new AESSymmetricEncrypter") return &AESSymmetricEncrypter{ Key: k.Key, IV: k.IV, @@ -83,25 +100,41 @@ func (k *AESSymmetricKey) NewDecrypter() (Decrypter, error) { } func pkcs7Pad(data []byte, blockSize int) []byte { + log.WithFields(logrus.Fields{ + "data_length": len(data), + "block_size": blockSize, + }).Debug("Applying PKCS#7 padding") + padding := blockSize - (len(data) % blockSize) padText := bytes.Repeat([]byte{byte(padding)}, padding) + padded := append(data, padText...) + + log.WithField("padded_length", len(padded)).Debug("PKCS#7 padding applied") return append(data, padText...) } func pkcs7Unpad(data []byte) ([]byte, error) { + log.WithField("data_length", len(data)).Debug("Removing PKCS#7 padding") + length := len(data) if length == 0 { + log.Error("Data is empty") return nil, fmt.Errorf("data is empty") } padding := int(data[length-1]) if padding == 0 || padding > aes.BlockSize { + log.WithField("padding", padding).Error("Invalid padding") return nil, fmt.Errorf("invalid padding") } paddingStart := length - padding for i := paddingStart; i < length; i++ { if data[i] != byte(padding) { + log.Error("Invalid padding") return nil, fmt.Errorf("invalid padding") } } - return data[:paddingStart], nil + + unpadded := data[:paddingStart] + log.WithField("unpadded_length", len(unpadded)).Debug("PKCS#7 padding removed") + return unpadded, nil } From a533cd7ce420600c89af0eeecdbc9421ccec48a5 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 16:39:28 -0400 Subject: [PATCH 47/94] expanded logging in curve25519.go --- lib/crypto/curve25519.go | 56 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/lib/crypto/curve25519.go b/lib/crypto/curve25519.go index d20d858..64acd70 100644 --- a/lib/crypto/curve25519.go +++ b/lib/crypto/curve25519.go @@ -5,6 +5,7 @@ import ( "crypto/sha256" "crypto/sha512" "errors" + "github.com/sirupsen/logrus" "io" "math/big" @@ -27,14 +28,20 @@ func (k Curve25519PublicKey) NewVerifier() (v Verifier, err error) { } func (k Curve25519PublicKey) Len() int { - return len(k) + length := len(k) + log.WithField("length", length).Debug("Retrieved Curve25519PublicKey length") + return length } func createCurve25519PublicKey(data []byte) (k *curve25519.PublicKey) { + log.WithField("data_length", len(data)).Debug("Creating Curve25519PublicKey") if len(data) == 256 { k2 := curve25519.PublicKey{} copy(k2[:], data) k = &k2 + log.Debug("Curve25519PublicKey created successfully") + } else { + log.Warn("Invalid data length for Curve25519PublicKey") } return } @@ -53,6 +60,7 @@ func createCurve25519Encryption(pub *curve25519.PublicKey, rand io.Reader) (enc if err == nil { enc = &Curve25519Encryption{} }*/ + log.Warn("createCurve25519Encryption is not implemented") return } @@ -61,11 +69,17 @@ type Curve25519Encryption struct { } func (curve25519 *Curve25519Encryption) Encrypt(data []byte) (enc []byte, err error) { + log.WithField("data_length", len(data)).Debug("Encrypting data with Curve25519") return curve25519.EncryptPadding(data, true) } func (curve25519 *Curve25519Encryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error) { + log.WithFields(logrus.Fields{ + "data_length": len(data), + "zero_padding": zeroPadding, + }).Debug("Encrypting data with padding using Curve25519") if len(data) > 222 { + log.Error("Data too big for Curve25519 encryption") err = Curve25519EncryptTooBig return } @@ -88,33 +102,55 @@ func (curve25519 *Curve25519Encryption) EncryptPadding(data []byte, zeroPadding copy(encrypted, curve25519.a.Bytes()) copy(encrypted[256:], b) } + log.WithField("encrypted_length", len(encrypted)).Debug("Data encrypted successfully") return } func (elg Curve25519PublicKey) NewEncrypter() (enc Encrypter, err error) { + log.Debug("Creating new Curve25519 Encrypter") k := createCurve25519PublicKey(elg[:]) enc, err = createCurve25519Encryption(k, rand.Reader) + if err != nil { + log.WithError(err).Error("Failed to create Curve25519 Encrypter") + } else { + log.Debug("Curve25519 Encrypter created successfully") + } return } func (v *Curve25519Verifier) VerifyHash(h, sig []byte) (err error) { + log.WithFields(logrus.Fields{ + "hash_length": len(h), + "signature_length": len(sig), + }).Debug("Verifying hash with Curve25519") + if len(sig) != curve25519.SignatureSize { + log.Error("Bad signature size") err = ErrBadSignatureSize return } if len(v.k) != curve25519.PublicKeySize { + log.Error("Invalid Curve25519 public key size") err = errors.New("failed to verify: invalid curve25519 public key size") return } ok := curve25519.Verify(v.k, h, sig) if !ok { + log.Error("Invalid signature") err = errors.New("failed to verify: invalid signature") + } else { + log.Debug("Hash verified successfully") } return } func (v *Curve25519Verifier) Verify(data, sig []byte) (err error) { + log.WithFields(logrus.Fields{ + "data_length": len(data), + "signature_length": len(sig), + }).Debug("Verifying data with Curve25519") + h := sha512.Sum512(data) err = v.VerifyHash(h[:], sig) return @@ -127,15 +163,31 @@ type Curve25519Signer struct { } func (s *Curve25519Signer) Sign(data []byte) (sig []byte, err error) { + log.WithField("data_length", len(data)).Debug("Signing data with Curve25519") + if len(s.k) != curve25519.PrivateKeySize { + log.Error("Invalid Curve25519 private key size") err = errors.New("failed to sign: invalid curve25519 private key size") return } h := sha512.Sum512(data) sig, err = s.SignHash(h[:]) + if err != nil { + log.WithError(err).Error("Failed to sign data") + } else { + log.WithField("signature_length", len(sig)).Debug("Data signed successfully") + } return } func (s *Curve25519Signer) SignHash(h []byte) (sig []byte, err error) { - return curve25519.Sign(rand.Reader, s.k, h) + log.WithField("hash_length", len(h)).Debug("Signing hash with Curve25519") + sig, err = curve25519.Sign(rand.Reader, s.k, h) + if err != nil { + log.WithError(err).Error("Failed to sign hash") + } else { + log.WithField("signature_length", len(sig)).Debug("Hash signed successfully") + } + //return curve25519.Sign(rand.Reader, s.k, h) + return } From e772fb5cebf90f856303554d7c367c85a883f236 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 16:56:25 -0400 Subject: [PATCH 48/94] expanded logging in dsa.go --- lib/crypto/dsa.go | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/crypto/dsa.go b/lib/crypto/dsa.go index 30087b8..e5b30fe 100644 --- a/lib/crypto/dsa.go +++ b/lib/crypto/dsa.go @@ -4,6 +4,7 @@ import ( "crypto/dsa" "crypto/rand" "crypto/sha1" + "github.com/sirupsen/logrus" "io" "math/big" ) @@ -43,16 +44,24 @@ var param = dsa.Parameters{ // generate a dsa keypair func generateDSA(priv *dsa.PrivateKey, rand io.Reader) error { + log.Debug("Generating DSA key pair") // put our paramters in priv.P = param.P priv.Q = param.Q priv.G = param.G // generate the keypair - return dsa.GenerateKey(priv, rand) + err := dsa.GenerateKey(priv, rand) + if err != nil { + log.WithError(err).Error("Failed to generate DSA key pair") + } else { + log.Debug("DSA key pair generated successfully") + } + return err } // create i2p dsa public key given its public component func createDSAPublicKey(Y *big.Int) *dsa.PublicKey { + log.Debug("Creating DSA public key") return &dsa.PublicKey{ Parameters: param, Y: Y, @@ -61,6 +70,7 @@ func createDSAPublicKey(Y *big.Int) *dsa.PublicKey { // createa i2p dsa private key given its public component func createDSAPrivkey(X *big.Int) (k *dsa.PrivateKey) { + log.Debug("Creating DSA private key") if X.Cmp(dsap) == -1 { Y := new(big.Int) Y.Exp(dsag, X, dsap) @@ -71,6 +81,9 @@ func createDSAPrivkey(X *big.Int) (k *dsa.PrivateKey) { }, X: X, } + log.Debug("DSA private key created successfully") + } else { + log.Warn("Failed to create DSA private key: X is not less than p") } return } @@ -83,6 +96,7 @@ type DSAPublicKey [128]byte // create a new dsa verifier func (k DSAPublicKey) NewVerifier() (v Verifier, err error) { + log.Debug("Creating new DSA verifier") v = &DSAVerifier{ k: createDSAPublicKey(new(big.Int).SetBytes(k[:])), } @@ -91,6 +105,10 @@ func (k DSAPublicKey) NewVerifier() (v Verifier, err error) { // verify data with a dsa public key func (v *DSAVerifier) Verify(data, sig []byte) (err error) { + log.WithFields(logrus.Fields{ + "data_length": len(data), + "sig_length": len(sig), + }).Debug("Verifying DSA signature") h := sha1.Sum(data) err = v.VerifyHash(h[:], sig) return @@ -98,16 +116,23 @@ func (v *DSAVerifier) Verify(data, sig []byte) (err error) { // verify hash of data with a dsa public key func (v *DSAVerifier) VerifyHash(h, sig []byte) (err error) { + log.WithFields(logrus.Fields{ + "hash_length": len(h), + "sig_length": len(sig), + }).Debug("Verifying DSA signature hash") if len(sig) == 40 { r := new(big.Int).SetBytes(sig[:20]) s := new(big.Int).SetBytes(sig[20:]) if dsa.Verify(v.k, h, r, s) { // valid signature + log.Debug("DSA signature verified successfully") } else { // invalid signature + log.Warn("Invalid DSA signature") err = ErrInvalidSignature } } else { + log.Error("Bad DSA signature size") err = ErrBadSignatureSize } return @@ -125,6 +150,7 @@ type DSAPrivateKey [20]byte // create a new dsa signer func (k DSAPrivateKey) NewSigner() (s Signer, err error) { + log.Debug("Creating new DSA signer") s = &DSASigner{ k: createDSAPrivkey(new(big.Int).SetBytes(k[:])), } @@ -134,30 +160,38 @@ func (k DSAPrivateKey) NewSigner() (s Signer, err error) { func (k DSAPrivateKey) Public() (pk DSAPublicKey, err error) { p := createDSAPrivkey(new(big.Int).SetBytes(k[:])) if p == nil { + log.Error("Invalid DSA private key format") err = ErrInvalidKeyFormat } else { copy(pk[:], p.Y.Bytes()) + log.Debug("DSA public key derived successfully") } return } func (k DSAPrivateKey) Generate() (s DSAPrivateKey, err error) { + log.Debug("Generating new DSA private key") dk := new(dsa.PrivateKey) err = generateDSA(dk, rand.Reader) if err == nil { copy(k[:], dk.X.Bytes()) s = k + log.Debug("New DSA private key generated successfully") + } else { + log.WithError(err).Error("Failed to generate new DSA private key") } return } func (ds *DSASigner) Sign(data []byte) (sig []byte, err error) { + log.WithField("data_length", len(data)).Debug("Signing data with DSA") h := sha1.Sum(data) sig, err = ds.SignHash(h[:]) return } func (ds *DSASigner) SignHash(h []byte) (sig []byte, err error) { + log.WithField("hash_length", len(h)).Debug("Signing hash with DSA") var r, s *big.Int r, s, err = dsa.Sign(rand.Reader, ds.k, h) if err == nil { @@ -168,6 +202,9 @@ func (ds *DSASigner) SignHash(h []byte) (sig []byte, err error) { sb := s.Bytes() sl := len(sb) copy(sig[20+(20-sl):], sb) + log.WithField("sig_length", len(sig)).Debug("DSA signature created successfully") + } else { + log.WithError(err).Error("Failed to create DSA signature") } return } From 84e3c5accc38906d421c4ab777b97d639bf9a8bf Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 17:01:42 -0400 Subject: [PATCH 49/94] expanded logging in ecdsa.go --- lib/crypto/ecdsa.go | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/lib/crypto/ecdsa.go b/lib/crypto/ecdsa.go index 1e76e0f..61262bd 100644 --- a/lib/crypto/ecdsa.go +++ b/lib/crypto/ecdsa.go @@ -4,6 +4,7 @@ import ( "crypto" "crypto/ecdsa" "crypto/elliptic" + "github.com/sirupsen/logrus" ) type ECDSAVerifier struct { @@ -14,15 +15,27 @@ type ECDSAVerifier struct { // verify a signature given the hash func (v *ECDSAVerifier) VerifyHash(h, sig []byte) (err error) { + log.WithFields(logrus.Fields{ + "hash_length": len(h), + "sig_length": len(sig), + }).Debug("Verifying ECDSA signature hash") + r, s := elliptic.Unmarshal(v.c, sig) if r == nil || s == nil || !ecdsa.Verify(v.k, h, r, s) { + log.Warn("Invalid ECDSA signature") err = ErrInvalidSignature + } else { + log.Debug("ECDSA signature verified successfully") } return } // verify a block of data by hashing it and comparing the hash against the signature func (v *ECDSAVerifier) Verify(data, sig []byte) (err error) { + log.WithFields(logrus.Fields{ + "data_length": len(data), + "sig_length": len(sig), + }).Debug("Verifying ECDSA signature") // sum the data and get the hash h := v.h.New().Sum(data)[len(data):] // verify @@ -31,8 +44,13 @@ func (v *ECDSAVerifier) Verify(data, sig []byte) (err error) { } func createECVerifier(c elliptic.Curve, h crypto.Hash, k []byte) (ev *ECDSAVerifier, err error) { + log.WithFields(logrus.Fields{ + "curve": c.Params().Name, + "hash": h.String(), + }).Debug("Creating ECDSA verifier") x, y := elliptic.Unmarshal(c, k[:]) if x == nil { + log.Error("Invalid ECDSA key format") err = ErrInvalidKeyFormat } else { ev = &ECDSAVerifier{ @@ -40,6 +58,7 @@ func createECVerifier(c elliptic.Curve, h crypto.Hash, k []byte) (ev *ECDSAVerif h: h, } ev.k = &ecdsa.PublicKey{c, x, y} + log.Debug("ECDSA verifier created successfully") } return } @@ -54,7 +73,13 @@ func (k ECP256PublicKey) Len() int { } func (k ECP256PublicKey) NewVerifier() (Verifier, error) { - return createECVerifier(elliptic.P256(), crypto.SHA256, k[:]) + log.Debug("Creating new P256 ECDSA verifier") + //return createECVerifier(elliptic.P256(), crypto.SHA256, k[:]) + v, err := createECVerifier(elliptic.P256(), crypto.SHA256, k[:]) + if err != nil { + log.WithError(err).Error("Failed to create P256 ECDSA verifier") + } + return v, err } type ( @@ -67,7 +92,13 @@ func (k ECP384PublicKey) Len() int { } func (k ECP384PublicKey) NewVerifier() (Verifier, error) { - return createECVerifier(elliptic.P384(), crypto.SHA384, k[:]) + log.Debug("Creating new P384 ECDSA verifier") + v, err := createECVerifier(elliptic.P384(), crypto.SHA384, k[:]) + if err != nil { + log.WithError(err).Error("Failed to create P384 ECDSA verifier") + } + return v, err + //return createECVerifier(elliptic.P384(), crypto.SHA384, k[:]) } type ( @@ -80,5 +111,11 @@ func (k ECP521PublicKey) Len() int { } func (k ECP521PublicKey) NewVerifier() (Verifier, error) { - return createECVerifier(elliptic.P521(), crypto.SHA512, k[:]) + log.Debug("Creating new P521 ECDSA verifier") + v, err := createECVerifier(elliptic.P521(), crypto.SHA512, k[:]) + if err != nil { + log.WithError(err).Error("Failed to create P521 ECDSA verifier") + } + return v, err + //return createECVerifier(elliptic.P521(), crypto.SHA512, k[:]) } From 8680acc5957416199daef8c77e8bcfd350a7d79c Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 21:42:07 -0400 Subject: [PATCH 50/94] expanded logging in ed25519.go --- lib/crypto/ed25519.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/crypto/ed25519.go b/lib/crypto/ed25519.go index f569677..9bf21ad 100644 --- a/lib/crypto/ed25519.go +++ b/lib/crypto/ed25519.go @@ -6,6 +6,7 @@ import ( "crypto/sha256" "crypto/sha512" "errors" + "github.com/sirupsen/logrus" "io" "math/big" ) @@ -30,10 +31,14 @@ func (k Ed25519PublicKey) Len() int { } func createEd25519PublicKey(data []byte) (k *ed25519.PublicKey) { + log.WithField("data_length", len(data)).Debug("Creating Ed25519 public key") if len(data) == 256 { k2 := ed25519.PublicKey{} copy(k2[:], data) k = &k2 + log.Debug("Ed25519 public key created successfully") + } else { + log.Warn("Invalid data length for Ed25519 public key") } return } @@ -52,6 +57,7 @@ func createEd25519Encryption(pub *ed25519.PublicKey, rand io.Reader) (enc *Ed255 if err == nil { enc = &Ed25519Encryption{} }*/ + log.Warn("createEd25519Encryption is not implemented") return } @@ -60,11 +66,18 @@ type Ed25519Encryption struct { } func (ed25519 *Ed25519Encryption) Encrypt(data []byte) (enc []byte, err error) { + log.Warn("createEd25519Encryption is not implemented") return ed25519.EncryptPadding(data, true) } func (ed25519 *Ed25519Encryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error) { + log.WithFields(logrus.Fields{ + "data_length": len(data), + "zero_padding": zeroPadding, + }).Debug("Encrypting data with padding using Ed25519") + if len(data) > 222 { + log.Error("Data too big for Ed25519 encryption") err = Ed25519EncryptTooBig return } @@ -87,33 +100,56 @@ func (ed25519 *Ed25519Encryption) EncryptPadding(data []byte, zeroPadding bool) copy(encrypted, ed25519.a.Bytes()) copy(encrypted[256:], b) } + + log.WithField("encrypted_length", len(encrypted)).Debug("Data encrypted successfully with Ed25519") return } func (elg Ed25519PublicKey) NewEncrypter() (enc Encrypter, err error) { + log.Debug("Creating new Ed25519 encrypter") k := createEd25519PublicKey(elg[:]) enc, err = createEd25519Encryption(k, rand.Reader) + if err != nil { + log.WithError(err).Error("Failed to create Ed25519 encrypter") + } else { + log.Debug("Ed25519 encrypter created successfully") + } return } func (v *Ed25519Verifier) VerifyHash(h, sig []byte) (err error) { + log.WithFields(logrus.Fields{ + "hash_length": len(h), + "sig_length": len(sig), + }).Debug("Verifying Ed25519 signature hash") + if len(sig) != ed25519.SignatureSize { + log.Error("Bad Ed25519 signature size") err = ErrBadSignatureSize return } if len(v.k) != ed25519.PublicKeySize { + log.Error("Invalid Ed25519 public key size") err = errors.New("failed to verify: invalid ed25519 public key size") return } ok := ed25519.Verify(v.k, h, sig) if !ok { + log.Warn("Invalid Ed25519 signature") err = errors.New("failed to verify: invalid signature") + } else { + log.Debug("Ed25519 signature verified successfully") } return } func (v *Ed25519Verifier) Verify(data, sig []byte) (err error) { + log.WithFields(logrus.Fields{ + "data_length": len(data), + "sig_length": len(sig), + }).Debug("Verifying Ed25519 signature") + h := sha512.Sum512(data) err = v.VerifyHash(h[:], sig) return @@ -126,7 +162,10 @@ type Ed25519Signer struct { } func (s *Ed25519Signer) Sign(data []byte) (sig []byte, err error) { + log.WithField("data_length", len(data)).Debug("Signing data with Ed25519") + if len(s.k) != ed25519.PrivateKeySize { + log.Error("Invalid Ed25519 private key size") err = errors.New("failed to sign: invalid ed25519 private key size") return } @@ -136,6 +175,8 @@ func (s *Ed25519Signer) Sign(data []byte) (sig []byte, err error) { } func (s *Ed25519Signer) SignHash(h []byte) (sig []byte, err error) { + log.WithField("hash_length", len(h)).Debug("Signing hash with Ed25519") sig = ed25519.Sign(s.k, h) + log.WithField("signature_length", len(sig)).Debug("Ed25519 signature created successfully") return } From a1d574446bab1789dfdcb9e5a845a031d6af4c47 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 21:54:27 -0400 Subject: [PATCH 51/94] expanded logging in elg.go --- lib/crypto/elg.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/lib/crypto/elg.go b/lib/crypto/elg.go index 853f37d..93a956b 100644 --- a/lib/crypto/elg.go +++ b/lib/crypto/elg.go @@ -5,6 +5,7 @@ import ( "crypto/sha256" "crypto/subtle" "errors" + "github.com/sirupsen/logrus" "io" "math/big" @@ -42,6 +43,7 @@ var ( // generate an elgamal key pair func ElgamalGenerate(priv *elgamal.PrivateKey, rand io.Reader) (err error) { + log.Debug("Generating ElGamal key pair") priv.P = elgp priv.G = elgg xBytes := make([]byte, priv.P.BitLen()/8) @@ -51,6 +53,9 @@ func ElgamalGenerate(priv *elgamal.PrivateKey, rand io.Reader) (err error) { priv.X = new(big.Int).SetBytes(xBytes) // compute public key priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P) + log.Debug("ElGamal key pair generated successfully") + } else { + log.WithError(err).Error("Failed to generate ElGamal key pair") } return } @@ -60,12 +65,23 @@ type elgDecrypter struct { } func (elg *elgDecrypter) Decrypt(data []byte) (dec []byte, err error) { + log.WithField("data_length", len(data)).Debug("Decrypting ElGamal data") dec, err = elgamalDecrypt(elg.k, data, true) // TODO(psi): should this be true or false? + if err != nil { + log.WithError(err).Error("Failed to decrypt ElGamal data") + } else { + log.WithField("decrypted_length", len(dec)).Debug("ElGamal data decrypted successfully") + } return } // decrypt an elgamal encrypted message, i2p style func elgamalDecrypt(priv *elgamal.PrivateKey, data []byte, zeroPadding bool) (decrypted []byte, err error) { + log.WithFields(logrus.Fields{ + "data_length": len(data), + "zero_padding": zeroPadding, + }).Debug("Decrypting ElGamal data") + a := new(big.Int) b := new(big.Int) idx := 0 @@ -87,9 +103,11 @@ func elgamalDecrypt(priv *elgamal.PrivateKey, data []byte, zeroPadding bool) (de if subtle.ConstantTimeCompare(d[:], m[1:33]) == 1 { // decryption successful good = 1 + log.Debug("ElGamal decryption successful") } else { // decrypt failed err = ElgDecryptFail + log.WithError(err).Error("ElGamal decryption failed") } // copy result decrypted = make([]byte, 222) @@ -107,10 +125,16 @@ type ElgamalEncryption struct { } func (elg *ElgamalEncryption) Encrypt(data []byte) (enc []byte, err error) { + log.WithField("data_length", len(data)).Debug("Encrypting data with ElGamal") return elg.EncryptPadding(data, true) } func (elg *ElgamalEncryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error) { + log.WithFields(logrus.Fields{ + "data_length": len(data), + "zero_padding": zeroPadding, + }).Debug("Encrypting data with ElGamal padding") + if len(data) > 222 { err = ElgEncryptTooBig return @@ -134,23 +158,31 @@ func (elg *ElgamalEncryption) EncryptPadding(data []byte, zeroPadding bool) (enc copy(encrypted, elg.a.Bytes()) copy(encrypted[256:], b) } + + log.WithField("encrypted_length", len(encrypted)).Debug("Data encrypted successfully with ElGamal") return } // create an elgamal public key from byte slice func createElgamalPublicKey(data []byte) (k *elgamal.PublicKey) { + log.WithField("data_length", len(data)).Debug("Creating ElGamal public key") if len(data) == 256 { k = &elgamal.PublicKey{ G: elgg, P: elgp, Y: new(big.Int).SetBytes(data), } + log.Debug("ElGamal public key created successfully") + } else { + log.Warn("Invalid data length for ElGamal public key") } + return } // create an elgamal private key from byte slice func createElgamalPrivateKey(data []byte) (k *elgamal.PrivateKey) { + log.WithField("data_length", len(data)).Debug("Creating ElGamal private key") if len(data) == 256 { x := new(big.Int).SetBytes(data) y := new(big.Int).Exp(elgg, x, elgp) @@ -162,12 +194,16 @@ func createElgamalPrivateKey(data []byte) (k *elgamal.PrivateKey) { }, X: x, } + log.Debug("ElGamal private key created successfully") + } else { + log.Warn("Invalid data length for ElGamal private key") } return } // create a new elgamal encryption session func createElgamalEncryption(pub *elgamal.PublicKey, rand io.Reader) (enc *ElgamalEncryption, err error) { + log.Debug("Creating ElGamal encryption session") kbytes := make([]byte, 256) k := new(big.Int) for err == nil { @@ -184,6 +220,9 @@ func createElgamalEncryption(pub *elgamal.PublicKey, rand io.Reader) (enc *Elgam a: new(big.Int).Exp(pub.G, k, pub.P), b1: new(big.Int).Exp(pub.Y, k, pub.P), } + log.Debug("ElGamal encryption session created successfully") + } else { + log.WithError(err).Error("Failed to create ElGamal encryption session") } return } @@ -198,8 +237,14 @@ func (elg ElgPublicKey) Len() int { } func (elg ElgPublicKey) NewEncrypter() (enc Encrypter, err error) { + log.Debug("Creating new ElGamal encrypter") k := createElgamalPublicKey(elg[:]) enc, err = createElgamalEncryption(k, rand.Reader) + if err != nil { + log.WithError(err).Error("Failed to create ElGamal encrypter") + } else { + log.Debug("ElGamal encrypter created successfully") + } return } @@ -208,8 +253,10 @@ func (elg ElgPrivateKey) Len() int { } func (elg ElgPrivateKey) NewDecrypter() (dec Decrypter, err error) { + log.Debug("Creating new ElGamal decrypter") dec = &elgDecrypter{ k: createElgamalPrivateKey(elg[:]), } + log.Debug("ElGamal decrypter created successfully") return } From e8c9dc17a301316f72b5994b2e7b00410ac7f30d Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 21:58:50 -0400 Subject: [PATCH 52/94] expanded logging in tunnel.go --- lib/crypto/tunnel.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/crypto/tunnel.go b/lib/crypto/tunnel.go index e681fec..c825b13 100644 --- a/lib/crypto/tunnel.go +++ b/lib/crypto/tunnel.go @@ -19,6 +19,7 @@ type Tunnel struct { } func NewTunnelCrypto(layerKey, ivKey TunnelKey) (t *Tunnel, err error) { + log.Debug("Creating new Tunnel crypto") t = new(Tunnel) t.layerKey, err = aes.NewCipher(layerKey[:]) if err == nil { @@ -27,24 +28,31 @@ func NewTunnelCrypto(layerKey, ivKey TunnelKey) (t *Tunnel, err error) { if err != nil { // error happened we don't need t + //log.WithError(err).Error("Failed to create Tunnel crypto") t = nil + } else { + log.Debug("Tunnel crypto created successfully") } return } // encrypt tunnel data in place func (t *Tunnel) Encrypt(td *TunnelData) { + log.Debug("Encrypting Tunnel data") data := *td t.ivKey.Encrypt(data[16:1024], data[16:1024]) layerBlock := cipher.NewCBCEncrypter(t.layerKey, data[:16]) layerBlock.CryptBlocks(data[16:1024], data[16:1024]) t.ivKey.Encrypt(data[16:1024], data[16:1024]) + log.Debug("Tunnel data encrypted successfully") } func (t *Tunnel) Decrypt(td *TunnelData) { + log.Debug("Decrypting Tunnel data") data := *td t.ivKey.Decrypt(data[16:1024], data[16:1024]) layerBlock := cipher.NewCBCDecrypter(t.layerKey, data[:16]) layerBlock.CryptBlocks(data[16:1024], data[16:1024]) t.ivKey.Decrypt(data[16:1024], data[16:1024]) + log.Debug("Tunnel data decrypted successfully") } From 013d35b44754f8d4637a85f6b924a502f3d95379 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 22:41:40 -0400 Subject: [PATCH 53/94] expanded logging in build_request_record.go --- lib/i2np/build_request_record.go | 43 ++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/lib/i2np/build_request_record.go b/lib/i2np/build_request_record.go index d986b06..cd48713 100644 --- a/lib/i2np/build_request_record.go +++ b/lib/i2np/build_request_record.go @@ -2,14 +2,17 @@ package i2np import ( "errors" + "github.com/sirupsen/logrus" "time" common "github.com/go-i2p/go-i2p/lib/common/data" "github.com/go-i2p/go-i2p/lib/common/session_key" "github.com/go-i2p/go-i2p/lib/tunnel" - log "github.com/sirupsen/logrus" + "github.com/go-i2p/go-i2p/lib/util/logger" ) +var log = logger.GetLogger() + /* I2P I2NP BuildRequestRecord https://geti2p.net/spec/i2np @@ -172,80 +175,94 @@ type BuildRequestRecord struct { var ERR_BUILD_REQUEST_RECORD_NOT_ENOUGH_DATA = errors.New("not enough i2np build request record data") func ReadBuildRequestRecord(data []byte) (BuildRequestRecord, error) { + log.Debug("Reading BuildRequestRecord") build_request_record := BuildRequestRecord{} receive_tunnel, err := readBuildRequestRecordReceiveTunnel(data) if err != nil { + log.WithError(err).Error("Failed to read ReceiveTunnel") return build_request_record, err } build_request_record.ReceiveTunnel = receive_tunnel our_ident, err := readBuildRequestRecordOurIdent(data) if err != nil { + log.WithError(err).Error("Failed to read OurIdent") return build_request_record, err } build_request_record.OurIdent = our_ident next_tunnel, err := readBuildRequestRecordNextTunnel(data) if err != nil { + log.WithError(err).Error("Failed to read NextTunnel") return build_request_record, err } build_request_record.NextTunnel = next_tunnel next_ident, err := readBuildRequestRecordNextIdent(data) if err != nil { + log.WithError(err).Error("Failed to read NextIdent") return build_request_record, err } build_request_record.NextIdent = next_ident layer_key, err := readBuildRequestRecordLayerKey(data) if err != nil { + log.WithError(err).Error("Failed to read LayerKey") return build_request_record, err } build_request_record.LayerKey = layer_key iv_key, err := readBuildRequestRecordIVKey(data) if err != nil { + log.WithError(err).Error("Failed to read IVKey") return build_request_record, err } build_request_record.IVKey = iv_key reply_key, err := readBuildRequestRecordReplyKey(data) if err != nil { + log.WithError(err).Error("Failed to read ReplyKey") return build_request_record, err } build_request_record.ReplyKey = reply_key reply_iv, err := readBuildRequestRecordReplyIV(data) if err != nil { + log.WithError(err).Error("Failed to read ReplyIV") return build_request_record, err } build_request_record.ReplyIV = reply_iv flag, err := readBuildRequestRecordFlag(data) if err != nil { + log.WithError(err).Error("Failed to read Flag") return build_request_record, err } build_request_record.Flag = flag request_time, err := readBuildRequestRecordRequestTime(data) if err != nil { + log.WithError(err).Error("Failed to read RequestTime") return build_request_record, err } build_request_record.RequestTime = request_time send_message_id, err := readBuildRequestRecordSendMessageID(data) if err != nil { + log.WithError(err).Error("Failed to read SendMessageID") return build_request_record, err } build_request_record.SendMessageID = send_message_id padding, err := readBuildRequestRecordPadding(data) if err != nil { + log.WithError(err).Error("Failed to read Padding") return build_request_record, err } build_request_record.Padding = padding + log.Debug("BuildRequestRecord read successfully") return build_request_record, nil } @@ -258,7 +275,7 @@ func readBuildRequestRecordReceiveTunnel(data []byte) (tunnel.TunnelID, error) { common.Integer(data[0:4]).Int(), ) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordReceiveTunnel", "receieve_tunnel": receive_tunnel, }).Debug("parsed_build_request_record_receive_tunnel") @@ -273,7 +290,7 @@ func readBuildRequestRecordOurIdent(data []byte) (common.Hash, error) { hash := common.Hash{} copy(hash[:], data[4:36]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordOurIdent", }).Debug("parsed_build_request_record_our_ident") return hash, nil @@ -288,7 +305,7 @@ func readBuildRequestRecordNextTunnel(data []byte) (tunnel.TunnelID, error) { common.Integer(data[36:40]).Int(), ) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordNextTunnel", "next_tunnel": next_tunnel, }).Debug("parsed_build_request_record_next_tunnel") @@ -303,7 +320,7 @@ func readBuildRequestRecordNextIdent(data []byte) (common.Hash, error) { hash := common.Hash{} copy(hash[:], data[40:72]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordNextIdent", }).Debug("parsed_build_request_record_next_ident") return hash, nil @@ -317,7 +334,7 @@ func readBuildRequestRecordLayerKey(data []byte) (session_key.SessionKey, error) session_key := session_key.SessionKey{} copy(session_key[:], data[72:104]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordLayerKey", }).Debug("parsed_build_request_record_layer_key") return session_key, nil @@ -331,7 +348,7 @@ func readBuildRequestRecordIVKey(data []byte) (session_key.SessionKey, error) { session_key := session_key.SessionKey{} copy(session_key[:], data[104:136]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordIVKey", }).Debug("parsed_build_request_record_iv_key") return session_key, nil @@ -345,7 +362,7 @@ func readBuildRequestRecordReplyKey(data []byte) (session_key.SessionKey, error) session_key := session_key.SessionKey{} copy(session_key[:], data[136:168]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordReplyKey", }).Debug("parsed_build_request_record_reply_key") return session_key, nil @@ -359,7 +376,7 @@ func readBuildRequestRecordReplyIV(data []byte) ([16]byte, error) { iv := [16]byte{} copy(iv[:], data[168:184]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordReplyIV", }).Debug("parsed_build_request_record_reply_iv") return iv, nil @@ -372,7 +389,7 @@ func readBuildRequestRecordFlag(data []byte) (int, error) { flag := common.Integer([]byte{data[185]}).Int() - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordFlag", "flag": flag, }).Debug("parsed_build_request_record_flag") @@ -387,7 +404,7 @@ func readBuildRequestRecordRequestTime(data []byte) (time.Time, error) { count := common.Integer(data[185:189]).Int() rtime := time.Unix(0, 0).Add(time.Duration(count) * time.Hour) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordRequestTime", }).Debug("parsed_build_request_record_request_time") return rtime, nil @@ -400,7 +417,7 @@ func readBuildRequestRecordSendMessageID(data []byte) (int, error) { send_message_id := common.Integer(data[189:193]).Int() - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordSendMessageID", }).Debug("parsed_build_request_record_send_message_id") return send_message_id, nil @@ -414,7 +431,7 @@ func readBuildRequestRecordPadding(data []byte) ([29]byte, error) { padding := [29]byte{} copy(padding[:], data[193:222]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.readBuildRequestRecordPadding", }).Debug("parsed_build_request_record_padding") return padding, nil From be35267079611bee6da4b49d3b266a87311d5790 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 22:47:28 -0400 Subject: [PATCH 54/94] expanded logging in header.go --- lib/i2np/header.go | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/lib/i2np/header.go b/lib/i2np/header.go index 9cfe7f3..2d493dc 100644 --- a/lib/i2np/header.go +++ b/lib/i2np/header.go @@ -2,11 +2,10 @@ package i2np import ( "errors" + "github.com/sirupsen/logrus" "time" datalib "github.com/go-i2p/go-i2p/lib/common/data" - - log "github.com/sirupsen/logrus" ) /* @@ -95,10 +94,12 @@ var ERR_I2NP_NOT_ENOUGH_DATA = errors.New("not enough i2np header data") // Read an entire I2NP message and return the parsed header // with embedded encrypted data func ReadI2NPNTCPHeader(data []byte) (I2NPNTCPHeader, error) { + log.Debug("Reading I2NP NTCP Header") header := I2NPNTCPHeader{} message_type, err := ReadI2NPType(data) if err != nil { + log.WithError(err).Error("Failed to read I2NP type") return header, err } else { header.Type = message_type @@ -106,6 +107,7 @@ func ReadI2NPNTCPHeader(data []byte) (I2NPNTCPHeader, error) { message_id, err := ReadI2NPNTCPMessageID(data) if err != nil { + log.WithError(err).Error("Failed to read I2NP NTCP message ID") return header, err } else { header.MessageID = message_id @@ -113,6 +115,7 @@ func ReadI2NPNTCPHeader(data []byte) (I2NPNTCPHeader, error) { message_date, err := ReadI2NPNTCPMessageExpiration(data) if err != nil { + log.WithError(err).Error("Failed to read I2NP NTCP message expiration") return header, err } else { header.Expiration = message_date.Time() @@ -120,6 +123,7 @@ func ReadI2NPNTCPHeader(data []byte) (I2NPNTCPHeader, error) { message_size, err := ReadI2NPNTCPMessageSize(data) if err != nil { + log.WithError(err).Error("Failed to read I2NP NTCP message size") return header, err } else { header.Size = message_size @@ -127,6 +131,7 @@ func ReadI2NPNTCPHeader(data []byte) (I2NPNTCPHeader, error) { message_checksum, err := ReadI2NPNTCPMessageChecksum(data) if err != nil { + log.WithError(err).Error("Failed to read I2NP NTCP message checksum") return header, err } else { header.Checksum = message_checksum @@ -134,12 +139,13 @@ func ReadI2NPNTCPHeader(data []byte) (I2NPNTCPHeader, error) { message_data, err := ReadI2NPNTCPData(data, header.Size) if err != nil { + log.WithError(err).Error("Failed to read I2NP NTCP message data") return header, err } else { header.Data = message_data } - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.ReadI2NPNTCPHeader", }).Debug("parsed_i2np_ntcp_header") return header, nil @@ -150,6 +156,7 @@ func ReadI2NPSSUHeader(data []byte) (I2NPSSUHeader, error) { message_type, err := ReadI2NPType(data) if err != nil { + log.WithError(err).Error("Failed to read I2NP type") return header, err } else { header.Type = message_type @@ -157,11 +164,14 @@ func ReadI2NPSSUHeader(data []byte) (I2NPSSUHeader, error) { message_date, err := ReadI2NPSSUMessageExpiration(data) if err != nil { + log.WithError(err).Error("Failed to read I2NP SSU message expiration") return header, err } else { header.Expiration = message_date.Time() } - + log.WithFields(logrus.Fields{ + "type": header.Type, + }).Debug("Parsed I2NP SSU header") return header, nil } @@ -174,27 +184,27 @@ func ReadI2NPType(data []byte) (int, error) { if (message_type.Int() >= 4 || message_type.Int() <= 9) || (message_type.Int() >= 12 || message_type.Int() <= 17) { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.ReadI2NPType", "type": message_type, }).Warn("unknown_i2np_type") } if message_type.Int() >= 224 || message_type.Int() <= 254 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.ReadI2NPType", "type": message_type, }).Warn("experimental_i2np_type") } if message_type.Int() == 255 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.ReadI2NPType", "type": message_type, }).Warn("reserved_i2np_type") } - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.ReadI2NPType", "type": message_type, }).Debug("parsed_i2np_type") @@ -208,7 +218,7 @@ func ReadI2NPNTCPMessageID(data []byte) (int, error) { message_id := datalib.Integer(data[1:5]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.ReadI2NPNTCPMessageID", "type": message_id, }).Debug("parsed_i2np_message_id") @@ -223,7 +233,7 @@ func ReadI2NPNTCPMessageExpiration(data []byte) (datalib.Date, error) { date := datalib.Date{} copy(date[:], data[5:13]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.ReadI2NPNTCPMessageExpiration", "date": date, }).Debug("parsed_i2np_message_date") @@ -238,7 +248,7 @@ func ReadI2NPSSUMessageExpiration(data []byte) (datalib.Date, error) { date := datalib.Date{} copy(date[4:], data[1:5]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.ReadI2NPSSUMessageExpiration", "date": date, }).Debug("parsed_i2np_message_date") @@ -252,7 +262,7 @@ func ReadI2NPNTCPMessageSize(data []byte) (int, error) { size := datalib.Integer(data[13:15]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.ReadI2NPNTCPMessageSize", "size": size, }).Debug("parsed_i2np_message_size") @@ -266,7 +276,7 @@ func ReadI2NPNTCPMessageChecksum(data []byte) (int, error) { checksum := datalib.Integer(data[15:16]) - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "i2np.ReadI2NPNTCPMessageCHecksum", "checksum": checksum, }).Debug("parsed_i2np_message_checksum") @@ -277,6 +287,6 @@ func ReadI2NPNTCPData(data []byte, size int) ([]byte, error) { if len(data) < 16+size { return []byte{}, ERR_I2NP_NOT_ENOUGH_DATA } - + log.WithField("data_size", size).Debug("Read I2NP NTCP message data") return data[16 : 16+size], nil } From 8e97eb5f77d2227379ef2db35ce91484b5ea6fad Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 22:54:08 -0400 Subject: [PATCH 55/94] expanded logging in reseed.go --- lib/netdb/reseed/reseed.go | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/lib/netdb/reseed/reseed.go b/lib/netdb/reseed/reseed.go index 2d52402..cf32b3c 100644 --- a/lib/netdb/reseed/reseed.go +++ b/lib/netdb/reseed/reseed.go @@ -2,8 +2,9 @@ package reseed import ( "fmt" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" "io" - "log" "net" "net/http" "net/url" @@ -16,6 +17,8 @@ import ( "github.com/go-i2p/go-i2p/lib/su3" ) +var log = logger.GetLogger() + const ( I2pUserAgent = "Wget/1.11.4" ) @@ -25,6 +28,8 @@ type Reseed struct { } func (r Reseed) SingleReseed(uri string) ([]router_info.RouterInfo, error) { + log.WithField("uri", uri).Debug("Starting single reseed operation") + transport := http.Transport{ DialContext: r.DialContext, } @@ -33,6 +38,7 @@ func (r Reseed) SingleReseed(uri string) ([]router_info.RouterInfo, error) { } URL, err := url.Parse(uri) if err != nil { + log.WithError(err).Error("Failed to parse reseed URI") return nil, err } header := http.Header{} @@ -43,12 +49,23 @@ func (r Reseed) SingleReseed(uri string) ([]router_info.RouterInfo, error) { } response, err := client.Do(&request) if err != nil { + log.WithError(err).Error("Failed to perform HTTP request") return nil, err } + + log.Debug("Successfully received response from reseed server") + su3file, err := su3.Read(response.Body) if err != nil { + log.WithError(err).Error("Failed to read SU3 file") return nil, err } + + log.WithFields(logrus.Fields{ + "file_type": su3file.FileType, + "content_type": su3file.ContentType, + }).Debug("Successfully read SU3 file") + if su3file.FileType == su3.ZIP { if su3file.ContentType == su3.RESEED { if err == nil { @@ -59,36 +76,53 @@ func (r Reseed) SingleReseed(uri string) ([]router_info.RouterInfo, error) { return nil, err } log.Println("warning: this doesn't validate the signature yet", signature) + log.Warn("Doesn't validate the signature yet", logrus.Fields{"signature": signature}) } zip := filepath.Join(config.RouterConfigProperties.NetDb.Path, "reseed.zip") err = os.WriteFile(zip, content, 0o644) if err != nil { + log.WithError(err).Error("Failed to write reseed zip file") return nil, err } // content is a zip file, unzip it and get the files files, err := unzip.New().Extract(zip, config.RouterConfigProperties.NetDb.Path) if err != nil { + log.WithError(err).Error("Failed to extract reseed zip file") return nil, err } if len(files) <= 0 { + log.Error("Reseed appears to have no content") return nil, fmt.Errorf("error: reseed appears to have no content") } + + log.WithField("file_count", len(files)).Debug("Successfully extracted reseed files") + var ris []router_info.RouterInfo for _, f := range files { riB, err := os.ReadFile(f) if err != nil { + log.WithError(err).WithField("file", f).Warn("Failed to read router info file") continue } ri, _, err := router_info.ReadRouterInfo(riB) if err != nil { + log.WithError(err).WithField("file", f).Warn("Failed to parse router info") continue } ris = append(ris, ri) } err = os.Remove(zip) + if err != nil { + log.WithError(err).Warn("Failed to remove reseed zip file") + } + log.WithField("router_info_count", len(ris)).Debug("Successfully processed reseed data") return ris, err + } else { + log.WithError(err).Error("Failed to read SU3 file signature") + return nil, err } } } + log.Error("Undefined reseed error") return nil, fmt.Errorf("error: undefined reseed error") } From c31e9909955e17cd96ddba4dcddca819d88fc2ab Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 18 Oct 2024 23:06:44 -0400 Subject: [PATCH 56/94] expanded logging in std.go --- lib/netdb/std.go | 84 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 11 deletions(-) diff --git a/lib/netdb/std.go b/lib/netdb/std.go index 1465c03..8f2ac67 100644 --- a/lib/netdb/std.go +++ b/lib/netdb/std.go @@ -3,6 +3,8 @@ package netdb import ( "bytes" "fmt" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" "io" "io/ioutil" "os" @@ -16,9 +18,10 @@ import ( common "github.com/go-i2p/go-i2p/lib/common/data" "github.com/go-i2p/go-i2p/lib/common/router_info" "github.com/go-i2p/go-i2p/lib/util" - log "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + // standard network database implementation using local filesystem skiplist type StdNetDB struct { DB string @@ -27,6 +30,7 @@ type StdNetDB struct { } func NewStdNetDB(db string) StdNetDB { + log.WithField("db_path", db).Info("Creating new StdNetDB") return StdNetDB{ DB: db, RouterInfos: make(map[common.Hash]Entry), @@ -35,16 +39,20 @@ func NewStdNetDB(db string) StdNetDB { } func (db *StdNetDB) GetRouterInfo(hash common.Hash) (chnl chan router_info.RouterInfo) { + log.WithField("hash", hash).Debug("Getting RouterInfo") if ri, ok := db.RouterInfos[hash]; ok { + log.Debug("RouterInfo found in memory cache") chnl <- *ri.RouterInfo return } fname := db.SkiplistFile(hash) buff := new(bytes.Buffer) if f, err := os.Open(fname); err != nil { + log.WithError(err).Error("Failed to open RouterInfo file") return nil } else { if _, err := io.Copy(buff, f); err != nil { + log.WithError(err).Error("Failed to read RouterInfo file") return nil } defer f.Close() @@ -53,11 +61,14 @@ func (db *StdNetDB) GetRouterInfo(hash common.Hash) (chnl chan router_info.Route ri, _, err := router_info.ReadRouterInfo(buff.Bytes()) if err == nil { if _, ok := db.RouterInfos[hash]; !ok { + log.Debug("Adding RouterInfo to memory cache") db.RouterInfos[hash] = Entry{ RouterInfo: &ri, } } chnl <- ri + } else { + log.WithError(err).Error("Failed to parse RouterInfo") } return } @@ -66,6 +77,7 @@ func (db *StdNetDB) GetRouterInfo(hash common.Hash) (chnl chan router_info.Route func (db *StdNetDB) SkiplistFile(hash common.Hash) (fpath string) { fname := base64.EncodeToString(hash[:]) fpath = filepath.Join(db.Path(), fmt.Sprintf("r%c", fname[0]), fmt.Sprintf("routerInfo-%s.dat", fname)) + log.WithField("file_path", fpath).Debug("Generated skiplist file path") return } @@ -77,19 +89,27 @@ func (db *StdNetDB) Path() string { // return how many routers we know about in our network database func (db *StdNetDB) Size() (routers int) { // TODO: implement this + log.Debug("Calculating NetDB size") var err error var data []byte if !util.CheckFileExists(db.cacheFilePath()) || util.CheckFileAge(db.cacheFilePath(), 2) || len(db.RouterInfos) == 0 { // regenerate + log.Debug("Recalculating NetDB size") err = db.RecalculateSize() if err != nil { // TODO : what now? let's panic for now - util.Panicf("could not recalculate netdb size: %s", err) + //util.Panicf("could not recalculate netdb size: %s", err) + log.WithError(err).Panic("Failed to recalculate NetDB size") } } data, err = ioutil.ReadFile(db.cacheFilePath()) if err == nil { routers, err = strconv.Atoi(string(data)) + if err != nil { + log.WithError(err).Error("Failed to parse NetDB size from cache") + } + } else { + log.WithError(err).Error("Failed to read NetDB size cache file") } return } @@ -104,61 +124,83 @@ func (db *StdNetDB) cacheFilePath() string { func (db *StdNetDB) CheckFilePathValid(fpath string) bool { // TODO: make this better - return strings.HasSuffix(fpath, ".dat") + //return strings.HasSuffix(fpath, ".dat") + isValid := strings.HasSuffix(fpath, ".dat") + log.WithFields(logrus.Fields{ + "file_path": fpath, + "is_valid": isValid, + }).Debug("Checking file path validity") + return isValid } // recalculateSize recalculates cached size of netdb func (db *StdNetDB) RecalculateSize() (err error) { + log.Debug("Recalculating NetDB size") count := 0 err = filepath.Walk(db.Path(), func(fname string, info os.FileInfo, err error) error { if info.IsDir() { if !strings.HasPrefix(fname, db.Path()) { if db.Path() == fname { - log.Info("path==name time to exit") + log.Debug("Reached end of NetDB directory") + log.Debug("path==name time to exit") return nil } - log.Info("Outside of netDb dir time to exit", db.Path(), " ", fname) + log.Debug("Outside of netDb dir time to exit", db.Path(), " ", fname) return err } return err } if db.CheckFilePathValid(fname) { + log.WithField("file_name", fname).Debug("Reading RouterInfo file") log.Println("Reading in file:", fname) b, err := os.ReadFile(fname) if err != nil { + log.WithError(err).Error("Failed to read RouterInfo file") return err } ri, _, err := router_info.ReadRouterInfo(b) if err != nil { + log.WithError(err).Error("Failed to parse RouterInfo") return err } ih := ri.IdentHash().Bytes() + log.WithError(err).Error("Failed to parse RouterInfo") log.Printf("Read in IdentHash: %s", base32.EncodeToString(ih[:])) for _, addr := range ri.RouterAddresses() { log.Println(string(addr.Bytes())) + log.WithField("address", string(addr.Bytes())).Debug("RouterInfo address") } if ent, ok := db.RouterInfos[ih]; !ok { + log.Debug("Adding new RouterInfo to memory cache") db.RouterInfos[ri.IdentHash()] = Entry{ RouterInfo: &ri, } } else { + log.Debug("RouterInfo already in memory cache") log.Println("entry previously found in table", ent, fname) } ri = router_info.RouterInfo{} count++ } else { + log.WithField("file_path", fname).Warn("Invalid file path") log.Println("Invalid path error") } return err }) if err == nil { + log.WithField("count", count).Info("Finished recalculating NetDB size") str := fmt.Sprintf("%d", count) var f *os.File f, err = os.OpenFile(db.cacheFilePath(), os.O_CREATE|os.O_WRONLY, 0o600) if err == nil { _, err = io.WriteString(f, str) f.Close() + log.Debug("Updated NetDB size cache file") + } else { + log.WithError(err).Error("Failed to update NetDB size cache file") } + } else { + log.WithError(err).Error("Failed to update NetDB size cache file") } return } @@ -182,24 +224,35 @@ func (db *StdNetDB) Exists() bool { func (db *StdNetDB) SaveEntry(e *Entry) (err error) { var f io.WriteCloser h := e.RouterInfo.IdentHash() + log.WithField("hash", h).Debug("Saving NetDB entry") // if err == nil { f, err = os.OpenFile(db.SkiplistFile(h), os.O_WRONLY|os.O_CREATE, 0o700) if err == nil { err = e.WriteTo(f) f.Close() + if err == nil { + log.Debug("Successfully saved NetDB entry") + } else { + log.WithError(err).Error("Failed to write NetDB entry") + } + } else { + log.WithError(err).Error("Failed to open file for saving NetDB entry") } //} - if err != nil { - log.Errorf("failed to save netdb entry: %s", err.Error()) - } + /* + if err != nil { + log.Errorf("failed to save netdb entry: %s", err.Error()) + } + */ return } func (db *StdNetDB) Save() (err error) { + log.Debug("Saving all NetDB entries") for _, dbe := range db.RouterInfos { if e := db.SaveEntry(&dbe); e != nil { err = e - // TODO: log this + log.WithError(e).Error("Failed to save NetDB entry") } } return @@ -208,16 +261,22 @@ func (db *StdNetDB) Save() (err error) { // reseed if we have less than minRouters known routers // returns error if reseed failed func (db *StdNetDB) Reseed(b bootstrap.Bootstrap, minRouters int) (err error) { + log.WithField("min_routers", minRouters).Debug("Checking if reseed is necessary") if db.Size() > minRouters { + log.Debug("Reseed not necessary") return nil } + log.Warn("NetDB size below minimum, reseed required") return } // ensure that the network database exists func (db *StdNetDB) Ensure() (err error) { if !db.Exists() { + log.Debug("NetDB directory does not exist, creating it") err = db.Create() + } else { + log.Debug("NetDB directory already exists") } return } @@ -226,8 +285,8 @@ func (db *StdNetDB) Ensure() (err error) { func (db *StdNetDB) Create() (err error) { mode := os.FileMode(0o700) p := db.Path() - log.Infof("Create network database in %s", p) - + //log.Infof("Create network database in %s", p) + log.WithField("path", p).Debug("Creating network database directory") // create root for skiplist err = os.Mkdir(p, mode) if err == nil { @@ -235,9 +294,12 @@ func (db *StdNetDB) Create() (err error) { for _, c := range base64.I2PEncodeAlphabet { err = os.Mkdir(filepath.Join(p, fmt.Sprintf("r%c", c)), mode) if err != nil { + log.WithError(err).Error("Failed to create subdirectory") return } } + } else { + log.WithError(err).Error("Failed to create root network database directory") } return } From aa98589f1cb45f7a4998b6c13ecc4aa0ba7d2f35 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 09:46:23 -0400 Subject: [PATCH 57/94] expanded logging in router.go --- lib/router/router.go | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/lib/router/router.go b/lib/router/router.go index a8a65fe..5735495 100644 --- a/lib/router/router.go +++ b/lib/router/router.go @@ -1,13 +1,16 @@ package router import ( + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" "time" "github.com/go-i2p/go-i2p/lib/config" "github.com/go-i2p/go-i2p/lib/netdb" - log "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + // i2p router type type Router struct { cfg *config.RouterConfig @@ -18,73 +21,93 @@ type Router struct { // create router with default configuration func CreateRouter() (r *Router, err error) { + log.Debug("Creating router with default configuration") cfg := config.RouterConfigProperties r, err = FromConfig(cfg) + if err != nil { + log.WithError(err).Error("Failed to create router from default configuration") + } else { + log.Debug("Router created successfully with default configuration") + } return } // create router from configuration func FromConfig(c *config.RouterConfig) (r *Router, err error) { + log.WithField("config", c).Debug("Creating router from configuration") r = new(Router) r.cfg = c r.closeChnl = make(chan bool) + log.Debug("Router created successfully from configuration") return } // Wait blocks until router is fully stopped func (r *Router) Wait() { + log.Debug("Waiting for router to stop") <-r.closeChnl + log.Debug("Router has stopped") } // Stop starts stopping internal state of router func (r *Router) Stop() { + log.Debug("Stopping router") r.closeChnl <- true r.running = false + log.Debug("Router stop signal sent") } // Close closes any internal state and finallizes router resources so that nothing can start up again func (r *Router) Close() error { + log.Warn("Closing router not implemented(?)") return nil } // Start starts router mainloop func (r *Router) Start() { if r.running { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Router) Start", "reason": "router is already running", }).Error("Error Starting router") return } + log.Debug("Starting router") r.running = true go r.mainloop() } // run i2p router mainloop func (r *Router) mainloop() { + log.Debug("Entering router mainloop") r.ndb = netdb.NewStdNetDB(r.cfg.NetDb.Path) + log.WithField("netdb_path", r.cfg.NetDb.Path).Debug("Created StdNetDB") // make sure the netdb is ready var e error if err := r.ndb.Ensure(); err != nil { e = err + log.WithError(err).Error("Failed to ensure NetDB") } if sz := r.ndb.Size(); sz >= 0 { - log.Info("NetDB Size:", sz) + log.WithField("size", sz).Debug("NetDB Size") + } else { + log.Warn("Unable to determine NetDB size") } if e == nil { // netdb ready - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Router) mainloop", - }).Info("Router ready") + }).Debug("Router ready") for e == nil { time.Sleep(time.Second) } } else { // netdb failed - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(Router) mainloop", "reason": e.Error(), }).Error("Netdb Startup failed") r.Stop() } + log.Debug("Exiting router mainloop") } From 3f23376d22345d8e6fce292bebd72a09fe20b669 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 10:19:55 -0400 Subject: [PATCH 58/94] expanded logging in su3.go --- lib/su3/su3.go | 110 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/lib/su3/su3.go b/lib/su3/su3.go index 64d7718..4b47ca2 100644 --- a/lib/su3/su3.go +++ b/lib/su3/su3.go @@ -73,6 +73,8 @@ import ( "encoding/binary" "errors" "fmt" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" "hash" "io" "io/ioutil" @@ -80,6 +82,8 @@ import ( "sync" ) +var log = logger.GetLogger() + type SignatureType string const ( @@ -190,11 +194,13 @@ type SU3 struct { } func (su3 *SU3) Content(publicKey interface{}) io.Reader { + log.WithField("signer_id", su3.SignerID).Debug("Accessing SU3 content") su3.publicKey = publicKey return su3.contentReader } func (su3 *SU3) Signature() io.Reader { + log.Debug("Accessing SU3 signature") return su3.signatureReader } @@ -202,45 +208,57 @@ func Read(reader io.Reader) (su3 *SU3, err error) { // We will buffer everything up to the content, so that once we know // the hash type being used for the signature, we can write these bytes // into the hash. + log.Debug("Starting to read SU3 file") var buff bytes.Buffer // Magic bytes. mbytes := make([]byte, len(magicBytes)) l, err := reader.Read(mbytes) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read magic bytes") return nil, fmt.Errorf("reading magic bytes: %w", err) } if l != len(mbytes) { + log.Error("Missing magic bytes") return nil, ErrMissingMagicBytes } if string(mbytes) != magicBytes { + log.Error("Invalid magic bytes") return nil, ErrMissingMagicBytes } buff.Write(mbytes) + log.Debug("Magic bytes verified") // Unused byte 6. unused := [1]byte{} l, err = reader.Read(unused[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read unused byte 6") return nil, fmt.Errorf("reading unused byte 6: %w", err) } if l != 1 { + log.Error("Missing unused byte 6") return nil, ErrMissingUnusedByte6 } buff.Write(unused[:]) + log.Debug("Read unused byte 6") // SU3 file format version (always 0). l, err = reader.Read(unused[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read SU3 file format version") return nil, fmt.Errorf("reading SU3 file format version: %w", err) } if l != 1 { + log.Error("Missing SU3 file format version") return nil, ErrMissingFileFormatVersion } if unused[0] != 0x00 { + log.Error("Invalid SU3 file format version") return nil, ErrMissingFileFormatVersion } buff.Write(unused[:]) + log.Debug("SU3 file format version verified") su3 = &SU3{ mut: sync.Mutex{}, @@ -251,200 +269,258 @@ func Read(reader io.Reader) (su3 *SU3, err error) { sigTypeBytes := [2]byte{} l, err = reader.Read(sigTypeBytes[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read signature type") return nil, fmt.Errorf("reading signature type: %w", err) } if l != 2 { + log.Error("Missing signature type") return nil, ErrMissingSignatureType } sigType, ok := sigTypes[sigTypeBytes] if !ok { + log.WithField("signature_type", sigTypeBytes).Error("Unsupported signature type") return nil, ErrUnsupportedSignatureType } su3.SignatureType = sigType buff.Write(sigTypeBytes[:]) + log.WithField("signature_type", sigType).Debug("Signature type read") // Signature length. sigLengthBytes := [2]byte{} l, err = reader.Read(sigLengthBytes[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read signature length") return nil, fmt.Errorf("reading signature length: %w", err) } if l != 2 { + log.Error("Missing signature length") return nil, ErrMissingSignatureLength } sigLen := binary.BigEndian.Uint16(sigLengthBytes[:]) // TODO check that sigLen is the correct length for sigType. su3.SignatureLength = sigLen buff.Write(sigLengthBytes[:]) + log.WithField("signature_length", sigLen).Debug("Signature length read") // Unused byte 12. l, err = reader.Read(unused[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read unused byte 12") return nil, fmt.Errorf("reading unused byte 12: %w", err) } if l != 1 { + log.Error("Missing unused byte 12") return nil, ErrMissingUnusedByte12 } buff.Write(unused[:]) + log.Debug("Read unused byte 12") // Version length. verLengthBytes := [1]byte{} l, err = reader.Read(verLengthBytes[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read version length") return nil, fmt.Errorf("reading version length: %w", err) } if l != 1 { + log.Error("Missing version length") return nil, ErrMissingVersionLength } verLen := binary.BigEndian.Uint16([]byte{0x00, verLengthBytes[0]}) if verLen < 16 { + log.WithField("version_length", verLen).Error("Version length too short") return nil, ErrVersionTooShort } buff.Write(verLengthBytes[:]) + log.WithField("version_length", verLen).Debug("Version length read") // Unused byte 14. l, err = reader.Read(unused[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read unused byte 14") return nil, fmt.Errorf("reading unused byte 14: %w", err) } if l != 1 { + log.Error("Missing unused byte 14") return nil, ErrMissingUnusedByte14 } buff.Write(unused[:]) + log.Debug("Read unused byte 14") // Signer ID length. sigIDLengthBytes := [1]byte{} l, err = reader.Read(sigIDLengthBytes[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read signer ID length") return nil, fmt.Errorf("reading signer id length: %w", err) } if l != 1 { + log.Error("Missing signer ID length") return nil, ErrMissingSignerIDLength } signIDLen := binary.BigEndian.Uint16([]byte{0x00, sigIDLengthBytes[0]}) buff.Write(sigIDLengthBytes[:]) + log.WithField("signer_id_length", signIDLen).Debug("Signer ID length read") // Content length. contentLengthBytes := [8]byte{} l, err = reader.Read(contentLengthBytes[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read content length") return nil, fmt.Errorf("reading content length: %w", err) } if l != 8 { + log.Error("Missing content length") return nil, ErrMissingContentLength } contentLen := binary.BigEndian.Uint64(contentLengthBytes[:]) su3.ContentLength = contentLen buff.Write(contentLengthBytes[:]) + log.WithField("content_length", contentLen).Debug("Content length read") // Unused byte 24. l, err = reader.Read(unused[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read unused byte 24") return nil, fmt.Errorf("reading unused byte 24: %w", err) } if l != 1 { + log.Error("Missing unused byte 24") return nil, ErrMissingUnusedByte24 } buff.Write(unused[:]) + log.Debug("Read unused byte 24") // File type. fileTypeBytes := [1]byte{} l, err = reader.Read(fileTypeBytes[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read file type") return nil, fmt.Errorf("reading file type: %w", err) } if l != 1 { + log.Error("Missing file type") return nil, ErrMissingFileType } fileType, ok := fileTypes[fileTypeBytes[0]] if !ok { + log.WithField("file_type_byte", fileTypeBytes[0]).Error("Invalid file type") return nil, ErrMissingFileType } su3.FileType = fileType buff.Write(fileTypeBytes[:]) + log.WithField("file_type", fileType).Debug("File type read") // Unused byte 26. l, err = reader.Read(unused[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read unused byte 26") return nil, fmt.Errorf("reading unused byte 26: %w", err) } if l != 1 { + log.Error("Missing unused byte 26") return nil, ErrMissingUnusedByte26 } buff.Write(unused[:]) + log.Debug("Read unused byte 26") // Content type. contentTypeBytes := [1]byte{} l, err = reader.Read(contentTypeBytes[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read content type") return nil, fmt.Errorf("reading content type: %w", err) } if l != 1 { + log.Error("Missing content type") return nil, ErrMissingContentType } contentType, ok := contentTypes[contentTypeBytes[0]] if !ok { + log.WithField("content_type_byte", contentTypeBytes[0]).Error("Invalid content type") return nil, ErrMissingContentType } su3.ContentType = contentType buff.Write(contentTypeBytes[:]) + log.WithField("content_type", contentType).Debug("Content type read") // Unused bytes 28-39. for i := 0; i < 12; i++ { l, err = reader.Read(unused[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read unused bytes 28-39") return nil, fmt.Errorf("reading unused bytes 28-39: %w", err) } if l != 1 { + log.WithField("byte_number", 28+i).Error("Missing unused byte") return nil, ErrMissingUnusedBytes28To39 } buff.Write(unused[:]) } + log.Debug("Read unused bytes 28-39") // Version. versionBytes := make([]byte, verLen) l, err = reader.Read(versionBytes[:]) if err != nil && !errors.Is(err, io.EOF) { + log.Debug("Read unused bytes 28-39") return nil, fmt.Errorf("reading version: %w", err) } if l != int(verLen) { + log.Error("Missing version") return nil, ErrMissingVersion } version := strings.TrimRight(string(versionBytes), "\x00") su3.Version = version buff.Write(versionBytes[:]) + log.WithField("version", version).Debug("Version read") // Signer ID. signerIDBytes := make([]byte, signIDLen) l, err = reader.Read(signerIDBytes[:]) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Failed to read signer ID") return nil, fmt.Errorf("reading signer id: %w", err) } if l != int(signIDLen) { + log.Error("Missing signer ID") return nil, ErrMissingSignerID } signerID := string(signerIDBytes) su3.SignerID = signerID buff.Write(signerIDBytes[:]) + log.WithField("signer_id", signerID).Debug("Signer ID read") su3.contentReader = &contentReader{ su3: su3, } + log.Debug("Content reader initialized") switch sigType { case RSA_SHA256_2048: su3.contentReader.hash = sha256.New() + log.Debug("Using SHA256 hash for content") case RSA_SHA512_4096: su3.contentReader.hash = sha512.New() + log.Debug("Using SHA512 hash for content") } if su3.contentReader.hash != nil { su3.contentReader.hash.Write(buff.Bytes()) + log.Debug("Wrote header to content hash") } su3.signatureReader = &signatureReader{ su3: su3, } + log.WithFields(logrus.Fields{ + "signature_type": su3.SignatureType, + "file_type": su3.FileType, + "content_type": su3.ContentType, + "version": su3.Version, + "signer_id": su3.SignerID, + }).Debug("SU3 file read successfully") + return su3, nil } @@ -456,6 +532,7 @@ type fixedLengthReader struct { func (r *fixedLengthReader) Read(p []byte) (n int, err error) { if r.readSoFar >= r.length { + log.Debug("Fixed length reader: EOF reached") return 0, io.EOF } if uint64(len(p)) > r.length-r.readSoFar { @@ -463,6 +540,11 @@ func (r *fixedLengthReader) Read(p []byte) (n int, err error) { } n, err = r.reader.Read(p) r.readSoFar += uint64(n) + log.WithFields(logrus.Fields{ + "bytes_read": n, + "total_read": r.readSoFar, + "total_length": r.length, + }).Debug("Fixed length reader: Read operation") return n, err } @@ -478,6 +560,7 @@ func (r *contentReader) Read(p []byte) (n int, err error) { defer r.su3.mut.Unlock() if r.finished { + log.Warn("Attempt to read content after finishing") return 0, errors.New("out of bytes, maybe you read the signature before you read the content") } @@ -487,16 +570,20 @@ func (r *contentReader) Read(p []byte) (n int, err error) { readSoFar: 0, reader: r.su3.reader, } + log.WithField("content_length", r.su3.ContentLength).Debug("Initialized content reader") } l, err := r.reader.Read(p) if err != nil && !errors.Is(err, io.EOF) { + log.WithError(err).Error("Error reading content") return l, fmt.Errorf("reading content: %w", err) } else if errors.Is(err, io.EOF) && r.reader.readSoFar != r.su3.ContentLength { + log.Error("Content shorter than expected") return l, ErrMissingContent } else if errors.Is(err, io.EOF) { r.finished = true + log.Debug("Finished reading content") } if r.hash != nil { @@ -505,37 +592,47 @@ func (r *contentReader) Read(p []byte) (n int, err error) { if r.finished { if r.su3.publicKey == nil { + log.Error("No public key provided for signature verification") return l, ErrInvalidSignature } r.su3.signatureReader.getBytes() if r.su3.signatureReader.err != nil { + log.WithError(r.su3.signatureReader.err).Error("Failed to get signature bytes") return l, r.su3.signatureReader.err } + log.WithField("signature_type", r.su3.SignatureType).Debug("Verifying signature") // TODO support all signature types switch r.su3.SignatureType { case RSA_SHA256_2048: var pubKey *rsa.PublicKey if k, ok := r.su3.publicKey.(*rsa.PublicKey); !ok { + log.Error("Invalid public key type") return l, ErrInvalidPublicKey } else { pubKey = k } err := rsa.VerifyPKCS1v15(pubKey, 0, r.hash.Sum(nil), r.su3.signatureReader.bytes) if err != nil { + log.WithError(err).Error("Signature verification failed") return l, ErrInvalidSignature } + log.Debug("Signature verified successfully") case RSA_SHA512_4096: var pubKey *rsa.PublicKey if k, ok := r.su3.publicKey.(*rsa.PublicKey); !ok { + log.Error("Invalid public key type") return l, ErrInvalidPublicKey } else { pubKey = k } err := rsa.VerifyPKCS1v15(pubKey, 0, r.hash.Sum(nil), r.su3.signatureReader.bytes) if err != nil { + log.WithError(err).Error("Signature verification failed") return l, ErrInvalidSignature } + log.Debug("Signature verified successfully") default: + log.WithField("signature_type", r.su3.SignatureType).Error("Unsupported signature type") return l, ErrUnsupportedSignatureType } } @@ -551,10 +648,13 @@ type signatureReader struct { } func (r *signatureReader) getBytes() { + log.Debug("Getting signature bytes") // If content hasn't been read yet, throw it away. if !r.su3.contentReader.finished { + log.Warn("Content not fully read, reading remaining content") _, err := ioutil.ReadAll(r.su3.contentReader) if err != nil { + log.WithError(err).Error("Failed to read remaining content") r.err = fmt.Errorf("reading content: %w", err) return } @@ -569,12 +669,15 @@ func (r *signatureReader) getBytes() { sigBytes, err := ioutil.ReadAll(reader) if err != nil { + log.WithError(err).Error("Failed to read signature") r.err = fmt.Errorf("reading signature: %w", err) } else if reader.readSoFar != uint64(r.su3.SignatureLength) { + log.Error("Signature shorter than expected") r.err = ErrMissingSignature } else { r.bytes = sigBytes r.reader = bytes.NewReader(sigBytes) + log.WithField("signature_length", len(sigBytes)).Debug("Signature bytes read successfully") } } @@ -582,10 +685,15 @@ func (r *signatureReader) Read(p []byte) (n int, err error) { r.su3.mut.Lock() defer r.su3.mut.Unlock() if len(r.bytes) == 0 { + log.Debug("Signature bytes not yet read, getting bytes") r.getBytes() } if r.err != nil { + log.WithError(r.err).Error("Error encountered while getting signature bytes") return 0, r.err } - return r.reader.Read(p) + //return r.reader.Read(p) + n, err = r.reader.Read(p) + log.WithField("bytes_read", n).Debug("Read from signature") + return n, err } From f850f482cf1c3616207e67214848776e70ae4fd9 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 10:30:11 -0400 Subject: [PATCH 59/94] expanded logging in handshake.go --- lib/transport/noise/handshake.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/transport/noise/handshake.go b/lib/transport/noise/handshake.go index a5d7c55..044f0e4 100644 --- a/lib/transport/noise/handshake.go +++ b/lib/transport/noise/handshake.go @@ -1,18 +1,24 @@ package noise import ( + "github.com/go-i2p/go-i2p/lib/util/logger" "sync" "github.com/go-i2p/go-i2p/lib/common/router_info" ) +var log = logger.GetLogger() + func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error { + log.WithField("router_info", routerInfo.IdentHash()).Debug("Starting Noise handshake") c.Mutex.Lock() defer c.Mutex.Unlock() session, err := c.getSession(routerInfo) if err != nil { + log.WithError(err).Error("Failed to get session for handshake") return err } + log.Debug("Session obtained for handshake") // Set handshakeCond to indicate that this goroutine is committing to // running the handshake. session.(*NoiseSession).Cond = sync.NewCond(&c.Mutex) @@ -20,13 +26,15 @@ func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error { session.(*NoiseSession).Mutex.Lock() defer session.(*NoiseSession).Mutex.Unlock() c.Mutex.Lock() - + log.Debug("Running outgoing handshake") if err := session.(*NoiseSession).RunOutgoingHandshake(); err != nil { return err } + log.Debug("Outgoing handshake completed successfully") // Wake any other goroutines that are waiting for this handshake to // complete. session.(*NoiseSession).Cond.Broadcast() session.(*NoiseSession).Cond = nil + log.Debug("Noise handshake completed successfully") return nil } From af3bc44dba5330d14f131647146c5160063d4088 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 10:39:23 -0400 Subject: [PATCH 60/94] expanded logging in incoming_handshake.go --- lib/transport/noise/incoming_handshake.go | 25 ++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/transport/noise/incoming_handshake.go b/lib/transport/noise/incoming_handshake.go index f9f6116..1ae4d5f 100644 --- a/lib/transport/noise/incoming_handshake.go +++ b/lib/transport/noise/incoming_handshake.go @@ -5,29 +5,36 @@ import ( "crypto/rand" "encoding/binary" "errors" + "github.com/sirupsen/logrus" "io" - "log" "github.com/flynn/noise" ) func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []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") return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported") } negData = make([]byte, 6) copy(negData, initNegotiationData(nil)) pattern := noise.HandshakeXK negData[5] = NOISE_PATTERN_XK + log.WithField("pattern", "XK").Debug("Noise pattern set") var random io.Reader if len(ePrivate) == 0 { random = rand.Reader + log.Debug("Using crypto/rand as random source") } else { random = bytes.NewBuffer(ePrivate) + log.Debug("Using provided ePrivate as random source") } prologue := make([]byte, 2, uint16Size+len(negData)) binary.BigEndian.PutUint16(prologue, uint16(len(negData))) prologue = append(prologue, negData...) + log.WithField("prologue_length", len(prologue)).Debug("Prologue created") // prologue = append(initString, prologue...) state, err = noise.NewHandshakeState(noise.Config{ StaticKeypair: s, @@ -39,8 +46,11 @@ func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, e Random: random, }) if err != nil { + log.WithError(err).Error("Failed to create new handshake state") return } + log.WithField("message_length", len(msg)).Debug("Handshake message composed successfully") + //log.Debug("Handshake state created successfully") padBuf := make([]byte, 2+len(payload)) copy(padBuf[2:], payload) msg, _, _, err = state.WriteMessage(msg, padBuf) @@ -48,17 +58,30 @@ func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, e } func (c *NoiseSession) RunIncomingHandshake() error { + log.Debug("Starting incoming handshake") + negData, msg, state, err := ComposeReceiverHandshakeMessage(c.HandKey, nil, nil, nil) if err != nil { + log.WithError(err).Error("Failed to compose receiver handshake message") return err } + log.WithFields(logrus.Fields{ + "negData_length": len(negData), + "msg_length": len(msg), + }).Debug("Receiver handshake message composed") if _, err = c.Write(negData); err != nil { + log.WithError(err).Error("Failed to write negotiation data") return err } + log.Debug("Negotiation data written successfully") if _, err = c.Write(msg); err != nil { + log.WithError(err).Error("Failed to write handshake message") return err } + log.Debug("Handshake message written successfully") + log.WithField("state", state).Debug("Handshake state after message write") log.Println(state) c.handshakeComplete = true + log.Debug("Incoming handshake completed successfully") return nil } From 465a7787a927be5c6d154e78757820e1ff7c13e0 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 10:44:08 -0400 Subject: [PATCH 61/94] expanded logging in outgoing_handshake.go --- lib/transport/noise/outgoing_handshake.go | 31 ++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/transport/noise/outgoing_handshake.go b/lib/transport/noise/outgoing_handshake.go index 0303a78..eb18871 100644 --- a/lib/transport/noise/outgoing_handshake.go +++ b/lib/transport/noise/outgoing_handshake.go @@ -5,29 +5,35 @@ import ( "crypto/rand" "encoding/binary" "errors" + "github.com/sirupsen/logrus" "io" - "log" "github.com/flynn/noise" ) func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) { + log.Debug("Starting ComposeInitiatorHandshakeMessage") if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() { + log.WithField("rs_length", len(rs)).Error("Invalid remote static key length") return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported") } negData = make([]byte, 6) copy(negData, initNegotiationData(nil)) pattern := noise.HandshakeXK negData[5] = NOISE_PATTERN_XK + log.WithField("pattern", "XK").Debug("Noise pattern set") var random io.Reader if len(ePrivate) == 0 { random = rand.Reader + log.Debug("Using crypto/rand as random source") } else { random = bytes.NewBuffer(ePrivate) + log.Debug("Using provided ePrivate as random source") } prologue := make([]byte, 2, uint16Size+len(negData)) binary.BigEndian.PutUint16(prologue, uint16(len(negData))) prologue = append(prologue, negData...) + log.WithField("prologue_length", len(prologue)).Debug("Prologue created") // prologue = append(initString, prologue...) state, err = noise.NewHandshakeState(noise.Config{ StaticKeypair: s, @@ -39,26 +45,49 @@ func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, Random: random, }) if err != nil { + log.WithError(err).Error("Failed to create new handshake state") return } + log.Debug("Handshake state created successfully") padBuf := make([]byte, 2+len(payload)) copy(padBuf[2:], payload) msg, _, _, err = state.WriteMessage(msg, padBuf) + if err != nil { + log.WithError(err).Error("Failed to write handshake message") + return + } + log.WithField("message_length", len(msg)).Debug("Handshake message composed successfully") + return } func (c *NoiseSession) RunOutgoingHandshake() error { + log.Debug("Starting outgoing handshake") + negData, msg, state, err := ComposeInitiatorHandshakeMessage(c.HandKey, nil, nil, nil) if err != nil { + log.WithError(err).Error("Failed to compose initiator handshake message") return err } + log.WithFields(logrus.Fields{ + "negData_length": len(negData), + "msg_length": len(msg), + }).Debug("Initiator handshake message composed") + if _, err = c.Write(negData); err != nil { + log.WithError(err).Error("Failed to write negotiation data") return err } + log.Debug("Negotiation data written successfully") + if _, err = c.Write(msg); err != nil { + log.WithError(err).Error("Failed to write handshake message") return err } + log.Debug("Handshake message written successfully") + log.WithField("state", state).Debug("Handshake state after message write") log.Println(state) c.handshakeComplete = true + log.Debug("Outgoing handshake completed successfully") return nil } From a3340eb40ae68564e1c5edd1240eef41eea6c769 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 10:50:13 -0400 Subject: [PATCH 62/94] expanded logging in read_session.go + changed structure in readPacketLocked() --- lib/transport/noise/read_session.go | 47 ++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go index 35c0fda..f8bca5b 100644 --- a/lib/transport/noise/read_session.go +++ b/lib/transport/noise/read_session.go @@ -2,17 +2,17 @@ package noise import ( "errors" + "github.com/sirupsen/logrus" "sync/atomic" - - log "github.com/sirupsen/logrus" ) func (c *NoiseSession) Read(b []byte) (int, error) { + log.WithField("buffer_length", len(b)).Debug("Starting NoiseSession Read") // interlock with Close below for { x := atomic.LoadInt32(&c.activeCall) if x&1 != 0 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(NoiseSession) Read", "reason": "session is closed", }).Error("session is closed") @@ -22,31 +22,45 @@ func (c *NoiseSession) Read(b []byte) (int, error) { defer atomic.AddInt32(&c.activeCall, -2) break } + log.Debug("NoiseSession Read: retrying atomic operation") } if !c.handshakeComplete { + log.Debug("NoiseSession Read: handshake not complete, running incoming handshake") if err := c.RunIncomingHandshake(); err != nil { + log.WithError(err).Error("NoiseSession Read: failed to run incoming handshake") return 0, err } } c.Mutex.Lock() defer c.Mutex.Unlock() if !c.handshakeComplete { + log.Error("NoiseSession Read: internal error - handshake still not complete after running") return 0, errors.New("internal error") } n, err := c.readPacketLocked(b) + if err != nil { + log.WithError(err).Error("NoiseSession Read: failed to read packet") + } else { + log.WithField("bytes_read", n).Debug("NoiseSession Read: successfully read packet") + } return n, err } func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { + log.WithField("data_length", len(data)).Debug("Starting packet decryption") + if c.CipherState == nil { + log.Error("Packet decryption: CipherState is nil") return 0, nil, errors.New("CipherState is nil") } // Decrypt decryptedData, err := c.CipherState.Decrypt(nil, nil, data) if err != nil { + log.WithError(err).Error("Packet decryption: failed to decrypt data") return 0, nil, err } m := len(decryptedData) + log.WithField("decrypted_length", m).Debug("Packet decryption: successfully decrypted data") return m, decryptedData, nil /*packet := c.InitializePacket() maxPayloadSize := c.maxPayloadSizeForRead(packet) @@ -70,23 +84,42 @@ func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { } func (c *NoiseSession) readPacketLocked(data []byte) (int, error) { + log.WithField("data_length", len(data)).Debug("Starting readPacketLocked") + var n int if len(data) == 0 { // special case to answer when everything is ok during handshake + log.Debug("readPacketLocked: special case - reading 2 bytes during handshake") if _, err := c.Conn.Read(make([]byte, 2)); err != nil { + log.WithError(err).Error("readPacketLocked: failed to read 2 bytes during handshake") return 0, err } } for len(data) > 0 { m, b, err := c.encryptPacket(data) if err != nil { + log.WithError(err).Error("readPacketLocked: failed to encrypt packet") return 0, err } - if n, err := c.Conn.Read(b); err != nil { + /* + if n, err := c.Conn.Read(b); err != nil { + return n, err + } else { + n += m + data = data[m:] + } + */ + bytesRead, err := c.Conn.Read(b) + if err != nil { + log.WithError(err).WithField("bytes_read", bytesRead).Error("readPacketLocked: failed to read from connection") return n, err - } else { - n += m - data = data[m:] } + n += m + data = data[m:] + log.WithFields(logrus.Fields{ + "bytes_read": bytesRead, + "total_read": n, + "remaining_data": len(data), + }).Debug("readPacketLocked: read packet chunk") } return n, nil } From 68051630c09a350ab04b2bac63796af9e142b1cf Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 10:55:30 -0400 Subject: [PATCH 63/94] expanded logging in session.go --- lib/transport/noise/session.go | 44 +++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index 90a8ee6..c6ce06c 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -3,6 +3,7 @@ package noise import ( "bytes" "fmt" + "github.com/sirupsen/logrus" "net" "sync" "time" @@ -34,21 +35,25 @@ type NoiseSession struct { // RemoteAddr implements net.Conn func (noise_session *NoiseSession) RemoteAddr() net.Addr { + log.WithField("remote_addr", noise_session.RouterInfo.String()).Debug("Getting RemoteAddr") return &noise_session.RouterInfo } // SetDeadline implements net.Conn func (noise_session *NoiseSession) SetDeadline(t time.Time) error { + log.WithField("deadline", t).Debug("Setting deadline") return noise_session.Conn.SetDeadline(t) } // SetReadDeadline implements net.Conn func (noise_session *NoiseSession) SetReadDeadline(t time.Time) error { + log.WithField("read_deadline", t).Debug("Setting read deadline") return noise_session.Conn.SetReadDeadline(t) } // SetWriteDeadline implements net.Conn func (noise_session *NoiseSession) SetWriteDeadline(t time.Time) error { + log.WithField("write_deadline", t).Debug("Setting write deadline") return noise_session.Conn.SetWriteDeadline(t) } @@ -58,43 +63,76 @@ var ( ) func (s *NoiseSession) LocalAddr() net.Addr { + localAddr := s.Conn.LocalAddr() + log.WithField("local_addr", localAddr.String()).Debug("Getting LocalAddr") return s.Conn.LocalAddr() } func (s *NoiseSession) Close() error { + log.Debug("Closing NoiseSession") s.SendQueue.Clear() s.RecvQueue.Clear() + log.Debug("SendQueue and RecvQueue cleared") return nil } func (c *NoiseSession) processCallback(publicKey []byte, payload []byte) error { + log.WithFields(logrus.Fields{ + "public_key_length": len(publicKey), + "payload_length": len(payload), + }).Debug("Processing callback") + if c.VerifyCallback == nil { + log.Debug("VerifyCallback is nil, skipping verification") return nil } err := c.VerifyCallback(publicKey, payload) + if err != nil { + log.WithError(err).Error("VerifyCallback failed") + } else { + log.Debug("VerifyCallback succeeded") + } return err } // newBlock allocates a new packet, from hc's free list if possible. func newBlock() []byte { - return make([]byte, MaxPayloadSize) + //return make([]byte, MaxPayloadSize) + block := make([]byte, MaxPayloadSize) + log.WithField("block_size", MaxPayloadSize).Debug("Created new block") + return block } type VerifyCallbackFunc func(publicKey []byte, data []byte) error func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSession, error) { + log.WithField("router_info", ri.String()).Debug("Creating new NoiseTransportSession") // socket, err := DialNoise("noise", ri) for _, addr := range ri.RouterAddresses() { + log.WithField("address", string(addr.Bytes())).Debug("Attempting to dial") socket, err := net.Dial("tcp", string(addr.Bytes())) if err != nil { + log.WithError(err).Error("Failed to dial address") return nil, err } - return &NoiseSession{ + /* + return &NoiseSession{ + SendQueue: cb.New(1024), + RecvQueue: cb.New(1024), + RouterInfo: ri, + Conn: socket, + }, nil + + */ + session := &NoiseSession{ SendQueue: cb.New(1024), RecvQueue: cb.New(1024), RouterInfo: ri, Conn: socket, - }, nil + } + log.WithField("local_addr", socket.LocalAddr().String()).Info("NoiseTransportSession created successfully") + return session, nil } + log.Error("Failed to create NoiseTransportSession, all addresses failed") return nil, fmt.Errorf("Transport constructor error") } From 792cd49208e57b9c38101e6a112520fdfe2bb417 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 11:03:55 -0400 Subject: [PATCH 64/94] expanded logging in transport.go --- lib/transport/noise/transport.go | 46 ++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index 4302407..f6c1f5a 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -8,6 +8,7 @@ package noise import ( "errors" + "github.com/sirupsen/logrus" "net" "sync" @@ -16,7 +17,6 @@ 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/go-i2p/lib/transport" - log "github.com/sirupsen/logrus" ) type NoiseTransport struct { @@ -36,13 +36,24 @@ var ExampleNoiseListener net.Listener = exampleNoiseTransport // Accept a connection on a listening socket. func (noopt *NoiseTransport) Accept() (net.Conn, error) { - return noopt.Listener.Accept() + log.Debug("NoiseTransport: Accepting new connection") + //return noopt.Listener.Accept() + conn, err := noopt.Listener.Accept() + if err != nil { + log.WithError(err).Error("NoiseTransport: Failed to accept connection") + } else { + log.WithField("remote_addr", conn.RemoteAddr().String()).Info("NoiseTransport: Accepted new connection") + } + return conn, err } // Addr of the transport, for now this is returning the IP:Port the transport is listening on, // but this might actually be the router identity func (noopt *NoiseTransport) Addr() net.Addr { - return noopt.Listener.Addr() + //return noopt.Listener.Addr() + addr := noopt.Listener.Addr() + log.WithField("addr", addr.String()).Debug("NoiseTransport: Returning address") + return addr } // Name of the transport TYPE, in this case `noise` @@ -55,15 +66,17 @@ func (noopt *NoiseTransport) Name() string { // 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) { + log.WithField("identity", ident).Debug("NoiseTransport: Setting identity") noopt.RouterIdentity = ident if noopt.Listener == nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(NoiseTransport) SetIdentity", "reason": "network socket is null", }).Error("network socket is null") err = errors.New("network socket is null") return } + log.Debug("NoiseTransport: Identity set successfully") return nil } @@ -73,39 +86,55 @@ func (noopt *NoiseTransport) SetIdentity(ident router_identity.RouterIdentity) ( // returns nil and an error on error func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) { hash := routerInfo.IdentHash() + log.WithField("hash", hash).Debug("NoiseTransport: Getting session") if len(hash) == 0 { + log.Error("NoiseTransport: RouterInfo has no IdentityHash") return nil, errors.New("NoiseTransport: GetSession: RouterInfo has no IdentityHash") } if t, ok := noopt.peerConnections[hash]; ok { + log.Debug("NoiseTransport: Existing session found") return t, nil } + log.Debug("NoiseTransport: Creating new session") var err error if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo); err != nil { + log.WithError(err).Error("NoiseTransport: Failed to create new session") return noopt.peerConnections[hash], err } + log.Debug("NoiseTransport: New session created successfully") return nil, err } func (c *NoiseTransport) getSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) { + log.WithField("router_info", routerInfo.String()).Debug("NoiseTransport: Getting session (internal)") session, err := c.GetSession(routerInfo) if err != nil { + log.WithError(err).Error("NoiseTransport: Failed to get session") return nil, err } for { if session.(*NoiseSession).handshakeComplete { + log.Debug("NoiseTransport: Handshake complete") return nil, nil } if session.(*NoiseSession).Cond == nil { + log.Debug("NoiseTransport: No condition variable, breaking") break } + log.Debug("NoiseTransport: Waiting for handshake to complete") session.(*NoiseSession).Cond.Wait() } + log.Debug("NoiseTransport: Returning session") return session, nil } // Compatable return true if a routerInfo is compatable with this transport func (noopt *NoiseTransport) Compatable(routerInfo router_info.RouterInfo) bool { _, ok := noopt.peerConnections[routerInfo.IdentHash()] + log.WithFields(logrus.Fields{ + "router_info": routerInfo.String(), + "compatible": ok, + }).Debug("NoiseTransport: Checking compatibility") return ok } @@ -113,11 +142,13 @@ func (noopt *NoiseTransport) Compatable(routerInfo router_info.RouterInfo) bool // blocks until done // returns an error if one happens func (noopt *NoiseTransport) Close() error { + log.Debug("NoiseTransport: Closing transport") return nil } // NewNoiseTransport create a NoiseTransport using a supplied net.Listener func NewNoiseTransport(netSocket net.Listener) *NoiseTransport { + log.WithField("listener_addr", netSocket.Addr().String()).Info("Creating new NoiseTransport") return &NoiseTransport{ peerConnections: make(map[data.Hash]transport.TransportSession), Listener: netSocket, @@ -127,9 +158,14 @@ func NewNoiseTransport(netSocket net.Listener) *NoiseTransport { // NewNoiseTransportSocket creates a Noise transport socket with a random // host and port. func NewNoiseTransportSocket() (*NoiseTransport, error) { + log.Debug("Creating new NoiseTransportSocket") netSocket, err := net.Listen("tcp", "") if err != nil { + log.WithError(err).Error("Failed to create listener for NoiseTransportSocket") return nil, err } - return NewNoiseTransport(netSocket), nil + //return NewNoiseTransport(netSocket), nil + _transport := NewNoiseTransport(netSocket) + log.WithField("addr", netSocket.Addr().String()).Info("Created new NoiseTransportSocket") + return _transport, nil } From 220159476af0c75ff485048cec8ca772ddb82ffa Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 11:09:37 -0400 Subject: [PATCH 65/94] expanded logging in write_session.go --- lib/transport/noise/write_session.go | 36 +++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index 35b4d29..3b56324 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -4,17 +4,17 @@ import ( "encoding/binary" "errors" "fmt" + "github.com/sirupsen/logrus" "sync/atomic" - - log "github.com/sirupsen/logrus" ) func (c *NoiseSession) Write(b []byte) (int, error) { + log.WithField("data_length", len(b)).Debug("NoiseSession: Starting Write operation") // interlock with Close below for { x := atomic.LoadInt32(&c.activeCall) if x&1 != 0 { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(NoiseSession) Write", "reason": "session is closed", }).Error("session is closed") @@ -24,30 +24,43 @@ func (c *NoiseSession) Write(b []byte) (int, error) { defer atomic.AddInt32(&c.activeCall, -2) break } + log.Debug("NoiseSession: Write - retrying atomic operation") } if !c.handshakeComplete { + log.Debug("NoiseSession: Write - handshake not complete, running outgoing handshake") if err := c.RunOutgoingHandshake(); err != nil { + log.WithError(err).Error("NoiseSession: Write - failed to run outgoing handshake") return 0, err } } c.Mutex.Lock() defer c.Mutex.Unlock() if !c.handshakeComplete { + log.Error("NoiseSession: Write - internal error, handshake still not complete") return 0, errors.New("internal error") } n, err := c.writePacketLocked(b) + if err != nil { + log.WithError(err).Error("NoiseSession: Write - failed to write packet") + } else { + log.WithField("bytes_written", n).Debug("NoiseSession: Write - successfully wrote packet") + } return n, err } func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { + log.WithField("data_length", len(data)).Debug("NoiseSession: Starting packet encryption") + m := len(data) if c.CipherState == nil { + log.Error("NoiseSession: encryptPacket - CipherState is nil") return 0, nil, errors.New("CipherState is nil") } // Encrypt the data encryptedData, err := c.CipherState.Encrypt(nil, nil, data) if err != nil { + log.WithError(err).Error("NoiseSession: encryptPacket - failed to encrypt data") return 0, nil, fmt.Errorf("failed to encrypt: '%w'", err) } // m := len(encryptedData) @@ -57,6 +70,11 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { // Append encr data to prefix packet := append(lengthPrefix, encryptedData...) + log.WithFields(logrus.Fields{ + "original_length": m, + "encrypted_length": len(encryptedData), + "packet_length": len(packet), + }).Debug("NoiseSession: encryptPacket - packet encrypted successfully") return m, packet, nil /*packet := c.InitializePacket() maxPayloadSize := c.maxPayloadSizeForWrite(packet) @@ -80,23 +98,35 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { } func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { + log.WithField("data_length", len(data)).Debug("NoiseSession: Starting writePacketLocked") + var n int if len(data) == 0 { // special case to answer when everything is ok during handshake + log.Debug("NoiseSession: writePacketLocked - special case, writing 2 empty bytes") if _, err := c.Conn.Write(make([]byte, 2)); err != nil { + log.WithError(err).Error("NoiseSession: writePacketLocked - failed to write empty bytes") return 0, err } } for len(data) > 0 { m, b, err := c.encryptPacket(data) if err != nil { + log.WithError(err).Error("NoiseSession: writePacketLocked - failed to encrypt packet") return 0, err } if n, err := c.Conn.Write(b); err != nil { + log.WithError(err).WithField("bytes_written", n).Error("NoiseSession: writePacketLocked - failed to write to connection") return n, err } else { n += m data = data[m:] + log.WithFields(logrus.Fields{ + "bytes_written": n, + "remaining_data": len(data), + }).Debug("NoiseSession: writePacketLocked - wrote packet chunk") } } + + log.WithField("total_bytes_written", n).Debug("NoiseSession: writePacketLocked - completed writing all packets") return n, nil } From f4f39ca53c0d73285f40c0026add50767802dc3b Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 11:18:20 -0400 Subject: [PATCH 66/94] expanded logging in multi.go --- lib/transport/multi.go | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/lib/transport/multi.go b/lib/transport/multi.go index 1d3331c..dce7512 100644 --- a/lib/transport/multi.go +++ b/lib/transport/multi.go @@ -3,8 +3,11 @@ 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/go-i2p/lib/util/logger" ) +var log = logger.GetLogger() + // muxes multiple transports into 1 Transport // implements transport.Transport type TransportMuxer struct { @@ -14,61 +17,81 @@ type TransportMuxer struct { // mux a bunch of transports together func Mux(t ...Transport) (tmux *TransportMuxer) { + log.WithField("transport_count", len(t)).Debug("Creating new TransportMuxer") tmux = new(TransportMuxer) tmux.trans = append(tmux.trans, t...) + log.Debug("TransportMuxer created successfully") return } // set the identity for every transport func (tmux *TransportMuxer) SetIdentity(ident router_identity.RouterIdentity) (err error) { - for _, t := range tmux.trans { + log.WithField("identity", ident).Debug("TransportMuxer: Setting identity for all transports") + for i, t := range tmux.trans { err = t.SetIdentity(ident) if err != nil { + log.WithError(err).WithField("transport_index", i).Error("TransportMuxer: Failed to set identity for transport") // an error happened let's return and complain return } + log.WithField("transport_index", i).Debug("TransportMuxer: Identity set successfully for transport") } + log.Debug("TransportMuxer: Identity set successfully for all transports") return } // close every transport that this transport muxer has func (tmux *TransportMuxer) Close() (err error) { - for _, t := range tmux.trans { + log.Debug("TransportMuxer: Closing all transports") + for i, t := range tmux.trans { err = t.Close() if t != nil { // TODO: handle error (?) + log.WithError(err).WithField("transport_index", i).Warn("TransportMuxer: Error closing transport") + } else { + log.WithField("transport_index", i).Debug("TransportMuxer: Transport closed successfully") } } + log.Debug("TransportMuxer: All transports closed") return } // the name of this transport with the names of all the ones that we mux func (tmux *TransportMuxer) Name() string { + log.Debug("TransportMuxer: Generating muxed transport name") name := "Muxed Transport: " for _, t := range tmux.trans { name += t.Name() + ", " } - return name[len(name)-3:] + //return name[len(name)-3:] + _name := name[len(name)-3:] + log.WithField("name", _name).Debug("TransportMuxer: Muxed transport name generated") + return _name } // get a transport session given a router info // return session and nil if successful // return nil and ErrNoTransportAvailable if we failed to get a session func (tmux *TransportMuxer) GetSession(routerInfo router_info.RouterInfo) (s TransportSession, err error) { - for _, t := range tmux.trans { + log.WithField("router_info", routerInfo.String()).Debug("TransportMuxer: Attempting to get session") + for i, t := range tmux.trans { // pick the first one that is compatable if t.Compatible(routerInfo) { + log.WithField("transport_index", i).Debug("TransportMuxer: Found compatible transport, attempting to get session") // try to get a session s, err = t.GetSession(routerInfo) if err != nil { + log.WithError(err).WithField("transport_index", i).Warn("TransportMuxer: Failed to get session from compatible transport") // we could not get a session // try the next transport continue } // we got a session + log.WithField("transport_index", i).Info("TransportMuxer: Successfully got session from transport") return } } + log.Error("TransportMuxer: Failed to get session, no compatible transport available") // we failed to get a session for this routerInfo err = ErrNoTransportAvailable return @@ -76,11 +99,14 @@ func (tmux *TransportMuxer) GetSession(routerInfo router_info.RouterInfo) (s Tra // is there a transport that we mux that is compatable with this router info? func (tmux *TransportMuxer) Compatible(routerInfo router_info.RouterInfo) (compat bool) { - for _, t := range tmux.trans { + log.WithField("router_info", routerInfo.String()).Debug("TransportMuxer: Checking compatibility") + for i, t := range tmux.trans { if t.Compatible(routerInfo) { + log.WithField("transport_index", i).Debug("TransportMuxer: Found compatible transport") compat = true return } } + log.Debug("TransportMuxer: No compatible transport found") return } From a4517cafd7a5a1052a9c2f59addeec5d33ea49e1 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 12:25:31 -0400 Subject: [PATCH 67/94] expanded logging in delivery.go --- lib/tunnel/delivery.go | 183 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 166 insertions(+), 17 deletions(-) diff --git a/lib/tunnel/delivery.go b/lib/tunnel/delivery.go index 336940f..20075ac 100644 --- a/lib/tunnel/delivery.go +++ b/lib/tunnel/delivery.go @@ -3,11 +3,13 @@ package tunnel import ( "encoding/binary" "errors" - common "github.com/go-i2p/go-i2p/lib/common/data" - log "github.com/sirupsen/logrus" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" ) +var log = logger.GetLogger() + /* I2P First Fragment Delivery Instructions https://geti2p.net/spec/tunnel-message#struct-tunnelmessagedeliveryinstructions @@ -152,6 +154,7 @@ type DeliveryInstructions []byte // Return if the DeliveryInstructions are of type FIRST_FRAGMENT or FOLLOW_ON_FRAGMENT. func (delivery_instructions DeliveryInstructions) Type() (int, error) { + log.Debug("Determining DeliveryInstructions type") if len(delivery_instructions) >= 1 { /* Check if the 7 bit of the Delivery Instructions @@ -169,18 +172,23 @@ func (delivery_instructions DeliveryInstructions) Type() (int, error) { fragment or a complete fragment */ if (delivery_instructions[0] & 0x08) == 0x08 { + log.Debug("DeliveryInstructions type: FOLLOW_ON_FRAGMENT") return FOLLOW_ON_FRAGMENT, nil } + log.Debug("DeliveryInstructions type: FIRST_FRAGMENT") return FIRST_FRAGMENT, nil } + log.Error("DeliveryInstructions contains no data") return 0, errors.New("DeliveryInstructions contains no data") } // Read the integer stored in the 6-1 bits of a FOLLOW_ON_FRAGMENT's flag, indicating // the fragment number. func (delivery_instructions DeliveryInstructions) FragmentNumber() (int, error) { + log.Debug("Getting FragmentNumber") di_type, err := delivery_instructions.Type() if err != nil { + log.WithError(err).Error("Failed to get DeliveryInstructions type") return 0, err } /* @@ -193,18 +201,26 @@ func (delivery_instructions DeliveryInstructions) FragmentNumber() (int, error) 0??????0 >> 1 => Integer(??????) */ if di_type == FOLLOW_ON_FRAGMENT { - return common.Integer( - []byte{((delivery_instructions[0] & 0x7e) >> 1)}, - ).Int(), nil + /* + return common.Integer( + []byte{((delivery_instructions[0] & 0x7e) >> 1)}, + ).Int(), nil + */ + fragNum := common.Integer([]byte{((delivery_instructions[0] & 0x7e) >> 1)}).Int() + log.WithField("fragment_number", fragNum).Debug("FragmentNumber retrieved") + return fragNum, nil } + log.Error("Fragment Number only exists on FOLLOW_ON_FRAGMENT Delivery Instructions") return 0, errors.New("Fragment Number only exists on FOLLOW_ON_FRAGMENT Delivery Instructions") } // Read the value of the 0 bit of a FOLLOW_ON_FRAGMENT, which is set to 1 to indicate the // last fragment. func (delivery_instructions DeliveryInstructions) LastFollowOnFragment() (bool, error) { + log.Debug("Checking if this is the LastFollowOnFragment") di_type, err := delivery_instructions.Type() if err != nil { + log.WithError(err).Error("Failed to get DeliveryInstructions type") return false, err } /* @@ -217,18 +233,25 @@ func (delivery_instructions DeliveryInstructions) LastFollowOnFragment() (bool, 0000000? => n */ if di_type == FOLLOW_ON_FRAGMENT { - if delivery_instructions[0]&0x01 == 0x01 { - return true, nil - } else { - return false, nil - } + /* + if delivery_instructions[0]&0x01 == 0x01 { + return true, nil + } else { + return false, nil + } + */ + isLast := delivery_instructions[0]&0x01 == 0x01 + log.WithField("is_last", isLast).Debug("LastFollowOnFragment status determined") + return isLast, nil } + log.Error("Last Fragment only exists for FOLLOW_ON_FRAGMENT Delivery Instructions") return false, errors.New("Last Fragment only exists for FOLLOW_ON_FRAGMENT Delivery Instructions") } // Return the delivery type for these DeliveryInstructions, can be of type // DT_LOCAL, DT_TUNNEL, DT_ROUTER, or DT_UNUSED. func (delivery_instructions DeliveryInstructions) DeliveryType() (byte, error) { + log.Debug("Getting DeliveryType") if len(delivery_instructions) >= 1 { /* Check if the 6-5 bits of the Delivery Instructions @@ -240,13 +263,18 @@ func (delivery_instructions DeliveryInstructions) DeliveryType() (byte, error) { --------- 000?0000 >> 4 => n (DT_* consts) */ - return ((delivery_instructions[0] & 0x30) >> 4), nil + //return ((delivery_instructions[0] & 0x30) >> 4), nil + deliveryType := (delivery_instructions[0] & 0x30) >> 4 + log.WithField("delivery_type", deliveryType).Debug("DeliveryType retrieved") + return deliveryType, nil } + log.Error("DeliveryInstructions contains no data") return 0, errors.New("DeliveryInstructions contains no data") } // Check if the delay bit is set. This feature in unimplemented in the Java router. func (delivery_instructions DeliveryInstructions) HasDelay() (bool, error) { + log.Debug("Checking if DeliveryInstructions has delay") if len(delivery_instructions) >= 1 { /* Check if the 4 bit of the Delivery Instructions @@ -266,19 +294,22 @@ func (delivery_instructions DeliveryInstructions) HasDelay() (bool, error) { */ delay := (delivery_instructions[0] & 0x10) == 0x10 if delay { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(DeliveryInstructions) HasDelay", "info": "this feature is unimplemented in the Java router", }).Warn("DeliveryInstructions found with delay bit set") } + log.WithField("has_delay", delay).Debug("HasDelay status determined") return delay, nil } + log.Error("DeliveryInstructions contains no data") return false, errors.New("DeliveryInstructions contains no data") } // Returns true if the Delivery Instructions are fragmented or false // if the following data contains the entire message func (delivery_instructions DeliveryInstructions) Fragmented() (bool, error) { + log.Debug("Checking if DeliveryInstructions is fragmented") if len(delivery_instructions) >= 1 { /* Check if the 3 bit of the Delivery Instructions @@ -295,13 +326,18 @@ func (delivery_instructions DeliveryInstructions) Fragmented() (bool, error) { message is message is not fragmented fragmented */ - return ((delivery_instructions[0] & 0x08) == 0x08), nil + fragmented := (delivery_instructions[0] & 0x08) == 0x08 + log.WithField("fragmented", fragmented).Debug("Fragmented status determined") + return fragmented, nil + //return ((delivery_instructions[0] & 0x08) == 0x08), nil } + log.Error("DeliveryInstructions contains no data") return false, errors.New("DeliveryInstructions contains no data") } // Check if the extended options bit is set. This feature in unimplemented in the Java router. func (delivery_instructions DeliveryInstructions) HasExtendedOptions() (bool, error) { + log.Debug("Checking if DeliveryInstructions has extended options") if len(delivery_instructions) >= 1 { /* Check if the 2 bit of the Delivery Instructions @@ -322,28 +358,37 @@ func (delivery_instructions DeliveryInstructions) HasExtendedOptions() (bool, er */ extended_options := (delivery_instructions[0] & 0x04) == 0x04 if extended_options { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(DeliveryInstructions) ExtendedOptions", "info": "this feature is unimplemented in the Java router", }).Warn("DeliveryInstructions found with extended_options bit set") } + log.WithField("has_extended_options", extended_options).Debug("HasExtendedOptions status determined") return extended_options, nil } + log.Error("DeliveryInstructions contains no data") return false, errors.New("DeliveryInstructions contains no data") } // Check if the DeliveryInstructions is of type DT_TUNNEL. func (delivery_instructions DeliveryInstructions) HasTunnelID() (bool, error) { + log.Debug("Checking if DeliveryInstructions has TunnelID") di_type, err := delivery_instructions.DeliveryType() if err != nil { + log.WithError(err).Error("Failed to get DeliveryType") return false, err } - return di_type == DT_TUNNEL, nil + //return di_type == DT_TUNNEL, nil + hasTunnelID := di_type == DT_TUNNEL + log.WithField("has_tunnel_id", hasTunnelID).Debug("HasTunnelID status determined") + return hasTunnelID, nil } func (delivery_instructions DeliveryInstructions) HasHash() (bool, error) { + log.Debug("Checking if DeliveryInstructions has Hash") di_type, err := delivery_instructions.DeliveryType() if err != nil { + log.WithError(err).Error("Failed to get DeliveryType") return false, err } if di_type == DT_TUNNEL || di_type == DT_ROUTER { @@ -352,28 +397,37 @@ func (delivery_instructions DeliveryInstructions) HasHash() (bool, error) { min_size += TUNNEL_ID_SIZE } if len(delivery_instructions) < min_size { + log.Error("Delivery Instructions indicates hash present but has too little data") return false, errors.New("Delivery Instructions indicates hash present but has too little data") } + log.Debug("DeliveryInstructions has Hash") } else { + log.Debug("DeliveryInstructions does not have Hash") return false, nil } + log.Debug("DeliveryInstructions does not have Hash(?)") return true, nil } // Return the tunnel ID in this DeliveryInstructions or 0 and an error if the // DeliveryInstructions are not of type DT_TUNNEL. func (delivery_instructions DeliveryInstructions) TunnelID() (tunnel_id uint32, err error) { + log.Debug("Getting TunnelID") has_tunnel_id, err := delivery_instructions.HasTunnelID() if err != nil { + log.WithError(err).Error("Failed to check HasTunnelID") return } if has_tunnel_id { if len(delivery_instructions) >= FLAG_SIZE+TUNNEL_ID_SIZE { tunnel_id = binary.BigEndian.Uint32(delivery_instructions[FLAG_SIZE:TUNNEL_ID_SIZE]) + log.WithField("tunnel_id", tunnel_id).Debug("TunnelID retrieved") } else { + log.Error("DeliveryInstructions are invalid, too little data for Tunnel ID") err = errors.New("DeliveryInstructions are invalid, too little data for Tunnel ID") } } else { + log.Error("DeliveryInstructions are not of type DT_TUNNEL") err = errors.New("DeliveryInstructions are not of type DT_TUNNEL") } return @@ -384,8 +438,10 @@ func (delivery_instructions DeliveryInstructions) TunnelID() (tunnel_id uint32, // If the type is DT_TUNNEL, hash is the SHA256 of the gateway router, if // the type is DT_ROUTER it is the SHA256 of the router. func (delivery_instructions DeliveryInstructions) Hash() (hash common.Hash, err error) { + log.Debug("Getting Hash") delivery_type, err := delivery_instructions.DeliveryType() if err != nil { + log.WithError(err).Error("Failed to get DeliveryType") return } hash_start := FLAG_SIZE @@ -395,16 +451,21 @@ func (delivery_instructions DeliveryInstructions) Hash() (hash common.Hash, err hash_end := hash_end + TUNNEL_ID_SIZE if len(delivery_instructions) >= hash_end { copy(hash[:], delivery_instructions[hash_start:hash_end]) + log.WithField("hash", hash).Debug("Hash retrieved for DT_TUNNEL") } else { + log.Error("DeliveryInstructions is invalid, not contain enough data for hash given type DT_TUNNEL") err = errors.New("DeliveryInstructions is invalid, not contain enough data for hash given type DT_TUNNEL") } } else if delivery_type == DT_ROUTER { if len(delivery_instructions) >= hash_end { copy(hash[:], delivery_instructions[hash_start:hash_end]) + log.WithField("hash", hash).Debug("Hash retrieved for DT_ROUTER") } else { + log.Error("DeliveryInstructions is invalid, not contain enough data for hash given type DT_ROUTER") err = errors.New("DeliveryInstructions is invalid, not contain enough data for hash given type DT_ROUTER") } } else { + log.Error("No Hash on DeliveryInstructions not of type DT_TUNNEL or DT_ROUTER") err = errors.New("No Hash on DeliveryInstructions not of type DT_TUNNEL or DT_ROUTER") } return @@ -412,32 +473,39 @@ func (delivery_instructions DeliveryInstructions) Hash() (hash common.Hash, err // Return the DelayFactor if present and any errors encountered parsing the DeliveryInstructions. func (delivery_instructions DeliveryInstructions) Delay() (delay_factor DelayFactor, err error) { + log.Debug("Getting Delay") delay, err := delivery_instructions.HasDelay() if err != nil { + log.WithError(err).Error("Failed to check HasDelay") return } if delay { var di_type byte di_type, err = delivery_instructions.DeliveryType() if err != nil { + log.WithError(err).Error("Failed to get DeliveryType") return } if di_type == DT_TUNNEL { if len(delivery_instructions) >= FLAG_SIZE+TUNNEL_ID_SIZE+HASH_SIZE { delay_factor = DelayFactor(delivery_instructions[FLAG_SIZE+TUNNEL_ID_SIZE+HASH_SIZE]) + log.WithField("delay_factor", delay_factor).Debug("Delay factor retrieved for DT_TUNNEL") } else { + log.Error("DeliveryInstructions is invalid, does not contain enough data for DelayFactor") err = errors.New("DeliveryInstructions is invalid, does not contain enough data for DelayFactor") return } } else if di_type == DT_ROUTER { if len(delivery_instructions) >= FLAG_SIZE+HASH_SIZE { delay_factor = DelayFactor(delivery_instructions[FLAG_SIZE+HASH_SIZE]) + log.WithField("delay_factor", delay_factor).Debug("Delay factor retrieved for DT_ROUTER") } else { + log.Error("DeliveryInstructions is invalid, does not contain enough data for DelayFactor") err = errors.New("DeliveryInstructions is invalid, does not contain enough data for DelayFactor") return } } else { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(DeliveryInstructions) Delay", }).Warn("Delay not present on DeliveryInstructions not of type DT_TUNNEL or DT_ROUTER") } @@ -448,28 +516,36 @@ func (delivery_instructions DeliveryInstructions) Delay() (delay_factor DelayFac // Return the I2NP Message ID or 0 and an error if the data is not available for this // DeliveryInstructions. func (delivery_instructions DeliveryInstructions) MessageID() (msgid uint32, err error) { + log.Debug("Getting MessageID") di_type, err := delivery_instructions.Type() if err != nil { + log.WithError(err).Error("Failed to get DeliveryInstructions type") return } if di_type == FOLLOW_ON_FRAGMENT { if len(delivery_instructions) >= 5 { msgid = binary.BigEndian.Uint32(delivery_instructions[1:5]) + log.WithField("message_id", msgid).Debug("MessageID retrieved for FOLLOW_ON_FRAGMENT") } else { + log.Error("DeliveryInstructions are invalid, not enough data for Message ID") err = errors.New("DeliveryInstructions are invalid, not enough data for Message ID") } } else if di_type == FIRST_FRAGMENT { var message_id_index int message_id_index, err = delivery_instructions.message_id_index() if err != nil { + log.WithError(err).Error("Failed to get message_id_index") return } if len(delivery_instructions) >= message_id_index+4 { msgid = binary.BigEndian.Uint32(delivery_instructions[message_id_index : message_id_index+4]) + log.WithField("message_id", msgid).Debug("MessageID retrieved for FIRST_FRAGMENT") } else { + log.Error("DeliveryInstructions are invalid, not enough data for Message ID") err = errors.New("DeliveryInstructions are invalid, not enough data for Message ID") } } else { + log.Error("No Message ID for DeliveryInstructions not of type FIRST_FRAGMENT or FOLLOW_ON_FRAGMENT") err = errors.New("No Message ID for DeliveryInstructions not of type FIRST_FRAGMENT or FOLLOW_ON_FRAGMENT") } return @@ -478,31 +554,38 @@ func (delivery_instructions DeliveryInstructions) MessageID() (msgid uint32, err // Return the Extended Options data if present, or an error if not present. Extended Options in unimplemented // in the Java router and the presence of extended options will generate a warning. func (delivery_instructions DeliveryInstructions) ExtendedOptions() (data []byte, err error) { + log.Debug("Getting ExtendedOptions") ops, err := delivery_instructions.HasExtendedOptions() if err != nil { + log.WithError(err).Error("Failed to check HasExtendedOptions") return } if ops { var extended_options_index int extended_options_index, err = delivery_instructions.extended_options_index() if err != nil { + log.WithError(err).Error("Failed to get extended_options_index") return } if len(delivery_instructions) < extended_options_index+2 { + log.Error("DeliveryInstructions are invalid, length is shorter than required for Extended Options") err = errors.New("DeliveryInstructions are invalid, length is shorter than required for Extended Options") return } else { extended_options_size := common.Integer([]byte{delivery_instructions[extended_options_index]}) if len(delivery_instructions) < extended_options_index+1+extended_options_size.Int() { + log.Error("DeliveryInstructions are invalid, length is shorter than specified in Extended Options") err = errors.New("DeliveryInstructions are invalid, length is shorter than specified in Extended Options") return } else { data = delivery_instructions[extended_options_index+1 : extended_options_size.Int()] + log.WithField("extended_options_length", len(data)).Debug("Extended Options retrieved") return } } } else { + log.Error("DeliveryInstruction does not have the ExtendedOptions flag set") err = errors.New("DeliveryInstruction does not have the ExtendedOptions flag set") } return @@ -510,28 +593,36 @@ func (delivery_instructions DeliveryInstructions) ExtendedOptions() (data []byte // Return the size of the associated I2NP fragment and an error if the data is unavailable. func (delivery_instructions DeliveryInstructions) FragmentSize() (frag_size uint16, err error) { + log.Debug("Getting FragmentSize") di_type, err := delivery_instructions.Type() if err != nil { + log.WithError(err).Error("Failed to get DeliveryInstructions type") return } if di_type == FOLLOW_ON_FRAGMENT { if len(delivery_instructions) >= 7 { frag_size = binary.BigEndian.Uint16(delivery_instructions[5:7]) + log.WithField("fragment_size", frag_size).Debug("FragmentSize retrieved for FOLLOW_ON_FRAGMENT") } else { + log.Error("DeliveryInstructions are invalid, not enough data for Fragment Size") err = errors.New("DeliveryInstructions are invalid, not enough data for Fragment Size") } } else if di_type == FIRST_FRAGMENT { var fragment_size_index int fragment_size_index, err = delivery_instructions.fragment_size_index() if err != nil { + log.WithError(err).Error("Failed to get fragment_size_index") return } if len(delivery_instructions) >= fragment_size_index+2 { frag_size = binary.BigEndian.Uint16(delivery_instructions[fragment_size_index : fragment_size_index+2]) + log.WithField("fragment_size", frag_size).Debug("FragmentSize retrieved for FIRST_FRAGMENT") } else { + log.Error("DeliveryInstructions are invalid, not enough data for Fragment Size") err = errors.New("DeliveryInstructions are invalid, not enough data for Fragment Size") } } else { + log.Error("No Fragment Size for DeliveryInstructions not of type FIRST_FRAGMENT or FOLLOW_ON_FRAGMENT") err = errors.New("No Fragment Size for DeliveryInstructions not of type FIRST_FRAGMENT or FOLLOW_ON_FRAGMENT") } return @@ -539,8 +630,10 @@ func (delivery_instructions DeliveryInstructions) FragmentSize() (frag_size uint // Find the correct index for the Message ID in a FIRST_FRAGMENT DeliveryInstructions func (delivery_instructions DeliveryInstructions) message_id_index() (message_id int, err error) { + log.Debug("Calculating message_id_index") fragmented, err := delivery_instructions.Fragmented() if err != nil { + log.WithError(err).Error("Failed to check if DeliveryInstructions are fragmented") return } if fragmented { @@ -551,6 +644,7 @@ func (delivery_instructions DeliveryInstructions) message_id_index() (message_id var di_type byte di_type, err = delivery_instructions.DeliveryType() if err != nil { + log.WithError(err).Error("Failed to get DeliveryType") return } if di_type == DT_TUNNEL { @@ -563,22 +657,26 @@ func (delivery_instructions DeliveryInstructions) message_id_index() (message_id var delay bool delay, err = delivery_instructions.HasDelay() if err != nil { + log.WithError(err).Error("Failed to check HasDelay") return } if delay { message_id++ } - + log.WithField("message_id_index", message_id).Debug("message_id_index calculated") return message_id, nil } else { + log.Error("DeliveryInstruction must be fragmented to have a Message ID") return 0, errors.New("DeliveryInstruction must be fragmented to have a Message ID") } } // Find the index of the extended options in this Delivery Instruction, if they exist. func (delivery_instructions DeliveryInstructions) extended_options_index() (extended_options int, err error) { + log.Debug("Calculating extended_options_index") ops, err := delivery_instructions.HasExtendedOptions() if err != nil { + log.WithError(err).Error("Failed to check HasExtendedOptions") return } if ops { @@ -589,6 +687,7 @@ func (delivery_instructions DeliveryInstructions) extended_options_index() (exte var di_type byte di_type, err = delivery_instructions.DeliveryType() if err != nil { + log.WithError(err).Error("Failed to get DeliveryType") return } if di_type == DT_TUNNEL { @@ -601,6 +700,7 @@ func (delivery_instructions DeliveryInstructions) extended_options_index() (exte var delay bool delay, err = delivery_instructions.HasDelay() if err != nil { + log.WithError(err).Error("Failed to check HasDelay") return } if delay { @@ -613,9 +713,11 @@ func (delivery_instructions DeliveryInstructions) extended_options_index() (exte } else { err = nil } + log.WithField("extended_options_index", extended_options).Debug("extended_options_index calculated") return extended_options, nil } else { + log.Error("DeliveryInstruction does not have the ExtendedOptions flag set") err = errors.New("DeliveryInstruction does not have the ExtendedOptions flag set") } return @@ -623,6 +725,7 @@ func (delivery_instructions DeliveryInstructions) extended_options_index() (exte // Find the index of the Fragment Size data in this Delivery Instruction. func (delivery_instructions DeliveryInstructions) fragment_size_index() (fragment_size int, err error) { + log.Debug("Calculating fragment_size_index") // Start counting after the flags fragment_size = 1 @@ -630,6 +733,7 @@ func (delivery_instructions DeliveryInstructions) fragment_size_index() (fragmen var di_type byte di_type, err = delivery_instructions.DeliveryType() if err != nil { + log.WithError(err).Error("Failed to get DeliveryType") return } if di_type == DT_TUNNEL { @@ -642,6 +746,7 @@ func (delivery_instructions DeliveryInstructions) fragment_size_index() (fragmen var delay bool delay, err = delivery_instructions.HasDelay() if err != nil { + log.WithError(err).Error("Failed to check HasDelay") return } if delay { @@ -661,22 +766,29 @@ func (delivery_instructions DeliveryInstructions) fragment_size_index() (fragmen fragment_size += len(extended_opts) + 1 } } + log.WithField("fragment_size_index", fragment_size).Debug("fragment_size_index calculated") return fragment_size, nil } func maybeAppendTunnelID(data, current []byte) (now []byte, err error) { + log.Debug("Attempting to append TunnelID") if has_tunnel_id, _ := DeliveryInstructions(data).HasTunnelID(); has_tunnel_id { _, err = DeliveryInstructions(data).TunnelID() if err == nil { now = append(current, data[1:5]...) + log.Debug("TunnelID appended") } else { + log.WithError(err).Error("Failed to get TunnelID") return } + } else { + log.Debug("No TunnelID to append") } return } func maybeAppendHash(di_flag DeliveryInstructions, data, current []byte) (now []byte, err error) { + log.Debug("Attempting to append Hash") delivery_type, _ := di_flag.DeliveryType() if _, err := DeliveryInstructions(data).HasHash(); err == nil { hash_start := 1 @@ -687,12 +799,16 @@ func maybeAppendHash(di_flag DeliveryInstructions, data, current []byte) (now [] } if err == nil { now = append(current, data[hash_start:hash_end]...) + log.Debug("Hash appended") } + } else { + log.Debug("No Hash to append") } return } func maybeAppendDelay(di_flag DeliveryInstructions, data, current []byte) (now []byte, err error) { + log.Debug("Attempting to append Delay") delivery_type, _ := di_flag.DeliveryType() if _, err = DeliveryInstructions(data).HasHash(); err == nil { delay_start := 1 @@ -704,12 +820,16 @@ func maybeAppendDelay(di_flag DeliveryInstructions, data, current []byte) (now [ } if err == nil { now = append(current, data[delay_start]) + log.Debug("Delay appended") } + } else { + log.Debug("No Delay to append") } return } func maybeAppendMessageID(di_flag DeliveryInstructions, di_type int, data, current []byte) (now []byte, err error) { + log.Debug("Attempting to append MessageID") if di_type == FIRST_FRAGMENT { if fragmented, _ := di_flag.Fragmented(); fragmented { message_id_index := 1 @@ -723,47 +843,61 @@ func maybeAppendMessageID(di_flag DeliveryInstructions, di_type int, data, curre message_id_index += 1 } if len(data) < message_id_index+4 { + log.Error("Data is too short to contain message ID in FIRST_FRAGMENT") err = errors.New("data is too short to contain message ID in FIRST_FRAGMENT") } else { now = append(current, data[message_id_index:message_id_index+4]...) + log.Debug("MessageID appended for FIRST_FRAGMENT") } } } else if di_type == FOLLOW_ON_FRAGMENT { if len(data) < 5 { + log.Error("Data is too short to contain message ID in FOLLOW_ON_FRAGMENT") err = errors.New("data is too short to contain message ID in FOLLOW_ON_FRAGMENT") } else { now = append(current, data[1:5]...) + log.Debug("MessageID appended for FOLLOW_ON_FRAGMENT") } } return } func maybeAppendExtendedOptions(di_flag DeliveryInstructions, data, current []byte) (now []byte, err error) { + log.Debug("Attempting to append ExtendedOptions") if index, err := DeliveryInstructions(data).extended_options_index(); err != nil { extended_options_length := common.Integer([]byte{data[index]}) now = append(current, data[index:index+extended_options_length.Int()]...) + log.WithField("extended_options_length", extended_options_length.Int()).Debug("ExtendedOptions appended") + } else { + log.Debug("No ExtendedOptions to append") } return } func maybeAppendSize(di_flag DeliveryInstructions, di_type int, data, current []byte) (now []byte, err error) { + log.Debug("Attempting to append Size") if di_type == FIRST_FRAGMENT { if index, err := DeliveryInstructions(data).extended_options_index(); err != nil { extended_options_length := common.Integer([]byte{data[index]}) now = append(current, data[index+extended_options_length.Int():index+extended_options_length.Int()+2]...) + log.Debug("Size appended for FIRST_FRAGMENT") } } else if di_type == FOLLOW_ON_FRAGMENT { if len(data) < 7 { + log.Error("Data is too short to contain size data") err = errors.New("data is too short to contain size data") } else { now = append(now, data[5:7]...) + log.Debug("Size appended for FOLLOW_ON_FRAGMENT") } } return } func readDeliveryInstructions(data []byte) (instructions DeliveryInstructions, remainder []byte, err error) { + log.Debug("Reading DeliveryInstructions") if len(data) < 1 { + log.Error("No data provided") err = errors.New("no data provided") return } @@ -775,42 +909,57 @@ func readDeliveryInstructions(data []byte) (instructions DeliveryInstructions, r di_data = append(di_data, data[0]) if di_type == FIRST_FRAGMENT { + log.Debug("Processing FIRST_FRAGMENT") di_data, err = maybeAppendTunnelID(data, di_data) if err != nil { + log.WithError(err).Error("Failed to append TunnelID") return } di_data, err = maybeAppendHash(di_flag, data, di_data) if err != nil { + log.WithError(err).Error("Failed to append Hash") return } di_data, err = maybeAppendDelay(di_flag, data, di_data) if err != nil { + log.WithError(err).Error("Failed to append Delay") return } di_data, err = maybeAppendMessageID(di_flag, di_type, data, di_data) if err != nil { + log.WithError(err).Error("Failed to append MessageID") return } di_data, err = maybeAppendExtendedOptions(di_flag, data, di_data) if err != nil { + log.WithError(err).Error("Failed to append ExtendedOptions") return } di_data, err = maybeAppendSize(di_flag, di_type, data, di_data) if err != nil { + log.WithError(err).Error("Failed to append Size") return } } else if di_type == FOLLOW_ON_FRAGMENT { di_data, err = maybeAppendMessageID(di_flag, di_type, data, di_data) if err != nil { + log.WithError(err).Error("Failed to append MessageID") return } di_data, err = maybeAppendSize(di_flag, di_type, data, di_data) if err != nil { + log.WithError(err).Error("Failed to append Size") return } } remainder = data[len(di_data):] + instructions = DeliveryInstructions(di_data) + + log.WithFields(logrus.Fields{ + "instructions_length": len(instructions), + "remainder_length": len(remainder), + }).Debug("Successfully read DeliveryInstructions") return } From 3c5aa206d171acee0ea9a01d1391c604382a5c32 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 12:32:49 -0400 Subject: [PATCH 68/94] expanded logging in message.go --- lib/tunnel/message.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/tunnel/message.go b/lib/tunnel/message.go index af72ed7..f255a93 100644 --- a/lib/tunnel/message.go +++ b/lib/tunnel/message.go @@ -2,9 +2,9 @@ package tunnel import ( "encoding/binary" + "github.com/sirupsen/logrus" "github.com/go-i2p/go-i2p/lib/crypto" - log "github.com/sirupsen/logrus" ) /* @@ -157,12 +157,17 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) Checksum() crypto.TunnelI // Returns the contents of a decrypted tunnel message that contain the data for the // DeliveryInstructions. func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData() []byte { + log.Debug("Retrieving delivery instruction data from DecryptedTunnelMessage") data_area := decrypted_tunnel_message[4+4+16:] for i := 0; i < len(data_area); i++ { if data_area[i] == 0x00 { - return data_area[i+1:] + //return data_area[i+1:] + delivery_data := data_area[i+1:] + log.WithField("delivery_data_length", len(delivery_data)).Debug("Retrieved delivery instruction data") + return delivery_data } } + log.Warn("No delivery instruction data found in DecryptedTunnelMessage") return []byte{} } @@ -174,7 +179,7 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) DeliveryInstructionsWithF for { instructions, remainder, err := readDeliveryInstructions(data) if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(DecryptedTunnelMessage) DeliveryInstructionsWithFragments", "err": err.Error(), }).Error("error reading delivery instructions") @@ -183,7 +188,7 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) DeliveryInstructionsWithF fragment_size, err := instructions.FragmentSize() if err != nil { - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "at": "(DecryptedTunnelMessage) DeliveryInstructionsWithFragments", "err": err.Error(), }).Error("error getting delivery instructions fragment size") From 02569083959a504fa0abfa88c0e9ae04cf7b440b Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Sat, 19 Oct 2024 17:27:39 -0400 Subject: [PATCH 69/94] CRITICAL FIX, bytesRead -> n. n wasn't being used before --- lib/transport/noise/read_session.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go index f8bca5b..87def0b 100644 --- a/lib/transport/noise/read_session.go +++ b/lib/transport/noise/read_session.go @@ -108,16 +108,15 @@ func (c *NoiseSession) readPacketLocked(data []byte) (int, error) { data = data[m:] } */ - bytesRead, err := c.Conn.Read(b) + n, err := c.Conn.Read(b) if err != nil { - log.WithError(err).WithField("bytes_read", bytesRead).Error("readPacketLocked: failed to read from connection") + log.WithError(err).WithField("bytes_read (aka n)", n).Error("readPacketLocked: failed to read from connection") return n, err } n += m data = data[m:] log.WithFields(logrus.Fields{ - "bytes_read": bytesRead, - "total_read": n, + "bytes_read": n, "remaining_data": len(data), }).Debug("readPacketLocked: read packet chunk") } From 647546a374039ca324b09bc38690cc55e62a6384 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Tue, 22 Oct 2024 14:51:17 -0400 Subject: [PATCH 70/94] typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 67c6f43..ec75f4c 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ export DEBUG_I2P=warn export DEBUG_I2P=error ``` -If in case I2P_DEBUG is set to an unrecognized variable, it will fall back to "debug". +In case I2P_DEBUG is set to an unrecognized variable, it will fall back to "debug". ## Contributing From a9dc482bda2858fee5402a79258f3ab854f21436 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Tue, 22 Oct 2024 17:37:17 -0400 Subject: [PATCH 71/94] gofumpt --- lib/common/router_info/router_info.go | 11 ++++++----- lib/common/signature/signature.go | 2 +- lib/crypto/aes.go | 1 + lib/crypto/curve25519.go | 5 +++-- lib/crypto/dsa.go | 3 ++- lib/crypto/ecdsa.go | 7 ++++--- lib/crypto/ed25519.go | 3 ++- lib/crypto/elg.go | 3 ++- lib/crypto/tunnel.go | 2 +- lib/i2np/build_request_record.go | 3 ++- lib/i2np/header.go | 3 ++- lib/netdb/reseed/reseed.go | 5 +++-- lib/netdb/std.go | 11 ++++++----- lib/router/router.go | 3 ++- lib/su3/su3.go | 7 ++++--- lib/transport/multi.go | 2 +- lib/transport/noise/handshake.go | 3 ++- lib/transport/noise/incoming_handshake.go | 5 +++-- lib/transport/noise/outgoing_handshake.go | 3 ++- lib/transport/noise/read_session.go | 3 ++- lib/transport/noise/session.go | 5 +++-- lib/transport/noise/transport.go | 9 +++++---- lib/transport/noise/write_session.go | 3 ++- lib/tunnel/delivery.go | 5 +++-- lib/tunnel/message.go | 3 ++- 25 files changed, 66 insertions(+), 44 deletions(-) diff --git a/lib/common/router_info/router_info.go b/lib/common/router_info/router_info.go index 3283f06..2cf6c1f 100644 --- a/lib/common/router_info/router_info.go +++ b/lib/common/router_info/router_info.go @@ -3,11 +3,12 @@ package router_info import ( "errors" - "github.com/go-i2p/go-i2p/lib/util/logger" - "github.com/sirupsen/logrus" "strconv" "strings" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" + . "github.com/go-i2p/go-i2p/lib/common/data" . "github.com/go-i2p/go-i2p/lib/common/router_address" . "github.com/go-i2p/go-i2p/lib/common/router_identity" @@ -299,7 +300,7 @@ func (router_info *RouterInfo) RouterCapabilities() string { log.WithError(err).Error("Failed to create I2PString for 'caps'") return "" } - //return string(router_info.options.Values().Get(str)) + // return string(router_info.options.Values().Get(str)) caps := string(router_info.options.Values().Get(str)) log.WithField("capabilities", caps).Debug("Retrieved RouterCapabilities") return caps @@ -312,7 +313,7 @@ func (router_info *RouterInfo) RouterVersion() string { log.WithError(err).Error("Failed to create I2PString for 'router.version'") return "" } - //return string(router_info.options.Values().Get(str)) + // return string(router_info.options.Values().Get(str)) version := string(router_info.options.Values().Get(str)) log.WithField("version", version).Debug("Retrieved RouterVersion") return version @@ -364,7 +365,7 @@ func (router_info *RouterInfo) Reachable() bool { log.WithField("reason", "U capability").Debug("RouterInfo is unreachable") return false } - //return strings.Contains(caps, "R") + // return strings.Contains(caps, "R") reachable := strings.Contains(caps, "R") log.WithFields(logrus.Fields{ "reachable": reachable, diff --git a/lib/common/signature/signature.go b/lib/common/signature/signature.go index 1e9492e..e55f8f3 100644 --- a/lib/common/signature/signature.go +++ b/lib/common/signature/signature.go @@ -52,7 +52,7 @@ func ReadSignature(bytes []byte) (info Signature, remainder []byte, err error) { // Returns a pointer to Signature unlike ReadSignature. func NewSignature(data []byte) (session_tag *Signature, remainder []byte, err error) { log.WithField("input_length", len(data)).Debug("Creating new Signature") - //sessionTag, remainder, err := ReadSignature(data) + // sessionTag, remainder, err := ReadSignature(data) sig, remainder, err := ReadSignature(data) if err != nil { log.WithError(err).Error("Failed to read Signature") diff --git a/lib/crypto/aes.go b/lib/crypto/aes.go index f805b46..96cf3b8 100644 --- a/lib/crypto/aes.go +++ b/lib/crypto/aes.go @@ -5,6 +5,7 @@ import ( "crypto/aes" "crypto/cipher" "fmt" + "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/sirupsen/logrus" ) diff --git a/lib/crypto/curve25519.go b/lib/crypto/curve25519.go index 64acd70..41f7c71 100644 --- a/lib/crypto/curve25519.go +++ b/lib/crypto/curve25519.go @@ -5,10 +5,11 @@ import ( "crypto/sha256" "crypto/sha512" "errors" - "github.com/sirupsen/logrus" "io" "math/big" + "github.com/sirupsen/logrus" + curve25519 "go.step.sm/crypto/x25519" ) @@ -188,6 +189,6 @@ func (s *Curve25519Signer) SignHash(h []byte) (sig []byte, err error) { } else { log.WithField("signature_length", len(sig)).Debug("Hash signed successfully") } - //return curve25519.Sign(rand.Reader, s.k, h) + // return curve25519.Sign(rand.Reader, s.k, h) return } diff --git a/lib/crypto/dsa.go b/lib/crypto/dsa.go index e5b30fe..0663fe9 100644 --- a/lib/crypto/dsa.go +++ b/lib/crypto/dsa.go @@ -4,9 +4,10 @@ import ( "crypto/dsa" "crypto/rand" "crypto/sha1" - "github.com/sirupsen/logrus" "io" "math/big" + + "github.com/sirupsen/logrus" ) var dsap = new(big.Int).SetBytes([]byte{ diff --git a/lib/crypto/ecdsa.go b/lib/crypto/ecdsa.go index 61262bd..d7b3f60 100644 --- a/lib/crypto/ecdsa.go +++ b/lib/crypto/ecdsa.go @@ -4,6 +4,7 @@ import ( "crypto" "crypto/ecdsa" "crypto/elliptic" + "github.com/sirupsen/logrus" ) @@ -74,7 +75,7 @@ func (k ECP256PublicKey) Len() int { func (k ECP256PublicKey) NewVerifier() (Verifier, error) { log.Debug("Creating new P256 ECDSA verifier") - //return createECVerifier(elliptic.P256(), crypto.SHA256, k[:]) + // return createECVerifier(elliptic.P256(), crypto.SHA256, k[:]) v, err := createECVerifier(elliptic.P256(), crypto.SHA256, k[:]) if err != nil { log.WithError(err).Error("Failed to create P256 ECDSA verifier") @@ -98,7 +99,7 @@ func (k ECP384PublicKey) NewVerifier() (Verifier, error) { log.WithError(err).Error("Failed to create P384 ECDSA verifier") } return v, err - //return createECVerifier(elliptic.P384(), crypto.SHA384, k[:]) + // return createECVerifier(elliptic.P384(), crypto.SHA384, k[:]) } type ( @@ -117,5 +118,5 @@ func (k ECP521PublicKey) NewVerifier() (Verifier, error) { log.WithError(err).Error("Failed to create P521 ECDSA verifier") } return v, err - //return createECVerifier(elliptic.P521(), crypto.SHA512, k[:]) + // return createECVerifier(elliptic.P521(), crypto.SHA512, k[:]) } diff --git a/lib/crypto/ed25519.go b/lib/crypto/ed25519.go index 9bf21ad..896b5b0 100644 --- a/lib/crypto/ed25519.go +++ b/lib/crypto/ed25519.go @@ -6,9 +6,10 @@ import ( "crypto/sha256" "crypto/sha512" "errors" - "github.com/sirupsen/logrus" "io" "math/big" + + "github.com/sirupsen/logrus" ) var Ed25519EncryptTooBig = errors.New("failed to encrypt data, too big for Ed25519") diff --git a/lib/crypto/elg.go b/lib/crypto/elg.go index 93a956b..702d357 100644 --- a/lib/crypto/elg.go +++ b/lib/crypto/elg.go @@ -5,10 +5,11 @@ import ( "crypto/sha256" "crypto/subtle" "errors" - "github.com/sirupsen/logrus" "io" "math/big" + "github.com/sirupsen/logrus" + "golang.org/x/crypto/openpgp/elgamal" ) diff --git a/lib/crypto/tunnel.go b/lib/crypto/tunnel.go index c825b13..1a959e5 100644 --- a/lib/crypto/tunnel.go +++ b/lib/crypto/tunnel.go @@ -28,7 +28,7 @@ func NewTunnelCrypto(layerKey, ivKey TunnelKey) (t *Tunnel, err error) { if err != nil { // error happened we don't need t - //log.WithError(err).Error("Failed to create Tunnel crypto") + // log.WithError(err).Error("Failed to create Tunnel crypto") t = nil } else { log.Debug("Tunnel crypto created successfully") diff --git a/lib/i2np/build_request_record.go b/lib/i2np/build_request_record.go index cd48713..9d81cea 100644 --- a/lib/i2np/build_request_record.go +++ b/lib/i2np/build_request_record.go @@ -2,9 +2,10 @@ package i2np import ( "errors" - "github.com/sirupsen/logrus" "time" + "github.com/sirupsen/logrus" + common "github.com/go-i2p/go-i2p/lib/common/data" "github.com/go-i2p/go-i2p/lib/common/session_key" "github.com/go-i2p/go-i2p/lib/tunnel" diff --git a/lib/i2np/header.go b/lib/i2np/header.go index 2d493dc..5ed92f6 100644 --- a/lib/i2np/header.go +++ b/lib/i2np/header.go @@ -2,9 +2,10 @@ package i2np import ( "errors" - "github.com/sirupsen/logrus" "time" + "github.com/sirupsen/logrus" + datalib "github.com/go-i2p/go-i2p/lib/common/data" ) diff --git a/lib/netdb/reseed/reseed.go b/lib/netdb/reseed/reseed.go index cf32b3c..9aba111 100644 --- a/lib/netdb/reseed/reseed.go +++ b/lib/netdb/reseed/reseed.go @@ -2,8 +2,6 @@ package reseed import ( "fmt" - "github.com/go-i2p/go-i2p/lib/util/logger" - "github.com/sirupsen/logrus" "io" "net" "net/http" @@ -11,6 +9,9 @@ import ( "os" "path/filepath" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" + "github.com/eyedeekay/go-unzip/pkg/unzip" "github.com/go-i2p/go-i2p/lib/common/router_info" "github.com/go-i2p/go-i2p/lib/config" diff --git a/lib/netdb/std.go b/lib/netdb/std.go index 8f2ac67..1e46719 100644 --- a/lib/netdb/std.go +++ b/lib/netdb/std.go @@ -3,8 +3,6 @@ package netdb import ( "bytes" "fmt" - "github.com/go-i2p/go-i2p/lib/util/logger" - "github.com/sirupsen/logrus" "io" "io/ioutil" "os" @@ -12,6 +10,9 @@ import ( "strconv" "strings" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" + "github.com/go-i2p/go-i2p/lib/bootstrap" "github.com/go-i2p/go-i2p/lib/common/base32" "github.com/go-i2p/go-i2p/lib/common/base64" @@ -98,7 +99,7 @@ func (db *StdNetDB) Size() (routers int) { err = db.RecalculateSize() if err != nil { // TODO : what now? let's panic for now - //util.Panicf("could not recalculate netdb size: %s", err) + // util.Panicf("could not recalculate netdb size: %s", err) log.WithError(err).Panic("Failed to recalculate NetDB size") } } @@ -124,7 +125,7 @@ func (db *StdNetDB) cacheFilePath() string { func (db *StdNetDB) CheckFilePathValid(fpath string) bool { // TODO: make this better - //return strings.HasSuffix(fpath, ".dat") + // return strings.HasSuffix(fpath, ".dat") isValid := strings.HasSuffix(fpath, ".dat") log.WithFields(logrus.Fields{ "file_path": fpath, @@ -285,7 +286,7 @@ func (db *StdNetDB) Ensure() (err error) { func (db *StdNetDB) Create() (err error) { mode := os.FileMode(0o700) p := db.Path() - //log.Infof("Create network database in %s", p) + // log.Infof("Create network database in %s", p) log.WithField("path", p).Debug("Creating network database directory") // create root for skiplist err = os.Mkdir(p, mode) diff --git a/lib/router/router.go b/lib/router/router.go index 5735495..c128a92 100644 --- a/lib/router/router.go +++ b/lib/router/router.go @@ -1,9 +1,10 @@ package router import ( + "time" + "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/sirupsen/logrus" - "time" "github.com/go-i2p/go-i2p/lib/config" "github.com/go-i2p/go-i2p/lib/netdb" diff --git a/lib/su3/su3.go b/lib/su3/su3.go index 4b47ca2..e28ba2f 100644 --- a/lib/su3/su3.go +++ b/lib/su3/su3.go @@ -73,13 +73,14 @@ import ( "encoding/binary" "errors" "fmt" - "github.com/go-i2p/go-i2p/lib/util/logger" - "github.com/sirupsen/logrus" "hash" "io" "io/ioutil" "strings" "sync" + + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/sirupsen/logrus" ) var log = logger.GetLogger() @@ -692,7 +693,7 @@ func (r *signatureReader) Read(p []byte) (n int, err error) { log.WithError(r.err).Error("Error encountered while getting signature bytes") return 0, r.err } - //return r.reader.Read(p) + // return r.reader.Read(p) n, err = r.reader.Read(p) log.WithField("bytes_read", n).Debug("Read from signature") return n, err diff --git a/lib/transport/multi.go b/lib/transport/multi.go index dce7512..9cf14da 100644 --- a/lib/transport/multi.go +++ b/lib/transport/multi.go @@ -63,7 +63,7 @@ func (tmux *TransportMuxer) Name() string { for _, t := range tmux.trans { name += t.Name() + ", " } - //return name[len(name)-3:] + // return name[len(name)-3:] _name := name[len(name)-3:] log.WithField("name", _name).Debug("TransportMuxer: Muxed transport name generated") return _name diff --git a/lib/transport/noise/handshake.go b/lib/transport/noise/handshake.go index 044f0e4..e85557b 100644 --- a/lib/transport/noise/handshake.go +++ b/lib/transport/noise/handshake.go @@ -1,9 +1,10 @@ package noise import ( - "github.com/go-i2p/go-i2p/lib/util/logger" "sync" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/go-i2p/go-i2p/lib/common/router_info" ) diff --git a/lib/transport/noise/incoming_handshake.go b/lib/transport/noise/incoming_handshake.go index 1ae4d5f..b8feb6f 100644 --- a/lib/transport/noise/incoming_handshake.go +++ b/lib/transport/noise/incoming_handshake.go @@ -5,9 +5,10 @@ import ( "crypto/rand" "encoding/binary" "errors" - "github.com/sirupsen/logrus" "io" + "github.com/sirupsen/logrus" + "github.com/flynn/noise" ) @@ -50,7 +51,7 @@ func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, e return } log.WithField("message_length", len(msg)).Debug("Handshake message composed successfully") - //log.Debug("Handshake state created successfully") + // log.Debug("Handshake state created successfully") padBuf := make([]byte, 2+len(payload)) copy(padBuf[2:], payload) msg, _, _, err = state.WriteMessage(msg, padBuf) diff --git a/lib/transport/noise/outgoing_handshake.go b/lib/transport/noise/outgoing_handshake.go index eb18871..f2dc3c6 100644 --- a/lib/transport/noise/outgoing_handshake.go +++ b/lib/transport/noise/outgoing_handshake.go @@ -5,9 +5,10 @@ import ( "crypto/rand" "encoding/binary" "errors" - "github.com/sirupsen/logrus" "io" + "github.com/sirupsen/logrus" + "github.com/flynn/noise" ) diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go index 87def0b..b8f8833 100644 --- a/lib/transport/noise/read_session.go +++ b/lib/transport/noise/read_session.go @@ -2,8 +2,9 @@ package noise import ( "errors" - "github.com/sirupsen/logrus" "sync/atomic" + + "github.com/sirupsen/logrus" ) func (c *NoiseSession) Read(b []byte) (int, error) { diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index c6ce06c..24b9d69 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -3,11 +3,12 @@ package noise import ( "bytes" "fmt" - "github.com/sirupsen/logrus" "net" "sync" "time" + "github.com/sirupsen/logrus" + cb "github.com/emirpasic/gods/queues/circularbuffer" "github.com/flynn/noise" @@ -97,7 +98,7 @@ func (c *NoiseSession) processCallback(publicKey []byte, payload []byte) error { // newBlock allocates a new packet, from hc's free list if possible. func newBlock() []byte { - //return make([]byte, MaxPayloadSize) + // return make([]byte, MaxPayloadSize) block := make([]byte, MaxPayloadSize) log.WithField("block_size", MaxPayloadSize).Debug("Created new block") return block diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index f6c1f5a..469e507 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -8,10 +8,11 @@ package noise import ( "errors" - "github.com/sirupsen/logrus" "net" "sync" + "github.com/sirupsen/logrus" + "github.com/flynn/noise" "github.com/go-i2p/go-i2p/lib/common/data" "github.com/go-i2p/go-i2p/lib/common/router_identity" @@ -37,7 +38,7 @@ var ExampleNoiseListener net.Listener = exampleNoiseTransport // Accept a connection on a listening socket. func (noopt *NoiseTransport) Accept() (net.Conn, error) { log.Debug("NoiseTransport: Accepting new connection") - //return noopt.Listener.Accept() + // return noopt.Listener.Accept() conn, err := noopt.Listener.Accept() if err != nil { log.WithError(err).Error("NoiseTransport: Failed to accept connection") @@ -50,7 +51,7 @@ func (noopt *NoiseTransport) Accept() (net.Conn, error) { // Addr of the transport, for now this is returning the IP:Port the transport is listening on, // but this might actually be the router identity func (noopt *NoiseTransport) Addr() net.Addr { - //return noopt.Listener.Addr() + // return noopt.Listener.Addr() addr := noopt.Listener.Addr() log.WithField("addr", addr.String()).Debug("NoiseTransport: Returning address") return addr @@ -164,7 +165,7 @@ func NewNoiseTransportSocket() (*NoiseTransport, error) { log.WithError(err).Error("Failed to create listener for NoiseTransportSocket") return nil, err } - //return NewNoiseTransport(netSocket), nil + // return NewNoiseTransport(netSocket), nil _transport := NewNoiseTransport(netSocket) log.WithField("addr", netSocket.Addr().String()).Info("Created new NoiseTransportSocket") return _transport, nil diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index 3b56324..19c098a 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -4,8 +4,9 @@ import ( "encoding/binary" "errors" "fmt" - "github.com/sirupsen/logrus" "sync/atomic" + + "github.com/sirupsen/logrus" ) func (c *NoiseSession) Write(b []byte) (int, error) { diff --git a/lib/tunnel/delivery.go b/lib/tunnel/delivery.go index 20075ac..0a6fdb7 100644 --- a/lib/tunnel/delivery.go +++ b/lib/tunnel/delivery.go @@ -3,6 +3,7 @@ package tunnel import ( "encoding/binary" "errors" + common "github.com/go-i2p/go-i2p/lib/common/data" "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/sirupsen/logrus" @@ -329,7 +330,7 @@ func (delivery_instructions DeliveryInstructions) Fragmented() (bool, error) { fragmented := (delivery_instructions[0] & 0x08) == 0x08 log.WithField("fragmented", fragmented).Debug("Fragmented status determined") return fragmented, nil - //return ((delivery_instructions[0] & 0x08) == 0x08), nil + // return ((delivery_instructions[0] & 0x08) == 0x08), nil } log.Error("DeliveryInstructions contains no data") return false, errors.New("DeliveryInstructions contains no data") @@ -378,7 +379,7 @@ func (delivery_instructions DeliveryInstructions) HasTunnelID() (bool, error) { log.WithError(err).Error("Failed to get DeliveryType") return false, err } - //return di_type == DT_TUNNEL, nil + // return di_type == DT_TUNNEL, nil hasTunnelID := di_type == DT_TUNNEL log.WithField("has_tunnel_id", hasTunnelID).Debug("HasTunnelID status determined") return hasTunnelID, nil diff --git a/lib/tunnel/message.go b/lib/tunnel/message.go index f255a93..6c8e12d 100644 --- a/lib/tunnel/message.go +++ b/lib/tunnel/message.go @@ -2,6 +2,7 @@ package tunnel import ( "encoding/binary" + "github.com/sirupsen/logrus" "github.com/go-i2p/go-i2p/lib/crypto" @@ -161,7 +162,7 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData() data_area := decrypted_tunnel_message[4+4+16:] for i := 0; i < len(data_area); i++ { if data_area[i] == 0x00 { - //return data_area[i+1:] + // return data_area[i+1:] delivery_data := data_area[i+1:] log.WithField("delivery_data_length", len(delivery_data)).Debug("Retrieved delivery instruction data") return delivery_data From 54325028527781cf258ba13e22ec052365b7aaad Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Tue, 22 Oct 2024 21:43:49 -0400 Subject: [PATCH 72/94] typo correction --- lib/common/data/date_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/data/date_test.go b/lib/common/data/date_test.go index bf45ffe..4786ebf 100644 --- a/lib/common/data/date_test.go +++ b/lib/common/data/date_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestTimeFromMiliseconds(t *testing.T) { +func TestTimeFromMilliseconds(t *testing.T) { assert := assert.New(t) next_day := Date{0x00, 0x00, 0x00, 0x00, 0x05, 0x26, 0x5c, 0x00} From 882c018c0ccfe64735ed983a5729f9b25a7ac134 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Tue, 22 Oct 2024 22:06:06 -0400 Subject: [PATCH 73/94] log name collision fix --- lib/crypto/aes_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/crypto/aes_test.go b/lib/crypto/aes_test.go index a2311a7..fe54988 100644 --- a/lib/crypto/aes_test.go +++ b/lib/crypto/aes_test.go @@ -6,8 +6,6 @@ import ( "crypto/rand" "encoding/hex" "testing" - - log "github.com/sirupsen/logrus" ) func TestAESEncryptDecrypt(t *testing.T) { From 4dbf537e94be0c7519a9ee4d6451d66981450c67 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Tue, 22 Oct 2024 22:07:39 -0400 Subject: [PATCH 74/94] log name collision fix --- lib/crypto/dsa_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/crypto/dsa_test.go b/lib/crypto/dsa_test.go index 5ca8967..d1c8f3f 100644 --- a/lib/crypto/dsa_test.go +++ b/lib/crypto/dsa_test.go @@ -4,8 +4,6 @@ import ( "crypto/rand" "io" "testing" - - log "github.com/sirupsen/logrus" ) func TestDSA(t *testing.T) { From 5eaa9cf588ab4407a27cbec5f2dec1de68614520 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Tue, 22 Oct 2024 22:10:14 -0400 Subject: [PATCH 75/94] log name collision fix --- lib/crypto/elg_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/crypto/elg_test.go b/lib/crypto/elg_test.go index 36b7c0e..8178b71 100644 --- a/lib/crypto/elg_test.go +++ b/lib/crypto/elg_test.go @@ -6,7 +6,6 @@ import ( "io" "testing" - log "github.com/sirupsen/logrus" "golang.org/x/crypto/openpgp/elgamal" ) From 4e06d3d5edd9badeb6b098df1a219a230b15a537 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Tue, 22 Oct 2024 22:31:19 -0400 Subject: [PATCH 76/94] makefiles --- Makefile | 29 ++++++++++++++- doc/tests/aes.mk | 17 +++++++++ doc/tests/base32.mk | 4 ++ doc/tests/base64.mk | 4 ++ doc/tests/build_request_record.mk | 24 ++++++++++++ doc/tests/certificate.mk | 61 +++++++++++++++++++++++++++++++ doc/tests/date.mk | 2 + doc/tests/dsa.mk | 20 ++++++++++ doc/tests/ed25519.mk | 7 ++++ doc/tests/elg.mk | 24 ++++++++++++ doc/tests/header.mk | 30 +++++++++++++++ doc/tests/hmac.mk | 7 ++++ doc/tests/integer.mk | 15 ++++++++ doc/tests/key_certificate.mk | 23 ++++++++++++ doc/tests/keys_and_cert.mk | 30 +++++++++++++++ doc/tests/lease_set.mk | 22 +++++++++++ doc/tests/mapping.mk | 28 ++++++++++++++ doc/tests/mapping_values.mk | 2 + doc/tests/noise.mk | 11 ++++++ doc/tests/router_address.mk | 19 ++++++++++ doc/tests/router_info.mk | 26 +++++++++++++ doc/tests/string.mk | 27 ++++++++++++++ doc/tests/su3.mk | 11 ++++++ doc/tests/tunnel.mk | 22 +++++++++++ 24 files changed, 464 insertions(+), 1 deletion(-) create mode 100644 doc/tests/aes.mk create mode 100644 doc/tests/base32.mk create mode 100644 doc/tests/base64.mk create mode 100644 doc/tests/build_request_record.mk create mode 100644 doc/tests/certificate.mk create mode 100644 doc/tests/date.mk create mode 100644 doc/tests/dsa.mk create mode 100644 doc/tests/ed25519.mk create mode 100644 doc/tests/elg.mk create mode 100644 doc/tests/header.mk create mode 100644 doc/tests/hmac.mk create mode 100644 doc/tests/integer.mk create mode 100644 doc/tests/key_certificate.mk create mode 100644 doc/tests/keys_and_cert.mk create mode 100644 doc/tests/lease_set.mk create mode 100644 doc/tests/mapping.mk create mode 100644 doc/tests/mapping_values.mk create mode 100644 doc/tests/noise.mk create mode 100644 doc/tests/router_address.mk create mode 100644 doc/tests/router_info.mk create mode 100644 doc/tests/string.mk create mode 100644 doc/tests/su3.mk create mode 100644 doc/tests/tunnel.mk diff --git a/Makefile b/Makefile index 064d1f7..bf6901a 100644 --- a/Makefile +++ b/Makefile @@ -46,4 +46,31 @@ callvis: go-callvis -format svg -focus upgrade -group pkg,type -limit github.com/go-i2p/go-i2p github.com/go-i2p/go-i2p godoc: - find lib -type d -exec bash -c "ls {}/*.go && godocdown -o ./{}/doc.md ./{}" \; \ No newline at end of file + find lib -type d -exec bash -c "ls {}/*.go && godocdown -o ./{}/doc.md ./{}" \; + +# Include test definitions +-include doc/tests/*.mk + +# Define the all-tests target that runs every test suite +test-all: test-string-all \ + test-mapping-all \ + test-crypto-aes-all \ + test-crypto-dsa-all \ + test-crypto-ed25519-all \ + test-crypto-elg-all \ + test-crypto-hmac-all \ + test-i2np-header-all \ + test-i2np-build-request-all \ + test-key-cert-all \ + test-keys-cert-all \ + test-lease-set-all \ + test-noise-transport-all \ + test-router-address-all \ + test-router-info-all \ + test-su3-all \ + test-tunnel-all + +#-include $(shell find doc/tests -type f -name '*.mk') #search for .mk files recursively + +#test-base64-encode-decode-not-mangled: + #go test -v ./lib/common/base64 -run TestEncodeDecodeNotMangled \ No newline at end of file diff --git a/doc/tests/aes.mk b/doc/tests/aes.mk new file mode 100644 index 0000000..382be5c --- /dev/null +++ b/doc/tests/aes.mk @@ -0,0 +1,17 @@ +test-crypto-aes-all: test-crypto-aes-core test-crypto-aes-validation test-crypto-aes-padding + +test-crypto-aes-core: + go test -v ./lib/crypto -run TestAESEncryptDecrypt + +test-crypto-aes-validation: + go test -v ./lib/crypto -run TestAESEncryptInvalidKey + go test -v ./lib/crypto -run TestAESDecryptInvalidInput + +test-crypto-aes-padding: + go test -v ./lib/crypto -run TestPKCS7PadUnpad + go test -v ./lib/crypto -run TestPKCS7UnpadInvalidInput + +.PHONY: test-crypto-aes-all \ + test-crypto-aes-core \ + test-crypto-aes-validation \ + test-crypto-aes-padding \ No newline at end of file diff --git a/doc/tests/base32.mk b/doc/tests/base32.mk new file mode 100644 index 0000000..b0d0ad6 --- /dev/null +++ b/doc/tests/base32.mk @@ -0,0 +1,4 @@ +test-base32-encode-decode-not-mangled: + go test -v ./lib/common/base32 -run TestEncodeDecodeNotMangled + +.PHONY: test-base32-encode-decode-not-mangled \ No newline at end of file diff --git a/doc/tests/base64.mk b/doc/tests/base64.mk new file mode 100644 index 0000000..23db4b9 --- /dev/null +++ b/doc/tests/base64.mk @@ -0,0 +1,4 @@ +test-base64-encode-decode-not-mangled: + go test -v ./lib/common/base64 -run TestEncodeDecodeNotMangled + +.PHONY: test-base64-encode-decode-not-mangled \ No newline at end of file diff --git a/doc/tests/build_request_record.mk b/doc/tests/build_request_record.mk new file mode 100644 index 0000000..3aadcdf --- /dev/null +++ b/doc/tests/build_request_record.mk @@ -0,0 +1,24 @@ +test-build-request-all: test-build-request-receive test-build-request-ident test-build-request-components + +test-build-request-receive: + go test -v ./lib/i2np -run TestReadBuildRequestRecordReceiveTunnel + +test-build-request-ident: + go test -v ./lib/i2np -run TestReadBuildRequestRecordOurIdent + +test-build-request-components: + go test -v ./lib/i2np -run TestReadBuildRequestRecordNextTunnel + go test -v ./lib/i2np -run TestReadBuildRequestRecordNextIdent + go test -v ./lib/i2np -run TestReadBuildRequestRecordLayerKey + go test -v ./lib/i2np -run TestReadBuildRequestRecordIVKey + go test -v ./lib/i2np -run TestReadBuildRequestRecordReplyKey + go test -v ./lib/i2np -run TestReadBuildRequestRecordReplyIV + go test -v ./lib/i2np -run TestReadBuildRequestRecordFlag + go test -v ./lib/i2np -run TestReadBuildRequestRecordRequestTime + go test -v ./lib/i2np -run TestReadBuildRequestRecordSendMessageID + go test -v ./lib/i2np -run TestReadBuildRequestRecordPadding + +.PHONY: test-build-request-all \ + test-build-request-receive \ + test-build-request-ident \ + test-build-request-components diff --git a/doc/tests/certificate.mk b/doc/tests/certificate.mk new file mode 100644 index 0000000..420fd8f --- /dev/null +++ b/doc/tests/certificate.mk @@ -0,0 +1,61 @@ + +test-cert-all: test-cert-type test-cert-length test-cert-data test-cert-read test-cert-length-correct test-cert-length-too-short test-cert-length-data-short test-cert-data-correct test-cert-data-too-long test-cert-data-too-short test-cert-read-correct test-cert-read-short test-cert-read-remainder test-cert-read-invalid + +test-cert-type: + go test -v ./lib/common/certificate -run TestCertificateTypeIsFirstByte + +test-cert-length: + go test -v ./lib/common/certificate -run TestCertificateLength + +test-cert-data: + go test -v ./lib/common/certificate -run TestCertificateData + +test-cert-read: + go test -v ./lib/common/certificate -run TestReadCertificate + +test-cert-length-correct: + go test -v ./lib/common/certificate -run TestCertificateLengthCorrect + +test-cert-length-too-short: + go test -v ./lib/common/certificate -run TestCertificateLengthErrWhenTooShort + +test-cert-length-data-short: + go test -v ./lib/common/certificate -run TestCertificateLengthErrWhenDataTooShort + +test-cert-data-correct: + go test -v ./lib/common/certificate -run TestCertificateDataWhenCorrectSize + +test-cert-data-too-long: + go test -v ./lib/common/certificate -run TestCertificateDataWhenTooLong + +test-cert-data-too-short: + go test -v ./lib/common/certificate -run TestCertificateDataWhenTooShort + +test-cert-read-correct: + go test -v ./lib/common/certificate -run TestReadCertificateWithCorrectData + +test-cert-read-short: + go test -v ./lib/common/certificate -run TestReadCertificateWithDataTooShort + +test-cert-read-remainder: + go test -v ./lib/common/certificate -run TestReadCertificateWithRemainder + +test-cert-read-invalid: + go test -v ./lib/common/certificate -run TestReadCertificateWithInvalidLength + +# Declare all targets as PHONY +.PHONY: test-cert-all \ + test-cert-type \ + test-cert-length \ + test-cert-data \ + test-cert-read \ + test-cert-length-correct \ + test-cert-length-too-short \ + test-cert-length-data-short \ + test-cert-data-correct \ + test-cert-data-too-long \ + test-cert-data-too-short \ + test-cert-read-correct \ + test-cert-read-short \ + test-cert-read-remainder \ + test-cert-read-invalid \ No newline at end of file diff --git a/doc/tests/date.mk b/doc/tests/date.mk new file mode 100644 index 0000000..5695c77 --- /dev/null +++ b/doc/tests/date.mk @@ -0,0 +1,2 @@ +test-date-time-from-milliseconds: + go test -v ./lib/common/data -run TestTimeFromMilliseconds \ No newline at end of file diff --git a/doc/tests/dsa.mk b/doc/tests/dsa.mk new file mode 100644 index 0000000..418308b --- /dev/null +++ b/doc/tests/dsa.mk @@ -0,0 +1,20 @@ +test-crypto-dsa-all: test-crypto-dsa test-crypto-dsa-benchmarks + +test-crypto-dsa: + go test -v ./lib/crypto -run TestDSA + +test-crypto-dsa-benchmarks: + go test -v ./lib/crypto -bench=DSA -run=^$ + +# Individual benchmarks +test-crypto-dsa-bench-generate: + go test -v ./lib/crypto -bench=DSAGenerate -run=^$ + +test-crypto-dsa-bench-sign-verify: + go test -v ./lib/crypto -bench=DSASignVerify -run=^$ + +.PHONY: test-crypto-dsa-all \ + test-crypto-dsa \ + test-crypto-dsa-benchmarks \ + test-crypto-dsa-bench-generate \ + test-crypto-dsa-bench-sign-verify diff --git a/doc/tests/ed25519.mk b/doc/tests/ed25519.mk new file mode 100644 index 0000000..3d7a5fe --- /dev/null +++ b/doc/tests/ed25519.mk @@ -0,0 +1,7 @@ +test-crypto-ed25519-all: test-crypto-ed25519 + +test-crypto-ed25519: + go test -v ./lib/crypto -run TestEd25519 + +.PHONY: test-crypto-ed25519-all \ + test-crypto-ed25519 diff --git a/doc/tests/elg.mk b/doc/tests/elg.mk new file mode 100644 index 0000000..917725c --- /dev/null +++ b/doc/tests/elg.mk @@ -0,0 +1,24 @@ +test-crypto-elg-all: test-crypto-elg test-crypto-elg-benchmarks + +test-crypto-elg: + go test -v ./lib/crypto -run TestElg + +test-crypto-elg-benchmarks: + go test -v ./lib/crypto -bench=Elg -run=^$ + +# Individual benchmarks +test-crypto-elg-bench-generate: + go test -v ./lib/crypto -bench=ElgGenerate -run=^$ + +test-crypto-elg-bench-encrypt: + go test -v ./lib/crypto -bench=ElgEncrypt -run=^$ + +test-crypto-elg-bench-decrypt: + go test -v ./lib/crypto -bench=ElgDecrypt -run=^$ + +.PHONY: test-crypto-elg-all \ + test-crypto-elg \ + test-crypto-elg-benchmarks \ + test-crypto-elg-bench-generate \ + test-crypto-elg-bench-encrypt \ + test-crypto-elg-bench-decrypt diff --git a/doc/tests/header.mk b/doc/tests/header.mk new file mode 100644 index 0000000..83f6d99 --- /dev/null +++ b/doc/tests/header.mk @@ -0,0 +1,30 @@ + +test-i2np-header-all: test-i2np-type test-i2np-message test-i2np-expiration test-i2np-ntcp-components test-i2np-data test-i2np-regression + +test-i2np-type: + go test -v ./lib/i2np -run TestReadI2NPTypeWith + +test-i2np-message: + go test -v ./lib/i2np -run TestReadI2NPNTCPMessageID + +test-i2np-expiration: + go test -v ./lib/i2np -run TestReadI2NPNTCPMessageExpiration + go test -v ./lib/i2np -run TestReadI2NPSSUMessageExpiration + +test-i2np-ntcp-components: + go test -v ./lib/i2np -run TestReadI2NPNTCPMessageSize + go test -v ./lib/i2np -run TestReadI2NPNTCPMessageChecksum + +test-i2np-data: + go test -v ./lib/i2np -run TestReadI2NPNTCPData + +test-i2np-regression: + go test -v ./lib/i2np -run TestCrasherRegression123781 + +.PHONY: test-i2np-header-all \ + test-i2np-type \ + test-i2np-message \ + test-i2np-expiration \ + test-i2np-ntcp-components \ + test-i2np-data \ + test-i2np-regression \ No newline at end of file diff --git a/doc/tests/hmac.mk b/doc/tests/hmac.mk new file mode 100644 index 0000000..4309d08 --- /dev/null +++ b/doc/tests/hmac.mk @@ -0,0 +1,7 @@ +test-crypto-hmac-all: test-crypto-hmac + +test-crypto-hmac: + go test -v ./lib/crypto -run Test_I2PHMAC + +.PHONY: test-crypto-hmac-all \ + test-crypto-hmac diff --git a/doc/tests/integer.mk b/doc/tests/integer.mk new file mode 100644 index 0000000..6185733 --- /dev/null +++ b/doc/tests/integer.mk @@ -0,0 +1,15 @@ +test-integer-all: test-integer-big-endian test-integer-one-byte test-integer-zero + +test-integer-big-endian: + go test -v ./lib/common/integer -run TestIntegerBigEndian + +test-integer-one-byte: + go test -v ./lib/common/integer -run TestWorksWithOneByte + +test-integer-zero: + go test -v ./lib/common/integer -run TestIsZeroWithNoData + +.PHONY: test-integer-all \ + test-integer-big-endian \ + test-integer-one-byte \ + test-integer-zero diff --git a/doc/tests/key_certificate.mk b/doc/tests/key_certificate.mk new file mode 100644 index 0000000..ee5833f --- /dev/null +++ b/doc/tests/key_certificate.mk @@ -0,0 +1,23 @@ +test-key-cert-all: test-key-cert-signing test-key-cert-public test-key-cert-construct + +test-key-cert-signing: + go test -v ./lib/common/key_certificate -run TestSingingPublicKeyTypeReturnsCorrectInteger + go test -v ./lib/common/key_certificate -run TestSingingPublicKeyTypeReportsWhenDataTooSmall + go test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyReportsWhenDataTooSmall + go test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithDSASHA1 + go test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithP256 + go test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithP384 + go test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithP521 + +test-key-cert-public: + go test -v ./lib/common/key_certificate -run TestPublicKeyTypeReturnsCorrectInteger + go test -v ./lib/common/key_certificate -run TestPublicKeyTypeReportsWhenDataTooSmall + +test-key-cert-construct: + go test -v ./lib/common/key_certificate -run TestConstructPublicKeyReportsWhenDataTooSmall + go test -v ./lib/common/key_certificate -run TestConstructPublicKeyReturnsCorrectDataWithElg + +.PHONY: test-key-cert-all \ + test-key-cert-signing \ + test-key-cert-public \ + test-key-cert-construct \ No newline at end of file diff --git a/doc/tests/keys_and_cert.mk b/doc/tests/keys_and_cert.mk new file mode 100644 index 0000000..dbe2890 --- /dev/null +++ b/doc/tests/keys_and_cert.mk @@ -0,0 +1,30 @@ +test-keys-cert-all: test-keys-cert-certificate test-keys-cert-public test-keys-cert-signing test-keys-cert-creation + +test-keys-cert-certificate: + go test -v ./lib/common/keys_and_cert -run TestCertificateWithValidData + +test-keys-cert-public: + go test -v ./lib/common/keys_and_cert -run TestPublicKeyWithBadData + go test -v ./lib/common/keys_and_cert -run TestPublicKeyWithBadCertificate + go test -v ./lib/common/keys_and_cert -run TestPublicKeyWithNullCertificate + go test -v ./lib/common/keys_and_cert -run TestPublicKeyWithKeyCertificate + +test-keys-cert-signing: + go test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithBadData + go test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithBadCertificate + go test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithNullCertificate + go test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithKeyCertificate + +test-keys-cert-creation: + go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithMissingData + go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithMissingCertData + go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithCertificate + go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithoutCertificate + go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithCertificateAndRemainder + go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithoutCertificateAndRemainder + +.PHONY: test-keys-cert-all \ + test-keys-cert-certificate \ + test-keys-cert-public \ + test-keys-cert-signing \ + test-keys-cert-creation \ No newline at end of file diff --git a/doc/tests/lease_set.mk b/doc/tests/lease_set.mk new file mode 100644 index 0000000..75268bd --- /dev/null +++ b/doc/tests/lease_set.mk @@ -0,0 +1,22 @@ +test-lease-set-all: test-lease-set-basic test-lease-set-leases test-lease-set-expiration + +test-lease-set-basic: + go test -v ./lib/common/lease_set -run TestDestinationIsCorrect + go test -v ./lib/common/lease_set -run TestPublicKeyIsCorrect + go test -v ./lib/common/lease_set -run TestSigningKeyIsCorrect + go test -v ./lib/common/lease_set -run TestSignatureIsCorrect + +test-lease-set-leases: + go test -v ./lib/common/lease_set -run TestLeaseCountCorrect + go test -v ./lib/common/lease_set -run TestLeaseCountCorrectWithMultiple + go test -v ./lib/common/lease_set -run TestLeaseCountErrorWithTooMany + go test -v ./lib/common/lease_set -run TestLeasesHaveCorrectData + +test-lease-set-expiration: + go test -v ./lib/common/lease_set -run TestNewestExpirationIsCorrect + go test -v ./lib/common/lease_set -run TestOldestExpirationIsCorrect + +.PHONY: test-lease-set-all \ + test-lease-set-basic \ + test-lease-set-leases \ + test-lease-set-expiration diff --git a/doc/tests/mapping.mk b/doc/tests/mapping.mk new file mode 100644 index 0000000..c251728 --- /dev/null +++ b/doc/tests/mapping.mk @@ -0,0 +1,28 @@ +test-mapping-all: test-mapping-values test-mapping-duplicates test-mapping-conversion test-mapping-utils + +test-mapping-values: + go test -v ./lib/common/data -run TestValuesExclusesPairWithBadData + go test -v ./lib/common/data -run TestValuesWarnsMissingData + go test -v ./lib/common/data -run TestValuesWarnsExtraData + go test -v ./lib/common/data -run TestValuesEnforcesEqualDelimitor + go test -v ./lib/common/data -run TestValuesEnforcedSemicolonDelimitor + go test -v ./lib/common/data -run TestValuesReturnsValues + +test-mapping-duplicates: + go test -v ./lib/common/data -run TestHasDuplicateKeysTrueWhenDuplicates + go test -v ./lib/common/data -run TestHasDuplicateKeysFalseWithoutDuplicates + go test -v ./lib/common/data -run TestReadMappingHasDuplicateKeys + +test-mapping-conversion: + go test -v ./lib/common/data -run TestGoMapToMappingProducesCorrectMapping + go test -v ./lib/common/data -run TestFullGoMapToMappingProducesCorrectMapping + +test-mapping-utils: + go test -v ./lib/common/data -run TestStopValueRead + go test -v ./lib/common/data -run TestBeginsWith + +.PHONY: test-mapping-all \ + test-mapping-values \ + test-mapping-duplicates \ + test-mapping-conversion \ + test-mapping-utils \ No newline at end of file diff --git a/doc/tests/mapping_values.mk b/doc/tests/mapping_values.mk new file mode 100644 index 0000000..9da2855 --- /dev/null +++ b/doc/tests/mapping_values.mk @@ -0,0 +1,2 @@ +test-mapping-values-order: + go test -v ./lib/common/data -run TestMappingOrderSortsValuesThenKeys \ No newline at end of file diff --git a/doc/tests/noise.mk b/doc/tests/noise.mk new file mode 100644 index 0000000..39f3d52 --- /dev/null +++ b/doc/tests/noise.mk @@ -0,0 +1,11 @@ +test-noise-transport-all: test-noise-packet-encryption test-noise-transport-connection + +test-noise-packet-encryption: + go test -v ./lib/transport/noise -run TestEncryptDecryptPacketOffline + +test-noise-transport-connection: + go test -v ./lib/transport/noise -run TestTransport + +.PHONY: test-noise-transport-all \ + test-noise-packet-encryption \ + test-noise-transport-connection diff --git a/doc/tests/router_address.mk b/doc/tests/router_address.mk new file mode 100644 index 0000000..959f19e --- /dev/null +++ b/doc/tests/router_address.mk @@ -0,0 +1,19 @@ +test-router-address-all: test-router-address-validation test-router-address-functionality test-router-address-fuzz + +test-router-address-validation: + go test -v ./lib/common/router_address -run TestCheckValidReportsEmptySlice + go test -v ./lib/common/router_address -run TestCheckRouterAddressValidReportsDataMissing + go test -v ./lib/common/router_address -run TestCheckRouterAddressValidNoErrWithValidData + +test-router-address-functionality: + go test -v ./lib/common/router_address -run TestRouterAddressCostReturnsFirstByte + go test -v ./lib/common/router_address -run TestRouterAddressExpirationReturnsCorrectData + go test -v ./lib/common/router_address -run TestReadRouterAddressReturnsCorrectRemainderWithoutError + +test-router-address-fuzz: + go test -v ./lib/common/router_address -run TestCorrectsFuzzCrasher1 + +.PHONY: test-router-address-all \ + test-router-address-validation \ + test-router-address-functionality \ + test-router-address-fuzz \ No newline at end of file diff --git a/doc/tests/router_info.mk b/doc/tests/router_info.mk new file mode 100644 index 0000000..fd1f1ac --- /dev/null +++ b/doc/tests/router_info.mk @@ -0,0 +1,26 @@ +test-router-info-all: test-router-info-published test-router-info-addresses test-router-info-identity test-router-info-misc + +test-router-info-published: + go test -v ./lib/common/router_info -run TestPublishedReturnsCorrectDate + go test -v ./lib/common/router_info -run TestPublishedReturnsCorrectErrorWithPartialDate + go test -v ./lib/common/router_info -run TestPublishedReturnsCorrectErrorWithInvalidData + +test-router-info-addresses: + go test -v ./lib/common/router_info -run TestRouterAddressCountReturnsCorrectCount + go test -v ./lib/common/router_info -run TestRouterAddressCountReturnsCorrectErrorWithInvalidData + go test -v ./lib/common/router_info -run TestRouterAddressesReturnsAddresses + go test -v ./lib/common/router_info -run TestRouterAddressesReturnsAddressesWithMultiple + +test-router-info-identity: + go test -v ./lib/common/router_info -run TestRouterIdentityIsCorrect + +test-router-info-misc: + go test -v ./lib/common/router_info -run TestPeerSizeIsZero + go test -v ./lib/common/router_info -run TestOptionsAreCorrect + go test -v ./lib/common/router_info -run TestSignatureIsCorrectSize + +.PHONY: test-router-info-all \ + test-router-info-published \ + test-router-info-addresses \ + test-router-info-identity \ + test-router-info-misc diff --git a/doc/tests/string.mk b/doc/tests/string.mk new file mode 100644 index 0000000..10ffd37 --- /dev/null +++ b/doc/tests/string.mk @@ -0,0 +1,27 @@ +test-string-all: test-string-length test-string-data test-string-conversion test-string-read + +test-string-length: + go test -v ./lib/common/data -run TestStringReportsCorrectLength + go test -v ./lib/common/data -run TestI2PStringReportsLengthZeroError + go test -v ./lib/common/data -run TestI2PStringReportsExtraDataError + go test -v ./lib/common/data -run TestI2PStringDataReportsLengthZeroError + +test-string-data: + go test -v ./lib/common/data -run TestI2PStringDataReportsExtraDataError + go test -v ./lib/common/data -run TestI2PStringDataEmptyWhenZeroLength + go test -v ./lib/common/data -run TestI2PStringDataErrorWhenNonZeroLengthOnly + +test-string-conversion: + go test -v ./lib/common/data -run TestToI2PI2PStringFormatsCorrectly + go test -v ./lib/common/data -run TestToI2PStringReportsOverflows + +test-string-read: + go test -v ./lib/common/data -run TestReadStringReadsLength + go test -v ./lib/common/data -run TestReadI2PStringErrWhenEmptySlice + go test -v ./lib/common/data -run TestReadI2PStringErrWhenDataTooShort + +.PHONY: test-string-all \ + test-string-length \ + test-string-data \ + test-string-conversion \ + test-string-read diff --git a/doc/tests/su3.mk b/doc/tests/su3.mk new file mode 100644 index 0000000..c22b655 --- /dev/null +++ b/doc/tests/su3.mk @@ -0,0 +1,11 @@ +test-su3-all: test-su3-read test-su3-signature + +test-su3-read: + go test -v ./lib/su3 -run TestRead + +test-su3-signature: + go test -v ./lib/su3 -run TestReadSignatureFirst + +.PHONY: test-su3-all \ + test-su3-read \ + test-su3-signature diff --git a/doc/tests/tunnel.mk b/doc/tests/tunnel.mk new file mode 100644 index 0000000..18f4366 --- /dev/null +++ b/doc/tests/tunnel.mk @@ -0,0 +1,22 @@ +test-tunnel-all: test-tunnel-delivery-instructions test-tunnel-message + +# Tests from delivery_test.go +test-tunnel-delivery-instructions: + go test -v ./lib/tunnel -run TestReadDeliveryInstructions + +# Tests from message_test.go +test-tunnel-message: test-tunnel-message-padding test-tunnel-message-fragments + +test-tunnel-message-padding: + go test -v ./lib/tunnel -run TestDeliveryInstructionDataWithNoPadding + go test -v ./lib/tunnel -run TestDeliveryInstructionDataWithSomePadding + go test -v ./lib/tunnel -run TestDeliveryInstructionDataWithOnlyPadding + +test-tunnel-message-fragments: + go test -v ./lib/tunnel -run TestDeliveryInstructionsWithFragments + +.PHONY: test-tunnel-all \ + test-tunnel-delivery-instructions \ + test-tunnel-message \ + test-tunnel-message-padding \ + test-tunnel-message-fragments From 677aac500efa64a656c14086969bfa01cc2b0d1a Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Wed, 23 Oct 2024 00:06:06 -0400 Subject: [PATCH 77/94] fix logger naming collision with other libs --- lib/common/certificate/certificate.go | 2 +- lib/common/data/date.go | 2 +- lib/common/destination/destination.go | 2 +- lib/common/key_certificate/key_certificate.go | 2 +- lib/common/keys_and_cert/keys_and_cert.go | 2 +- lib/common/lease_set/lease_set.go | 2 +- lib/common/router_address/router_address.go | 2 +- lib/common/router_identity/router_identity.go | 2 +- lib/common/router_info/router_info.go | 2 +- lib/common/session_tag/session_tag.go | 2 +- lib/common/signature/signature.go | 2 +- lib/crypto/aes.go | 2 +- lib/i2np/build_request_record.go | 2 +- lib/netdb/reseed/reseed.go | 2 +- lib/netdb/std.go | 2 +- lib/router/router.go | 2 +- lib/su3/su3.go | 2 +- lib/transport/multi.go | 2 +- lib/transport/noise/handshake.go | 2 +- lib/tunnel/delivery.go | 2 +- lib/util/logger/log.go | 10 +++++----- main.go | 2 +- 22 files changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/common/certificate/certificate.go b/lib/common/certificate/certificate.go index 1834faf..73f0c06 100644 --- a/lib/common/certificate/certificate.go +++ b/lib/common/certificate/certificate.go @@ -13,7 +13,7 @@ import ( . "github.com/go-i2p/go-i2p/lib/common/data" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() // Certificate Types const ( diff --git a/lib/common/data/date.go b/lib/common/data/date.go index f543e1c..a97df40 100644 --- a/lib/common/data/date.go +++ b/lib/common/data/date.go @@ -9,7 +9,7 @@ import ( "github.com/sirupsen/logrus" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() // DATE_SIZE is the length in bytes of an I2P Date. const DATE_SIZE = 8 diff --git a/lib/common/destination/destination.go b/lib/common/destination/destination.go index 2a1a316..16a536f 100644 --- a/lib/common/destination/destination.go +++ b/lib/common/destination/destination.go @@ -14,7 +14,7 @@ import ( "github.com/go-i2p/go-i2p/lib/crypto" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() /* [Destination] diff --git a/lib/common/key_certificate/key_certificate.go b/lib/common/key_certificate/key_certificate.go index 2748fa7..c52089e 100644 --- a/lib/common/key_certificate/key_certificate.go +++ b/lib/common/key_certificate/key_certificate.go @@ -38,7 +38,7 @@ import ( "github.com/go-i2p/go-i2p/lib/crypto" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() // Key Certificate Signing Key Types const ( diff --git a/lib/common/keys_and_cert/keys_and_cert.go b/lib/common/keys_and_cert/keys_and_cert.go index bc46c5e..25e09ce 100644 --- a/lib/common/keys_and_cert/keys_and_cert.go +++ b/lib/common/keys_and_cert/keys_and_cert.go @@ -12,7 +12,7 @@ import ( "github.com/sirupsen/logrus" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() // Sizes of various KeysAndCert structures and requirements const ( diff --git a/lib/common/lease_set/lease_set.go b/lib/common/lease_set/lease_set.go index a6d1b69..8736039 100644 --- a/lib/common/lease_set/lease_set.go +++ b/lib/common/lease_set/lease_set.go @@ -17,7 +17,7 @@ import ( "github.com/go-i2p/go-i2p/lib/crypto" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() // Sizes of various structures in an I2P LeaseSet const ( diff --git a/lib/common/router_address/router_address.go b/lib/common/router_address/router_address.go index 81479d8..a1a46ad 100644 --- a/lib/common/router_address/router_address.go +++ b/lib/common/router_address/router_address.go @@ -19,7 +19,7 @@ const ( ROUTER_ADDRESS_MIN_SIZE = 9 ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() /* [RouterAddress] diff --git a/lib/common/router_identity/router_identity.go b/lib/common/router_identity/router_identity.go index 032e560..01063c4 100644 --- a/lib/common/router_identity/router_identity.go +++ b/lib/common/router_identity/router_identity.go @@ -7,7 +7,7 @@ import ( "github.com/sirupsen/logrus" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() /* [RouterIdentity] diff --git a/lib/common/router_info/router_info.go b/lib/common/router_info/router_info.go index 2cf6c1f..06131bb 100644 --- a/lib/common/router_info/router_info.go +++ b/lib/common/router_info/router_info.go @@ -15,7 +15,7 @@ import ( . "github.com/go-i2p/go-i2p/lib/common/signature" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() const ROUTER_INFO_MIN_SIZE = 439 diff --git a/lib/common/session_tag/session_tag.go b/lib/common/session_tag/session_tag.go index 6509836..6c48ae2 100644 --- a/lib/common/session_tag/session_tag.go +++ b/lib/common/session_tag/session_tag.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() /* [SessionKey] diff --git a/lib/common/signature/signature.go b/lib/common/signature/signature.go index e55f8f3..188421e 100644 --- a/lib/common/signature/signature.go +++ b/lib/common/signature/signature.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() // Lengths of signature keys const ( diff --git a/lib/crypto/aes.go b/lib/crypto/aes.go index 96cf3b8..97c418e 100644 --- a/lib/crypto/aes.go +++ b/lib/crypto/aes.go @@ -10,7 +10,7 @@ import ( "github.com/sirupsen/logrus" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() // AESSymmetricKey represents a symmetric key for AES encryption/decryption type AESSymmetricKey struct { diff --git a/lib/i2np/build_request_record.go b/lib/i2np/build_request_record.go index 9d81cea..45255f8 100644 --- a/lib/i2np/build_request_record.go +++ b/lib/i2np/build_request_record.go @@ -12,7 +12,7 @@ import ( "github.com/go-i2p/go-i2p/lib/util/logger" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() /* I2P I2NP BuildRequestRecord diff --git a/lib/netdb/reseed/reseed.go b/lib/netdb/reseed/reseed.go index 9aba111..0ec6e4e 100644 --- a/lib/netdb/reseed/reseed.go +++ b/lib/netdb/reseed/reseed.go @@ -18,7 +18,7 @@ import ( "github.com/go-i2p/go-i2p/lib/su3" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() const ( I2pUserAgent = "Wget/1.11.4" diff --git a/lib/netdb/std.go b/lib/netdb/std.go index 1e46719..013d95e 100644 --- a/lib/netdb/std.go +++ b/lib/netdb/std.go @@ -21,7 +21,7 @@ import ( "github.com/go-i2p/go-i2p/lib/util" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() // standard network database implementation using local filesystem skiplist type StdNetDB struct { diff --git a/lib/router/router.go b/lib/router/router.go index c128a92..70927ed 100644 --- a/lib/router/router.go +++ b/lib/router/router.go @@ -10,7 +10,7 @@ import ( "github.com/go-i2p/go-i2p/lib/netdb" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() // i2p router type type Router struct { diff --git a/lib/su3/su3.go b/lib/su3/su3.go index e28ba2f..cd59751 100644 --- a/lib/su3/su3.go +++ b/lib/su3/su3.go @@ -83,7 +83,7 @@ import ( "github.com/sirupsen/logrus" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() type SignatureType string diff --git a/lib/transport/multi.go b/lib/transport/multi.go index 9cf14da..8538839 100644 --- a/lib/transport/multi.go +++ b/lib/transport/multi.go @@ -6,7 +6,7 @@ import ( "github.com/go-i2p/go-i2p/lib/util/logger" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() // muxes multiple transports into 1 Transport // implements transport.Transport diff --git a/lib/transport/noise/handshake.go b/lib/transport/noise/handshake.go index e85557b..bf3849c 100644 --- a/lib/transport/noise/handshake.go +++ b/lib/transport/noise/handshake.go @@ -8,7 +8,7 @@ import ( "github.com/go-i2p/go-i2p/lib/common/router_info" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error { log.WithField("router_info", routerInfo.IdentHash()).Debug("Starting Noise handshake") diff --git a/lib/tunnel/delivery.go b/lib/tunnel/delivery.go index 0a6fdb7..498c39e 100644 --- a/lib/tunnel/delivery.go +++ b/lib/tunnel/delivery.go @@ -9,7 +9,7 @@ import ( "github.com/sirupsen/logrus" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() /* I2P First Fragment Delivery Instructions diff --git a/lib/util/logger/log.go b/lib/util/logger/log.go index 442cbf3..16f6215 100644 --- a/lib/util/logger/log.go +++ b/lib/util/logger/log.go @@ -14,7 +14,7 @@ var ( once sync.Once ) -func InitializeLogger() { +func InitializeGoI2PLogger() { once.Do(func() { log = logrus.New() // We do not want to log by default @@ -38,14 +38,14 @@ func InitializeLogger() { }) } -// GetLogger returns the initialized logger -func GetLogger() *logrus.Logger { +// GetGoI2PLogger returns the initialized logger +func GetGoI2PLogger() *logrus.Logger { if log == nil { - InitializeLogger() + InitializeGoI2PLogger() } return log } func init() { - InitializeLogger() + InitializeGoI2PLogger() } diff --git a/main.go b/main.go index 4d28046..9c3847e 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "github.com/go-i2p/go-i2p/lib/util/signals" ) -var log = logger.GetLogger() +var log = logger.GetGoI2PLogger() func main() { netDbPath := flag.String("netDb", config.DefaultNetDbConfig.Path, "Path to the netDb") From 748dc8a66f171f3761ae79739d7998f4470704d6 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Wed, 23 Oct 2024 00:11:46 -0400 Subject: [PATCH 78/94] tweaks --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ec75f4c..f243bef 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ export DEBUG_I2P=warn export DEBUG_I2P=error ``` -In case I2P_DEBUG is set to an unrecognized variable, it will fall back to "debug". +If I2P_DEBUG is set to an unrecognized variable, it will fall back to "debug". ## Contributing From f0d9f89ed9aeb320e4a2faca5bae5dd2700e324b Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 24 Oct 2024 14:05:06 -0400 Subject: [PATCH 79/94] Mkdir -> MkdirAll --- lib/netdb/std.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/netdb/std.go b/lib/netdb/std.go index 013d95e..e9df933 100644 --- a/lib/netdb/std.go +++ b/lib/netdb/std.go @@ -289,11 +289,11 @@ func (db *StdNetDB) Create() (err error) { // log.Infof("Create network database in %s", p) log.WithField("path", p).Debug("Creating network database directory") // create root for skiplist - err = os.Mkdir(p, mode) + err = os.MkdirAll(p, mode) if err == nil { // create all subdirectories for skiplist for _, c := range base64.I2PEncodeAlphabet { - err = os.Mkdir(filepath.Join(p, fmt.Sprintf("r%c", c)), mode) + err = os.MkdirAll(filepath.Join(p, fmt.Sprintf("r%c", c)), mode) if err != nil { log.WithError(err).Error("Failed to create subdirectory") return From 3f191db37a40120eeff1fca70ede28502343dc54 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 24 Oct 2024 18:03:20 -0400 Subject: [PATCH 80/94] implement TODO for Compatible in NoiseTransport --- lib/transport/noise/transport.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index 469e507..f4f1c12 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -28,6 +28,12 @@ type NoiseTransport struct { peerConnections map[data.Hash]transport.TransportSession } +func (noopt *NoiseTransport) Compatible(routerInfo router_info.RouterInfo) bool { + //TODO implement + //panic("implement me") + return true +} + var exampleNoiseTransport transport.Transport = &NoiseTransport{} // ExampleNoiseListener is not a real Noise Listener, do not use it. From 833836ae6795111c35a58c13cce766a635e4acf5 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 24 Oct 2024 18:58:07 -0400 Subject: [PATCH 81/94] added TestEncryptDecryptPacketObfsOffline --- lib/transport/noise/encrdecr_packet_test.go | 236 ++++++++++++++++++++ 1 file changed, 236 insertions(+) diff --git a/lib/transport/noise/encrdecr_packet_test.go b/lib/transport/noise/encrdecr_packet_test.go index ef4dc81..b689619 100644 --- a/lib/transport/noise/encrdecr_packet_test.go +++ b/lib/transport/noise/encrdecr_packet_test.go @@ -1,6 +1,8 @@ package noise import ( + "crypto/aes" + "crypto/cipher" "crypto/rand" "encoding/binary" "testing" @@ -164,3 +166,237 @@ func TestEncryptDecryptPacketOffline(t *testing.T) { assert.Equal(t, responseData, decryptedResponse, "Decrypted response does not match original data") } +func TestEncryptDecryptPacketObfsOffline(t *testing.T) { + // Simulate Bob's Router Hash (RH_B) + bobRouterHash := make([]byte, 32) + rand.Read(bobRouterHash) + + // Simulate Bob's IV (ri.IV) + bobIV := make([]byte, 16) + rand.Read(bobIV) + + // Create AES cipher block + aesBlock, err := aes.NewCipher(bobRouterHash) + if err != nil { + t.Fatalf("Failed to create AES cipher block: %v", err) + } + + // Create AES CBC encrypter and decrypter + aesEncrypter := cipher.NewCBCEncrypter(aesBlock, bobIV) + aesDecrypter := cipher.NewCBCDecrypter(aesBlock, bobIV) + + // Generate static keypairs + initiatorStatic, err := noise.DH25519.GenerateKeypair(rand.Reader) + if err != nil { + t.Fatalf("Failed to generate initiator static keypair: %v", err) + } + responderStatic, err := noise.DH25519.GenerateKeypair(rand.Reader) + if err != nil { + t.Fatalf("Failed to generate responder static keypair: %v", err) + } + + pattern := noise.HandshakeXK + cipherSuite := noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256) + + // Negotiation + negData := initNegotiationData(nil) + prologue := make([]byte, 2, uint16Size+len(negData)) + binary.BigEndian.PutUint16(prologue, uint16(len(negData))) + prologue = append(prologue, negData...) + + // Alice's Handshake State + initiatorHS, err := noise.NewHandshakeState(noise.Config{ + StaticKeypair: initiatorStatic, + Initiator: true, + Pattern: pattern, + CipherSuite: cipherSuite, + Prologue: prologue, + PeerStatic: responderStatic.Public, // Bob's static public key + }) + if err != nil { + t.Fatalf("Failed to create initiator handshake state: %v", err) + } + + // Bob's Handshake State + responderHS, err := noise.NewHandshakeState(noise.Config{ + StaticKeypair: responderStatic, + Initiator: false, + Pattern: pattern, + CipherSuite: cipherSuite, + Prologue: prologue, + }) + if err != nil { + t.Fatalf("Failed to create responder handshake state: %v", err) + } + + var ( + initiatorSendCS *noise.CipherState + initiatorRecvCS *noise.CipherState + responderSendCS *noise.CipherState + responderRecvCS *noise.CipherState + ) + + // Simulate the handshake message exchange + + // ------------------------------- + // Message 1: Initiator -> Responder + // ------------------------------- + + // Alice writes message 1 + msg1, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil) + if err != nil { + t.Fatalf("Initiator failed to write handshake message 1: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Initiator should not have CipherStates after message 1") + } + + // Encrypt Alice's ephemeral public key using AES-256-CBC + if len(msg1) < 32 { + t.Fatalf("Message 1 is too short to contain ephemeral public key") + } + aliceEphemeralPubKey := msg1[:32] // First 32 bytes + encryptedX := make([]byte, len(aliceEphemeralPubKey)) + aesEncrypter.CryptBlocks(encryptedX, aliceEphemeralPubKey) + + // Construct the modified message 1 + fullMsg1 := append(encryptedX, msg1[32:]...) + + // ------------------------------- + // Responder processes message 1 + // ------------------------------- + + // Extract encrypted ephemeral public key + encryptedXReceived := fullMsg1[:32] + // Decrypt the ephemeral public key + decryptedX := make([]byte, len(encryptedXReceived)) + aesDecrypter.CryptBlocks(decryptedX, encryptedXReceived) + + // Replace the encrypted ephemeral key with the decrypted one + modifiedMsg1 := append(decryptedX, fullMsg1[32:]...) + + // Bob reads message 1 + _, cs0, cs1, err = responderHS.ReadMessage(nil, modifiedMsg1) + if err != nil { + t.Fatalf("Responder failed to read handshake message 1: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Responder should not have CipherStates after reading message 1") + } + + // ------------------------------- + // Message 2: Responder -> Initiator + // ------------------------------- + + // Bob writes message 2 + msg2, cs0, cs1, err := responderHS.WriteMessage(nil, nil) + if err != nil { + t.Fatalf("Responder failed to write handshake message 2: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Responder should not have CipherStates after writing message 2") + } + + // Encrypt Bob's ephemeral public key using AES-256-CBC + if len(msg2) < 32 { + t.Fatalf("Message 2 is too short to contain ephemeral public key") + } + bobEphemeralPubKey := msg2[:32] // First 32 bytes + encryptedY := make([]byte, len(bobEphemeralPubKey)) + aesEncrypter.CryptBlocks(encryptedY, bobEphemeralPubKey) + + // Construct the modified message 2 + fullMsg2 := append(encryptedY, msg2[32:]...) + + // ------------------------------- + // Initiator processes message 2 + // ------------------------------- + + // Extract encrypted ephemeral public key + encryptedYReceived := fullMsg2[:32] + // Decrypt the ephemeral public key + decryptedY := make([]byte, len(encryptedYReceived)) + aesDecrypter.CryptBlocks(decryptedY, encryptedYReceived) + + // Replace the encrypted ephemeral key with the decrypted one + modifiedMsg2 := append(decryptedY, fullMsg2[32:]...) + + // Alice reads message 2 + _, cs0, cs1, err = initiatorHS.ReadMessage(nil, modifiedMsg2) + if err != nil { + t.Fatalf("Initiator failed to read handshake message 2: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Initiator should not have CipherStates after reading message 2") + } + + // ------------------------------- + // Message 3: Initiator -> Responder + // ------------------------------- + + // Alice writes message 3 + msg3, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil) + if err != nil { + t.Fatalf("Initiator failed to write handshake message 3: %v", err) + } + if cs0 == nil || cs1 == nil { + t.Fatalf("Initiator did not receive CipherStates after writing message 3") + } + initiatorSendCS = cs0 + initiatorRecvCS = cs1 + + // Responder processes message 3 + _, cs0, cs1, err = responderHS.ReadMessage(nil, msg3) + if err != nil { + t.Fatalf("Responder failed to read handshake message 3: %v", err) + } + if cs0 == nil || cs1 == nil { + t.Fatalf("Responder did not receive CipherStates after reading message 3") + } + responderRecvCS = cs0 + responderSendCS = cs1 + + // Now both parties have the CipherStates + + // Initiator sends a message to Responder + initiatorSession := &NoiseSession{ + CipherState: initiatorSendCS, + } + responderSession := &NoiseSession{ + CipherState: responderRecvCS, + } + + originalData := []byte("This is a test message.") + _, encryptedPacket, err := initiatorSession.encryptPacket(originalData) + if err != nil { + t.Fatalf("Encryption failed: %v", err) + } + + _, decryptedData, err := responderSession.decryptPacket(encryptedPacket[2:]) + if err != nil { + t.Fatalf("Decryption failed: %v", err) + } + + assert.Equal(t, originalData, decryptedData, "Decrypted data does not match the original data") + + // Responder sends a message to Initiator + responderSession = &NoiseSession{ + CipherState: responderSendCS, + } + initiatorSession = &NoiseSession{ + CipherState: initiatorRecvCS, + } + + responseData := []byte("This is a response message.") + _, encryptedResponse, err := responderSession.encryptPacket(responseData) + if err != nil { + t.Fatalf("Responder encryption failed: %v", err) + } + + _, decryptedResponse, err := initiatorSession.decryptPacket(encryptedResponse[2:]) + if err != nil { + t.Fatalf("Initiator decryption failed: %v", err) + } + + assert.Equal(t, responseData, decryptedResponse, "Decrypted response does not match original data") +} From 971a18de8dd30e3afdc724f3e899370df8e3181a Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 24 Oct 2024 19:23:36 -0400 Subject: [PATCH 82/94] added Compatible warning message --- lib/transport/noise/transport.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index f4f1c12..7c72403 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -31,6 +31,7 @@ type NoiseTransport struct { func (noopt *NoiseTransport) Compatible(routerInfo router_info.RouterInfo) bool { //TODO implement //panic("implement me") + log.Warn("func (noopt *NoiseTransport) Compatible(routerInfo router_info.RouterInfo) is not implemented!") return true } From e6f84c16f6637cc9f5ddc0a01575e0f086e23e30 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 24 Oct 2024 22:56:00 -0400 Subject: [PATCH 83/94] added experimental functions which factor in packet length -encryptPacketDeux -decryptPacketDeux Added test -> TestEncryptDecryptPacketObfsOfflineWithFunc() added new functions in aes.go -EncryptNoPadding -DecryptNoPadding --- lib/crypto/aes.go | 36 +++ lib/transport/noise/encrdecr_packet_test.go | 272 ++++++++++++++++++++ lib/transport/noise/read_session.go | 28 ++ lib/transport/noise/write_session.go | 18 ++ 4 files changed, 354 insertions(+) diff --git a/lib/crypto/aes.go b/lib/crypto/aes.go index 97c418e..1da3c82 100644 --- a/lib/crypto/aes.go +++ b/lib/crypto/aes.go @@ -139,3 +139,39 @@ func pkcs7Unpad(data []byte) ([]byte, error) { log.WithField("unpadded_length", len(unpadded)).Debug("PKCS#7 padding removed") return unpadded, nil } + +// EncryptNoPadding encrypts data using AES-CBC without padding +func (e *AESSymmetricEncrypter) EncryptNoPadding(data []byte) ([]byte, error) { + if len(data)%aes.BlockSize != 0 { + return nil, fmt.Errorf("data length must be a multiple of block size") + } + + block, err := aes.NewCipher(e.Key) + if err != nil { + return nil, err + } + + ciphertext := make([]byte, len(data)) + mode := cipher.NewCBCEncrypter(block, e.IV) + mode.CryptBlocks(ciphertext, data) + + return ciphertext, nil +} + +// DecryptNoPadding decrypts data using AES-CBC without padding +func (d *AESSymmetricDecrypter) DecryptNoPadding(data []byte) ([]byte, error) { + if len(data)%aes.BlockSize != 0 { + return nil, fmt.Errorf("data length must be a multiple of block size") + } + + block, err := aes.NewCipher(d.Key) + if err != nil { + return nil, err + } + + plaintext := make([]byte, len(data)) + mode := cipher.NewCBCDecrypter(block, d.IV) + mode.CryptBlocks(plaintext, data) + + return plaintext, nil +} diff --git a/lib/transport/noise/encrdecr_packet_test.go b/lib/transport/noise/encrdecr_packet_test.go index b689619..41216dd 100644 --- a/lib/transport/noise/encrdecr_packet_test.go +++ b/lib/transport/noise/encrdecr_packet_test.go @@ -5,6 +5,8 @@ import ( "crypto/cipher" "crypto/rand" "encoding/binary" + "fmt" + "github.com/go-i2p/go-i2p/lib/crypto" "testing" "github.com/flynn/noise" @@ -400,3 +402,273 @@ func TestEncryptDecryptPacketObfsOffline(t *testing.T) { assert.Equal(t, responseData, decryptedResponse, "Decrypted response does not match original data") } + +// ObfuscateEphemeralKey encrypts the ephemeral public key in the message using AES-256-CBC without padding +func ObfuscateEphemeralKey(message []byte, aesKey *crypto.AESSymmetricKey) ([]byte, error) { + if len(message) < 32 { + return nil, fmt.Errorf("message is too short to contain ephemeral public key") + } + + // Extract the ephemeral public key (first 32 bytes) + ephemeralPubKey := message[:32] + + // Create AES encrypter + encrypter := &crypto.AESSymmetricEncrypter{ + Key: aesKey.Key, + IV: aesKey.IV, + } + + // Encrypt the ephemeral public key without padding + encryptedKey, err := encrypter.EncryptNoPadding(ephemeralPubKey) + if err != nil { + return nil, err + } + + // Replace the ephemeral public key in the message with the encrypted key + obfuscatedMessage := append(encryptedKey, message[32:]...) + + return obfuscatedMessage, nil +} + +// DeobfuscateEphemeralKey decrypts the ephemeral public key in the message using AES-256-CBC without padding +func DeobfuscateEphemeralKey(message []byte, aesKey *crypto.AESSymmetricKey) ([]byte, error) { + if len(message) < 32 { + return nil, fmt.Errorf("message is too short to contain ephemeral public key") + } + + // Extract the encrypted ephemeral public key (first 32 bytes) + encryptedKey := message[:32] + + // Create AES decrypter + decrypter := &crypto.AESSymmetricDecrypter{ + Key: aesKey.Key, + IV: aesKey.IV, + } + + // Decrypt the ephemeral public key without padding + decryptedKey, err := decrypter.DecryptNoPadding(encryptedKey) + if err != nil { + return nil, err + } + + // Replace the encrypted ephemeral key in the message with the decrypted key + deobfuscatedMessage := append(decryptedKey, message[32:]...) + + return deobfuscatedMessage, nil +} + +// TestEncryptDecryptPacketObfsOffline tests the encryption and decryption with AES obfuscation +func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) { + // Simulate Bob's Router Hash (RH_B) + bobRouterHash := make([]byte, 32) + rand.Read(bobRouterHash) + + // Simulate Bob's IV (ri.IV) + bobIV := make([]byte, 16) + rand.Read(bobIV) + + // Create AES symmetric key + aesKey := &crypto.AESSymmetricKey{ + Key: bobRouterHash, + IV: bobIV, + } + + // Generate static keypairs + initiatorStatic, err := noise.DH25519.GenerateKeypair(rand.Reader) + if err != nil { + t.Fatalf("Failed to generate initiator static keypair: %v", err) + } + responderStatic, err := noise.DH25519.GenerateKeypair(rand.Reader) + if err != nil { + t.Fatalf("Failed to generate responder static keypair: %v", err) + } + + pattern := noise.HandshakeXK + cipherSuite := noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256) + + // Negotiation + negData := initNegotiationData(nil) + prologue := make([]byte, 2+len(negData)) + binary.BigEndian.PutUint16(prologue, uint16(len(negData))) + copy(prologue[2:], negData) + + // Alice's Handshake State + initiatorHS, err := noise.NewHandshakeState(noise.Config{ + StaticKeypair: initiatorStatic, + Initiator: true, + Pattern: pattern, + CipherSuite: cipherSuite, + Prologue: prologue, + PeerStatic: responderStatic.Public, // Bob's static public key + }) + if err != nil { + t.Fatalf("Failed to create initiator handshake state: %v", err) + } + + // Bob's Handshake State + responderHS, err := noise.NewHandshakeState(noise.Config{ + StaticKeypair: responderStatic, + Initiator: false, + Pattern: pattern, + CipherSuite: cipherSuite, + Prologue: prologue, + }) + if err != nil { + t.Fatalf("Failed to create responder handshake state: %v", err) + } + + var ( + initiatorSendCS *noise.CipherState + initiatorRecvCS *noise.CipherState + responderSendCS *noise.CipherState + responderRecvCS *noise.CipherState + ) + + // Simulate the handshake message exchange + + // ------------------------------- + // Message 1: Initiator -> Responder + // ------------------------------- + + // Alice writes message 1 + msg1, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil) + if err != nil { + t.Fatalf("Initiator failed to write handshake message 1: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Initiator should not have CipherStates after message 1") + } + + // Obfuscate Alice's ephemeral public key in message 1 + obfuscatedMsg1, err := ObfuscateEphemeralKey(msg1, aesKey) + if err != nil { + t.Fatalf("Failed to obfuscate message 1: %v", err) + } + + // ------------------------------- + // Responder processes message 1 + // ------------------------------- + + // Deobfuscate Alice's ephemeral public key in message 1 + deobfuscatedMsg1, err := DeobfuscateEphemeralKey(obfuscatedMsg1, aesKey) + if err != nil { + t.Fatalf("Failed to deobfuscate message 1: %v", err) + } + + // Bob reads message 1 + _, cs0, cs1, err = responderHS.ReadMessage(nil, deobfuscatedMsg1) + if err != nil { + t.Fatalf("Responder failed to read handshake message 1: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Responder should not have CipherStates after reading message 1") + } + + // ------------------------------- + // Message 2: Responder -> Initiator + // ------------------------------- + + // Bob writes message 2 + msg2, cs0, cs1, err := responderHS.WriteMessage(nil, nil) + if err != nil { + t.Fatalf("Responder failed to write handshake message 2: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Responder should not have CipherStates after writing message 2") + } + + // Obfuscate Bob's ephemeral public key in message 2 + obfuscatedMsg2, err := ObfuscateEphemeralKey(msg2, aesKey) + if err != nil { + t.Fatalf("Failed to obfuscate message 2: %v", err) + } + + // ------------------------------- + // Initiator processes message 2 + // ------------------------------- + + // Deobfuscate Bob's ephemeral public key in message 2 + deobfuscatedMsg2, err := DeobfuscateEphemeralKey(obfuscatedMsg2, aesKey) + if err != nil { + t.Fatalf("Failed to deobfuscate message 2: %v", err) + } + + // Alice reads message 2 + _, cs0, cs1, err = initiatorHS.ReadMessage(nil, deobfuscatedMsg2) + if err != nil { + t.Fatalf("Initiator failed to read handshake message 2: %v", err) + } + if cs0 != nil || cs1 != nil { + t.Fatalf("Initiator should not have CipherStates after reading message 2") + } + + // ------------------------------- + // Message 3: Initiator -> Responder + // ------------------------------- + + // Alice writes message 3 + msg3, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil) + if err != nil { + t.Fatalf("Initiator failed to write handshake message 3: %v", err) + } + if cs0 == nil || cs1 == nil { + t.Fatalf("Initiator did not receive CipherStates after writing message 3") + } + initiatorSendCS = cs0 + initiatorRecvCS = cs1 + + // Responder processes message 3 + _, cs0, cs1, err = responderHS.ReadMessage(nil, msg3) + if err != nil { + t.Fatalf("Responder failed to read handshake message 3: %v", err) + } + if cs0 == nil || cs1 == nil { + t.Fatalf("Responder did not receive CipherStates after reading message 3") + } + responderRecvCS = cs0 + responderSendCS = cs1 + + // Now both parties have the CipherStates + + // Initiator sends a message to Responder + initiatorSession := &NoiseSession{ + CipherState: initiatorSendCS, + } + responderSession := &NoiseSession{ + CipherState: responderRecvCS, + } + + originalData := []byte("This is a test message.") + _, encryptedPacket, err := initiatorSession.encryptPacketDeux(originalData) + if err != nil { + t.Fatalf("Encryption failed: %v", err) + } + + _, decryptedData, err := responderSession.decryptPacketDeux(encryptedPacket) + if err != nil { + t.Fatalf("Decryption failed: %v", err) + } + + assert.Equal(t, originalData, decryptedData, "Decrypted data does not match the original data") + + // Responder sends a message to Initiator + responderSession = &NoiseSession{ + CipherState: responderSendCS, + } + initiatorSession = &NoiseSession{ + CipherState: initiatorRecvCS, + } + + responseData := []byte("This is a response message.") + _, encryptedResponse, err := responderSession.encryptPacketDeux(responseData) + if err != nil { + t.Fatalf("Responder encryption failed: %v", err) + } + + _, decryptedResponse, err := initiatorSession.decryptPacketDeux(encryptedResponse) + if err != nil { + t.Fatalf("Initiator decryption failed: %v", err) + } + + assert.Equal(t, responseData, decryptedResponse, "Decrypted response does not match original data") +} diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go index b8f8833..af5e63f 100644 --- a/lib/transport/noise/read_session.go +++ b/lib/transport/noise/read_session.go @@ -1,7 +1,9 @@ package noise import ( + "encoding/binary" "errors" + "fmt" "sync/atomic" "github.com/sirupsen/logrus" @@ -83,6 +85,32 @@ func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { b := c.encryptIfNeeded(packet)*/ //c.freeBlock(packet) } +func (ns *NoiseSession) decryptPacketDeux(packet []byte) (int, []byte, error) { + if ns.CipherState == nil { + return 0, nil, fmt.Errorf("CipherState is nil") + } + + if len(packet) < 2 { + return 0, nil, fmt.Errorf("Packet too short to contain length prefix") + } + + // Extract the length prefix + packetLength := binary.BigEndian.Uint16(packet[:2]) + + if len(packet[2:]) < int(packetLength) { + return 0, nil, fmt.Errorf("Packet data is shorter than indicated length") + } + + ciphertext := packet[2 : 2+packetLength] + + // Decrypt the data + plaintext, err := ns.CipherState.Decrypt(nil, nil, ciphertext) + if err != nil { + return 0, nil, err + } + + return len(plaintext), plaintext, nil +} func (c *NoiseSession) readPacketLocked(data []byte) (int, error) { log.WithField("data_length", len(data)).Debug("Starting readPacketLocked") diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index 19c098a..adc346c 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -97,7 +97,25 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { b := c.encryptIfNeeded(packet)*/ //c.freeBlock(packet) } +func (ns *NoiseSession) encryptPacketDeux(plaintext []byte) (int, []byte, error) { + if ns.CipherState == nil { + return 0, nil, fmt.Errorf("CipherState is nil") + } + // Encrypt the data + ciphertext, err := ns.CipherState.Encrypt(nil, nil, plaintext) + if err != nil { + log.Fatalf("unimplemented\nerror:%v\n", err) + } + + // Prepend the length of the ciphertext as a 2-byte big-endian value + packetLength := uint16(len(ciphertext)) + packet := make([]byte, 2+len(ciphertext)) + binary.BigEndian.PutUint16(packet[:2], packetLength) + copy(packet[2:], ciphertext) + + return len(packet), packet, nil +} func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { log.WithField("data_length", len(data)).Debug("NoiseSession: Starting writePacketLocked") From e58d326d89542cffbe2e7b37278df1fc078f521d Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Fri, 25 Oct 2024 21:29:02 -0400 Subject: [PATCH 84/94] Move obfuscation functions to lib/transport/ntcp --- lib/transport/noise/encrdecr_packet_test.go | 64 ++------------------- lib/transport/ntcp/obfs.go | 60 +++++++++++++++++++ 2 files changed, 65 insertions(+), 59 deletions(-) create mode 100644 lib/transport/ntcp/obfs.go diff --git a/lib/transport/noise/encrdecr_packet_test.go b/lib/transport/noise/encrdecr_packet_test.go index 41216dd..b95b210 100644 --- a/lib/transport/noise/encrdecr_packet_test.go +++ b/lib/transport/noise/encrdecr_packet_test.go @@ -5,8 +5,8 @@ import ( "crypto/cipher" "crypto/rand" "encoding/binary" - "fmt" "github.com/go-i2p/go-i2p/lib/crypto" + "github.com/go-i2p/go-i2p/lib/transport/ntcp" "testing" "github.com/flynn/noise" @@ -403,60 +403,6 @@ func TestEncryptDecryptPacketObfsOffline(t *testing.T) { assert.Equal(t, responseData, decryptedResponse, "Decrypted response does not match original data") } -// ObfuscateEphemeralKey encrypts the ephemeral public key in the message using AES-256-CBC without padding -func ObfuscateEphemeralKey(message []byte, aesKey *crypto.AESSymmetricKey) ([]byte, error) { - if len(message) < 32 { - return nil, fmt.Errorf("message is too short to contain ephemeral public key") - } - - // Extract the ephemeral public key (first 32 bytes) - ephemeralPubKey := message[:32] - - // Create AES encrypter - encrypter := &crypto.AESSymmetricEncrypter{ - Key: aesKey.Key, - IV: aesKey.IV, - } - - // Encrypt the ephemeral public key without padding - encryptedKey, err := encrypter.EncryptNoPadding(ephemeralPubKey) - if err != nil { - return nil, err - } - - // Replace the ephemeral public key in the message with the encrypted key - obfuscatedMessage := append(encryptedKey, message[32:]...) - - return obfuscatedMessage, nil -} - -// DeobfuscateEphemeralKey decrypts the ephemeral public key in the message using AES-256-CBC without padding -func DeobfuscateEphemeralKey(message []byte, aesKey *crypto.AESSymmetricKey) ([]byte, error) { - if len(message) < 32 { - return nil, fmt.Errorf("message is too short to contain ephemeral public key") - } - - // Extract the encrypted ephemeral public key (first 32 bytes) - encryptedKey := message[:32] - - // Create AES decrypter - decrypter := &crypto.AESSymmetricDecrypter{ - Key: aesKey.Key, - IV: aesKey.IV, - } - - // Decrypt the ephemeral public key without padding - decryptedKey, err := decrypter.DecryptNoPadding(encryptedKey) - if err != nil { - return nil, err - } - - // Replace the encrypted ephemeral key in the message with the decrypted key - deobfuscatedMessage := append(decryptedKey, message[32:]...) - - return deobfuscatedMessage, nil -} - // TestEncryptDecryptPacketObfsOffline tests the encryption and decryption with AES obfuscation func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) { // Simulate Bob's Router Hash (RH_B) @@ -540,7 +486,7 @@ func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) { } // Obfuscate Alice's ephemeral public key in message 1 - obfuscatedMsg1, err := ObfuscateEphemeralKey(msg1, aesKey) + obfuscatedMsg1, err := ntcp.ObfuscateEphemeralKey(msg1, aesKey) if err != nil { t.Fatalf("Failed to obfuscate message 1: %v", err) } @@ -550,7 +496,7 @@ func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) { // ------------------------------- // Deobfuscate Alice's ephemeral public key in message 1 - deobfuscatedMsg1, err := DeobfuscateEphemeralKey(obfuscatedMsg1, aesKey) + deobfuscatedMsg1, err := ntcp.DeobfuscateEphemeralKey(obfuscatedMsg1, aesKey) if err != nil { t.Fatalf("Failed to deobfuscate message 1: %v", err) } @@ -578,7 +524,7 @@ func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) { } // Obfuscate Bob's ephemeral public key in message 2 - obfuscatedMsg2, err := ObfuscateEphemeralKey(msg2, aesKey) + obfuscatedMsg2, err := ntcp.ObfuscateEphemeralKey(msg2, aesKey) if err != nil { t.Fatalf("Failed to obfuscate message 2: %v", err) } @@ -588,7 +534,7 @@ func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) { // ------------------------------- // Deobfuscate Bob's ephemeral public key in message 2 - deobfuscatedMsg2, err := DeobfuscateEphemeralKey(obfuscatedMsg2, aesKey) + deobfuscatedMsg2, err := ntcp.DeobfuscateEphemeralKey(obfuscatedMsg2, aesKey) if err != nil { t.Fatalf("Failed to deobfuscate message 2: %v", err) } diff --git a/lib/transport/ntcp/obfs.go b/lib/transport/ntcp/obfs.go new file mode 100644 index 0000000..6690b36 --- /dev/null +++ b/lib/transport/ntcp/obfs.go @@ -0,0 +1,60 @@ +package ntcp + +import ( + "fmt" + "github.com/go-i2p/go-i2p/lib/crypto" +) + +// ObfuscateEphemeralKey encrypts the ephemeral public key in the message using AES-256-CBC without padding +func ObfuscateEphemeralKey(message []byte, aesKey *crypto.AESSymmetricKey) ([]byte, error) { + if len(message) < 32 { + return nil, fmt.Errorf("message is too short to contain ephemeral public key") + } + + // Extract the ephemeral public key (first 32 bytes) + ephemeralPubKey := message[:32] + + // Create AES encrypter + encrypter := &crypto.AESSymmetricEncrypter{ + Key: aesKey.Key, + IV: aesKey.IV, + } + + // Encrypt the ephemeral public key without padding + encryptedKey, err := encrypter.EncryptNoPadding(ephemeralPubKey) + if err != nil { + return nil, err + } + + // Replace the ephemeral public key in the message with the encrypted key + obfuscatedMessage := append(encryptedKey, message[32:]...) + + return obfuscatedMessage, nil +} + +// DeobfuscateEphemeralKey decrypts the ephemeral public key in the message using AES-256-CBC without padding +func DeobfuscateEphemeralKey(message []byte, aesKey *crypto.AESSymmetricKey) ([]byte, error) { + if len(message) < 32 { + return nil, fmt.Errorf("message is too short to contain ephemeral public key") + } + + // Extract the encrypted ephemeral public key (first 32 bytes) + encryptedKey := message[:32] + + // Create AES decrypter + decrypter := &crypto.AESSymmetricDecrypter{ + Key: aesKey.Key, + IV: aesKey.IV, + } + + // Decrypt the ephemeral public key without padding + decryptedKey, err := decrypter.DecryptNoPadding(encryptedKey) + if err != nil { + return nil, err + } + + // Replace the encrypted ephemeral key in the message with the decrypted key + deobfuscatedMessage := append(decryptedKey, message[32:]...) + + return deobfuscatedMessage, nil +} From 80e539930edcbf7f76df40d5edd812b96e58c81c Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Mon, 28 Oct 2024 18:11:54 -0400 Subject: [PATCH 85/94] Mapping: fix off-by-one. Format: gofumpt --- lib/common/data/mapping_values.go | 2 +- lib/transport/noise/encrdecr_packet_test.go | 4 +++- lib/transport/noise/read_session.go | 1 + lib/transport/noise/transport.go | 4 ++-- lib/transport/noise/write_session.go | 2 ++ lib/transport/ntcp/obfs.go | 1 + 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/common/data/mapping_values.go b/lib/common/data/mapping_values.go index 739164e..6f2426b 100644 --- a/lib/common/data/mapping_values.go +++ b/lib/common/data/mapping_values.go @@ -22,7 +22,7 @@ func (m MappingValues) Get(key I2PString) I2PString { "key": string(keyBytes), "value": string(pair[1][1:]), }).Debug("Found matching key in MappingValues") - return pair[1][1:] + return pair[1] } } log.WithFields(logrus.Fields{ diff --git a/lib/transport/noise/encrdecr_packet_test.go b/lib/transport/noise/encrdecr_packet_test.go index b95b210..dad90c2 100644 --- a/lib/transport/noise/encrdecr_packet_test.go +++ b/lib/transport/noise/encrdecr_packet_test.go @@ -5,9 +5,10 @@ import ( "crypto/cipher" "crypto/rand" "encoding/binary" + "testing" + "github.com/go-i2p/go-i2p/lib/crypto" "github.com/go-i2p/go-i2p/lib/transport/ntcp" - "testing" "github.com/flynn/noise" "github.com/stretchr/testify/assert" @@ -168,6 +169,7 @@ func TestEncryptDecryptPacketOffline(t *testing.T) { assert.Equal(t, responseData, decryptedResponse, "Decrypted response does not match original data") } + func TestEncryptDecryptPacketObfsOffline(t *testing.T) { // Simulate Bob's Router Hash (RH_B) bobRouterHash := make([]byte, 32) diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go index af5e63f..1eb1804 100644 --- a/lib/transport/noise/read_session.go +++ b/lib/transport/noise/read_session.go @@ -85,6 +85,7 @@ func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { b := c.encryptIfNeeded(packet)*/ //c.freeBlock(packet) } + func (ns *NoiseSession) decryptPacketDeux(packet []byte) (int, []byte, error) { if ns.CipherState == nil { return 0, nil, fmt.Errorf("CipherState is nil") diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index 7c72403..0431a58 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -29,8 +29,8 @@ type NoiseTransport struct { } func (noopt *NoiseTransport) Compatible(routerInfo router_info.RouterInfo) bool { - //TODO implement - //panic("implement me") + // TODO implement + // panic("implement me") log.Warn("func (noopt *NoiseTransport) Compatible(routerInfo router_info.RouterInfo) is not implemented!") return true } diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index adc346c..8525e0f 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -97,6 +97,7 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { b := c.encryptIfNeeded(packet)*/ //c.freeBlock(packet) } + func (ns *NoiseSession) encryptPacketDeux(plaintext []byte) (int, []byte, error) { if ns.CipherState == nil { return 0, nil, fmt.Errorf("CipherState is nil") @@ -116,6 +117,7 @@ func (ns *NoiseSession) encryptPacketDeux(plaintext []byte) (int, []byte, error) return len(packet), packet, nil } + func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { log.WithField("data_length", len(data)).Debug("NoiseSession: Starting writePacketLocked") diff --git a/lib/transport/ntcp/obfs.go b/lib/transport/ntcp/obfs.go index 6690b36..39e1dac 100644 --- a/lib/transport/ntcp/obfs.go +++ b/lib/transport/ntcp/obfs.go @@ -2,6 +2,7 @@ package ntcp import ( "fmt" + "github.com/go-i2p/go-i2p/lib/crypto" ) From 12a3fd4623cd13bd6b581f92a4ea5dcda811782e Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Wed, 30 Oct 2024 09:16:22 -0400 Subject: [PATCH 86/94] Added config files + args -added routerInstance -added initConfig() -added updateRouterConfig() -yaml format --- go.mod | 24 ++++- go.sum | 53 ++++++++++ lib/config/config.go | 1 + main.go | 228 ++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 291 insertions(+), 15 deletions(-) create mode 100644 lib/config/config.go diff --git a/go.mod b/go.mod index 633b162..320ce00 100644 --- a/go.mod +++ b/go.mod @@ -14,8 +14,28 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/spf13/cobra v1.8.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.19.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 6c67222..abdf2c7 100644 --- a/go.sum +++ b/go.sum @@ -1,32 +1,81 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e h1:NMjWYVkgcQHGOy0/VxU0TU6smrcoxzj9hwDesx2sB0w= github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e/go.mod h1:fKfFM3BsOOyjtZmEty7FsGzGabXo8Eb/dHjyIhTtxsE= github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= go.step.sm/crypto v0.53.0 h1:+1as1ogzuCzx15/468M4mEC5juogI5a0Fzbsyh1CuYY= go.step.sm/crypto v0.53.0/go.mod h1:AqLU78RqNUHepLzyOWZuNN/2++Lu7dZENdO9UzWOGSk= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -34,10 +83,14 @@ golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lib/config/config.go b/lib/config/config.go new file mode 100644 index 0000000..d912156 --- /dev/null +++ b/lib/config/config.go @@ -0,0 +1 @@ +package config diff --git a/main.go b/main.go index 9c3847e..6de0034 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,12 @@ package main import ( - "flag" + "fmt" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v3" + "os" + "path/filepath" "github.com/go-i2p/go-i2p/lib/config" "github.com/go-i2p/go-i2p/lib/router" @@ -9,29 +14,226 @@ import ( "github.com/go-i2p/go-i2p/lib/util/signals" ) -var log = logger.GetGoI2PLogger() +var ( + cfgFile string + routerInstance *router.Router + log = logger.GetGoI2PLogger() +) -func main() { - netDbPath := flag.String("netDb", config.DefaultNetDbConfig.Path, "Path to the netDb") - flag.Parse() - config.RouterConfigProperties.NetDb.Path = *netDbPath +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "go-i2p", + Short: "I2P Router implementation in Go", + Run: func(cmd *cobra.Command, args []string) { + runRouter() + }, +} + +func initConfig() { + defaultConfigDir := filepath.Join(os.Getenv("HOME"), ".go-i2p") + defaultConfigFile := filepath.Join(defaultConfigDir, "config.yaml") + + if cfgFile != "" { + // Use config file from the flag + viper.SetConfigFile(cfgFile) + } else { + // Create default config if it doesn't exist + if _, err := os.Stat(defaultConfigFile); os.IsNotExist(err) { + // Ensure directory exists + if err := os.MkdirAll(defaultConfigDir, 0755); err != nil { + log.Fatalf("Could not create config directory: %s", err) + } + + // Create default configuration + defaultConfig := struct { + BaseDir string `yaml:"base_dir"` + WorkingDir string `yaml:"working_dir"` + NetDB config.NetDbConfig `yaml:"netdb"` + Bootstrap config.BootstrapConfig `yaml:"bootstrap"` + }{ + BaseDir: config.DefaultRouterConfig().BaseDir, + WorkingDir: config.DefaultRouterConfig().WorkingDir, + NetDB: *config.DefaultRouterConfig().NetDb, + Bootstrap: *config.DefaultRouterConfig().Bootstrap, + } + + // Marshal config to YAML + yamlData, err := yaml.Marshal(defaultConfig) + if err != nil { + log.Fatalf("Could not marshal default config: %s", err) + } + + // Write default config file + if err := os.WriteFile(defaultConfigFile, yamlData, 0644); err != nil { + log.Fatalf("Could not write default config file: %s", err) + } + + log.Infof("Created default configuration at: %s", defaultConfigFile) + } + + // Set up viper to use the config file + viper.AddConfigPath(defaultConfigDir) + viper.SetConfigName("config") + viper.SetConfigType("yaml") + } + + // Load defaults + setDefaults() + + // Read config file + if err := viper.ReadInConfig(); err != nil { + log.Warnf("Error reading config file: %s", err) + } else { + log.Debugf("Using config file: %s", viper.ConfigFileUsed()) + } + + // Update RouterConfigProperties + updateRouterConfig() +} + +func init() { + cobra.OnInitialize(initConfig) + + // Global flags + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.go-i2p/config.yaml)") + + // Router configuration flags + rootCmd.PersistentFlags().String("base-dir", config.DefaultRouterConfig().BaseDir, "Base directory for I2P router") + rootCmd.PersistentFlags().String("working-dir", config.DefaultRouterConfig().WorkingDir, "Working directory for I2P router") + + // NetDb flags + rootCmd.PersistentFlags().String("netdb.path", config.DefaultNetDbConfig.Path, "Path to the netDb") + + // Bootstrap flags + rootCmd.PersistentFlags().Int("bootstrap.low-peer-threshold", config.DefaultBootstrapConfig.LowPeerThreshold, + "Minimum number of peers before reseeding") + + // Bind flags to viper + viper.BindPFlag("base_dir", rootCmd.PersistentFlags().Lookup("base-dir")) + viper.BindPFlag("working_dir", rootCmd.PersistentFlags().Lookup("working-dir")) + viper.BindPFlag("netdb.path", rootCmd.PersistentFlags().Lookup("netdb.path")) + viper.BindPFlag("bootstrap.low_peer_threshold", rootCmd.PersistentFlags().Lookup("bootstrap.low-peer-threshold")) +} + +func setDefaults() { + // Router defaults + viper.SetDefault("base_dir", config.DefaultRouterConfig().BaseDir) + viper.SetDefault("working_dir", config.DefaultRouterConfig().WorkingDir) + + // NetDb defaults + viper.SetDefault("netdb.path", config.DefaultNetDbConfig.Path) + + // Bootstrap defaults + viper.SetDefault("bootstrap.low_peer_threshold", config.DefaultBootstrapConfig.LowPeerThreshold) + viper.SetDefault("bootstrap.reseed_servers", []config.ReseedConfig{}) +} + +func updateRouterConfig() { + // Update Router configuration + config.RouterConfigProperties.BaseDir = viper.GetString("base_dir") + config.RouterConfigProperties.WorkingDir = viper.GetString("working_dir") + + // Update NetDb configuration + config.RouterConfigProperties.NetDb = &config.NetDbConfig{ + Path: viper.GetString("netdb.path"), + } + + // Update Bootstrap configuration + var reseedServers []*config.ReseedConfig + if err := viper.UnmarshalKey("bootstrap.reseed_servers", &reseedServers); err != nil { + log.Warnf("Error parsing reseed servers: %s", err) + reseedServers = []*config.ReseedConfig{} + } + + config.RouterConfigProperties.Bootstrap = &config.BootstrapConfig{ + LowPeerThreshold: viper.GetInt("bootstrap.low_peer_threshold"), + ReseedServers: reseedServers, + } +} +func runRouter() { go signals.Handle() + log.Debug("parsing i2p router configuration") log.Debug("using netDb in:", config.RouterConfigProperties.NetDb.Path) log.Debug("starting up i2p router") - r, err := router.CreateRouter() + + var err error + routerInstance, err = router.CreateRouter() if err == nil { signals.RegisterReloadHandler(func() { - // TODO: reload config + if err := viper.ReadInConfig(); err != nil { + log.Errorf("failed to reload config: %s", err) + return + } + updateRouterConfig() }) + signals.RegisterInterruptHandler(func() { - // TODO: graceful shutdown - r.Stop() + if routerInstance != nil { + routerInstance.Stop() + } }) - r.Start() - r.Wait() - r.Close() + + routerInstance.Start() + routerInstance.Wait() + routerInstance.Close() } else { log.Errorf("failed to create i2p router: %s", err) } } + +// configCmd shows current configuration +var configCmd = &cobra.Command{ + Use: "config", + Short: "Show current configuration", + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("Configuration file: %s\n", viper.ConfigFileUsed()) + fmt.Printf("\nRouter Configuration:") + fmt.Printf(" Base Directory: %s", config.RouterConfigProperties.BaseDir) + fmt.Printf(" Working Directory: %s", config.RouterConfigProperties.WorkingDir) + + fmt.Printf("\nNetDb Configuration:") + fmt.Printf(" Path: %s", config.RouterConfigProperties.NetDb.Path) + + fmt.Printf("\nBootstrap Configuration:") + fmt.Printf(" Low Peer Threshold: %d", config.RouterConfigProperties.Bootstrap.LowPeerThreshold) + fmt.Printf(" Reseed Servers:") + for _, server := range config.RouterConfigProperties.Bootstrap.ReseedServers { + fmt.Printf(" - URL: %s", server.Url) + fmt.Printf(" SU3 Fingerprint: %s", server.SU3Fingerprint) + } + }, +} + +func main() { + rootCmd.AddCommand(configCmd) + if err := rootCmd.Execute(); err != nil { + log.Error(err) + os.Exit(1) + } + /* + netDbPath := flag.String("netDb", config.DefaultNetDbConfig.Path, "Path to the netDb") + flag.Parse() + config.RouterConfigProperties.NetDb.Path = *netDbPath + go signals.Handle() + log.Debug("parsing i2p router configuration") + log.Debug("using netDb in:", config.RouterConfigProperties.NetDb.Path) + log.Debug("starting up i2p router") + r, err := router.CreateRouter() + if err == nil { + signals.RegisterReloadHandler(func() { + // TODO: reload config + }) + signals.RegisterInterruptHandler(func() { + // TODO: graceful shutdown + r.Stop() + }) + r.Start() + r.Wait() + r.Close() + } else { + log.Errorf("failed to create i2p router: %s", err) + } + + */ +} From 4be55062fcc59c807b54a7d4ec49d9e84b4054de Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Wed, 30 Oct 2024 09:22:32 -0400 Subject: [PATCH 87/94] Moved config funcs to config.go --- lib/config/config.go | 156 ++++++++++++++++++++++++++++++++++++++ main.go | 177 ++++--------------------------------------- 2 files changed, 171 insertions(+), 162 deletions(-) diff --git a/lib/config/config.go b/lib/config/config.go index d912156..81bc5eb 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -1 +1,157 @@ package config + +import ( + "github.com/go-i2p/go-i2p/lib/router" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/go-i2p/go-i2p/lib/util/signals" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v3" + "os" + "path/filepath" +) + +var ( + CfgFile string + routerInstance *router.Router + log = logger.GetGoI2PLogger() +) + +// RootCmd represents the base command when called without any subcommands +var RootCmd = &cobra.Command{ + Use: "go-i2p", + Short: "I2P Router implementation in Go", + Run: func(cmd *cobra.Command, args []string) { + runRouter() + }, +} + +func InitConfig() { + defaultConfigDir := filepath.Join(os.Getenv("HOME"), ".go-i2p") + defaultConfigFile := filepath.Join(defaultConfigDir, "config.yaml") + + if CfgFile != "" { + // Use config file from the flag + viper.SetConfigFile(CfgFile) + } else { + // Create default config if it doesn't exist + if _, err := os.Stat(defaultConfigFile); os.IsNotExist(err) { + // Ensure directory exists + if err := os.MkdirAll(defaultConfigDir, 0755); err != nil { + log.Fatalf("Could not create config directory: %s", err) + } + + // Create default configuration + defaultConfig := struct { + BaseDir string `yaml:"base_dir"` + WorkingDir string `yaml:"working_dir"` + NetDB NetDbConfig `yaml:"netdb"` + Bootstrap BootstrapConfig `yaml:"bootstrap"` + }{ + BaseDir: DefaultRouterConfig().BaseDir, + WorkingDir: DefaultRouterConfig().WorkingDir, + NetDB: *DefaultRouterConfig().NetDb, + Bootstrap: *DefaultRouterConfig().Bootstrap, + } + + // Marshal config to YAML + yamlData, err := yaml.Marshal(defaultConfig) + if err != nil { + log.Fatalf("Could not marshal default config: %s", err) + } + + // Write default config file + if err := os.WriteFile(defaultConfigFile, yamlData, 0644); err != nil { + log.Fatalf("Could not write default config file: %s", err) + } + + log.Infof("Created default configuration at: %s", defaultConfigFile) + } + + // Set up viper to use the config file + viper.AddConfigPath(defaultConfigDir) + viper.SetConfigName("config") + viper.SetConfigType("yaml") + } + + // Load defaults + setDefaults() + + // Read config file + if err := viper.ReadInConfig(); err != nil { + log.Warnf("Error reading config file: %s", err) + } else { + log.Debugf("Using config file: %s", viper.ConfigFileUsed()) + } + + // Update RouterConfigProperties + updateRouterConfig() +} + +func setDefaults() { + // Router defaults + viper.SetDefault("base_dir", DefaultRouterConfig().BaseDir) + viper.SetDefault("working_dir", DefaultRouterConfig().WorkingDir) + + // NetDb defaults + viper.SetDefault("netdb.path", DefaultNetDbConfig.Path) + + // Bootstrap defaults + viper.SetDefault("bootstrap.low_peer_threshold", DefaultBootstrapConfig.LowPeerThreshold) + viper.SetDefault("bootstrap.reseed_servers", []ReseedConfig{}) +} + +func updateRouterConfig() { + // Update Router configuration + RouterConfigProperties.BaseDir = viper.GetString("base_dir") + RouterConfigProperties.WorkingDir = viper.GetString("working_dir") + + // Update NetDb configuration + RouterConfigProperties.NetDb = &NetDbConfig{ + Path: viper.GetString("netdb.path"), + } + + // Update Bootstrap configuration + var reseedServers []*ReseedConfig + if err := viper.UnmarshalKey("bootstrap.reseed_servers", &reseedServers); err != nil { + log.Warnf("Error parsing reseed servers: %s", err) + reseedServers = []*ReseedConfig{} + } + + RouterConfigProperties.Bootstrap = &BootstrapConfig{ + LowPeerThreshold: viper.GetInt("bootstrap.low_peer_threshold"), + ReseedServers: reseedServers, + } +} + +func runRouter() { + go signals.Handle() + + log.Debug("parsing i2p router configuration") + log.Debug("using netDb in:", RouterConfigProperties.NetDb.Path) + log.Debug("starting up i2p router") + + var err error + routerInstance, err = router.CreateRouter() + if err == nil { + signals.RegisterReloadHandler(func() { + if err := viper.ReadInConfig(); err != nil { + log.Errorf("failed to reload config: %s", err) + return + } + updateRouterConfig() + }) + + signals.RegisterInterruptHandler(func() { + if routerInstance != nil { + routerInstance.Stop() + } + }) + + routerInstance.Start() + routerInstance.Wait() + routerInstance.Close() + } else { + log.Errorf("failed to create i2p router: %s", err) + } +} diff --git a/main.go b/main.go index 6de0034..2fd2206 100644 --- a/main.go +++ b/main.go @@ -2,184 +2,37 @@ package main import ( "fmt" + "github.com/go-i2p/go-i2p/lib/config" + "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/spf13/cobra" "github.com/spf13/viper" - "gopkg.in/yaml.v3" "os" - "path/filepath" - - "github.com/go-i2p/go-i2p/lib/config" - "github.com/go-i2p/go-i2p/lib/router" - "github.com/go-i2p/go-i2p/lib/util/logger" - "github.com/go-i2p/go-i2p/lib/util/signals" ) -var ( - cfgFile string - routerInstance *router.Router - log = logger.GetGoI2PLogger() -) - -// rootCmd represents the base command when called without any subcommands -var rootCmd = &cobra.Command{ - Use: "go-i2p", - Short: "I2P Router implementation in Go", - Run: func(cmd *cobra.Command, args []string) { - runRouter() - }, -} - -func initConfig() { - defaultConfigDir := filepath.Join(os.Getenv("HOME"), ".go-i2p") - defaultConfigFile := filepath.Join(defaultConfigDir, "config.yaml") - - if cfgFile != "" { - // Use config file from the flag - viper.SetConfigFile(cfgFile) - } else { - // Create default config if it doesn't exist - if _, err := os.Stat(defaultConfigFile); os.IsNotExist(err) { - // Ensure directory exists - if err := os.MkdirAll(defaultConfigDir, 0755); err != nil { - log.Fatalf("Could not create config directory: %s", err) - } - - // Create default configuration - defaultConfig := struct { - BaseDir string `yaml:"base_dir"` - WorkingDir string `yaml:"working_dir"` - NetDB config.NetDbConfig `yaml:"netdb"` - Bootstrap config.BootstrapConfig `yaml:"bootstrap"` - }{ - BaseDir: config.DefaultRouterConfig().BaseDir, - WorkingDir: config.DefaultRouterConfig().WorkingDir, - NetDB: *config.DefaultRouterConfig().NetDb, - Bootstrap: *config.DefaultRouterConfig().Bootstrap, - } - - // Marshal config to YAML - yamlData, err := yaml.Marshal(defaultConfig) - if err != nil { - log.Fatalf("Could not marshal default config: %s", err) - } - - // Write default config file - if err := os.WriteFile(defaultConfigFile, yamlData, 0644); err != nil { - log.Fatalf("Could not write default config file: %s", err) - } - - log.Infof("Created default configuration at: %s", defaultConfigFile) - } - - // Set up viper to use the config file - viper.AddConfigPath(defaultConfigDir) - viper.SetConfigName("config") - viper.SetConfigType("yaml") - } - - // Load defaults - setDefaults() - - // Read config file - if err := viper.ReadInConfig(); err != nil { - log.Warnf("Error reading config file: %s", err) - } else { - log.Debugf("Using config file: %s", viper.ConfigFileUsed()) - } - - // Update RouterConfigProperties - updateRouterConfig() -} +var log = logger.GetGoI2PLogger() func init() { - cobra.OnInitialize(initConfig) + cobra.OnInitialize(config.InitConfig) // Global flags - rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.go-i2p/config.yaml)") + config.RootCmd.PersistentFlags().StringVar(&config.CfgFile, "config", "", "config file (default is $HOME/.go-i2p/config.yaml)") // Router configuration flags - rootCmd.PersistentFlags().String("base-dir", config.DefaultRouterConfig().BaseDir, "Base directory for I2P router") - rootCmd.PersistentFlags().String("working-dir", config.DefaultRouterConfig().WorkingDir, "Working directory for I2P router") + config.RootCmd.PersistentFlags().String("base-dir", config.DefaultRouterConfig().BaseDir, "Base directory for I2P router") + config.RootCmd.PersistentFlags().String("working-dir", config.DefaultRouterConfig().WorkingDir, "Working directory for I2P router") // NetDb flags - rootCmd.PersistentFlags().String("netdb.path", config.DefaultNetDbConfig.Path, "Path to the netDb") + config.RootCmd.PersistentFlags().String("netdb.path", config.DefaultNetDbConfig.Path, "Path to the netDb") // Bootstrap flags - rootCmd.PersistentFlags().Int("bootstrap.low-peer-threshold", config.DefaultBootstrapConfig.LowPeerThreshold, + config.RootCmd.PersistentFlags().Int("bootstrap.low-peer-threshold", config.DefaultBootstrapConfig.LowPeerThreshold, "Minimum number of peers before reseeding") // Bind flags to viper - viper.BindPFlag("base_dir", rootCmd.PersistentFlags().Lookup("base-dir")) - viper.BindPFlag("working_dir", rootCmd.PersistentFlags().Lookup("working-dir")) - viper.BindPFlag("netdb.path", rootCmd.PersistentFlags().Lookup("netdb.path")) - viper.BindPFlag("bootstrap.low_peer_threshold", rootCmd.PersistentFlags().Lookup("bootstrap.low-peer-threshold")) -} - -func setDefaults() { - // Router defaults - viper.SetDefault("base_dir", config.DefaultRouterConfig().BaseDir) - viper.SetDefault("working_dir", config.DefaultRouterConfig().WorkingDir) - - // NetDb defaults - viper.SetDefault("netdb.path", config.DefaultNetDbConfig.Path) - - // Bootstrap defaults - viper.SetDefault("bootstrap.low_peer_threshold", config.DefaultBootstrapConfig.LowPeerThreshold) - viper.SetDefault("bootstrap.reseed_servers", []config.ReseedConfig{}) -} - -func updateRouterConfig() { - // Update Router configuration - config.RouterConfigProperties.BaseDir = viper.GetString("base_dir") - config.RouterConfigProperties.WorkingDir = viper.GetString("working_dir") - - // Update NetDb configuration - config.RouterConfigProperties.NetDb = &config.NetDbConfig{ - Path: viper.GetString("netdb.path"), - } - - // Update Bootstrap configuration - var reseedServers []*config.ReseedConfig - if err := viper.UnmarshalKey("bootstrap.reseed_servers", &reseedServers); err != nil { - log.Warnf("Error parsing reseed servers: %s", err) - reseedServers = []*config.ReseedConfig{} - } - - config.RouterConfigProperties.Bootstrap = &config.BootstrapConfig{ - LowPeerThreshold: viper.GetInt("bootstrap.low_peer_threshold"), - ReseedServers: reseedServers, - } -} -func runRouter() { - go signals.Handle() - - log.Debug("parsing i2p router configuration") - log.Debug("using netDb in:", config.RouterConfigProperties.NetDb.Path) - log.Debug("starting up i2p router") - - var err error - routerInstance, err = router.CreateRouter() - if err == nil { - signals.RegisterReloadHandler(func() { - if err := viper.ReadInConfig(); err != nil { - log.Errorf("failed to reload config: %s", err) - return - } - updateRouterConfig() - }) - - signals.RegisterInterruptHandler(func() { - if routerInstance != nil { - routerInstance.Stop() - } - }) - - routerInstance.Start() - routerInstance.Wait() - routerInstance.Close() - } else { - log.Errorf("failed to create i2p router: %s", err) - } + viper.BindPFlag("base_dir", config.RootCmd.PersistentFlags().Lookup("base-dir")) + viper.BindPFlag("working_dir", config.RootCmd.PersistentFlags().Lookup("working-dir")) + viper.BindPFlag("netdb.path", config.RootCmd.PersistentFlags().Lookup("netdb.path")) + viper.BindPFlag("bootstrap.low_peer_threshold", config.RootCmd.PersistentFlags().Lookup("bootstrap.low-peer-threshold")) } // configCmd shows current configuration @@ -206,8 +59,8 @@ var configCmd = &cobra.Command{ } func main() { - rootCmd.AddCommand(configCmd) - if err := rootCmd.Execute(); err != nil { + config.RootCmd.AddCommand(configCmd) + if err := config.RootCmd.Execute(); err != nil { log.Error(err) os.Exit(1) } From 46883f6457c13dd8145e28636db64ded650f4a3f Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Wed, 30 Oct 2024 09:31:01 -0400 Subject: [PATCH 88/94] build fails -> import cycle --- lib/config/config.go | 3 --- main.go | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/config/config.go b/lib/config/config.go index 81bc5eb..43d0bd5 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -17,7 +17,6 @@ var ( log = logger.GetGoI2PLogger() ) -// RootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ Use: "go-i2p", Short: "I2P Router implementation in Go", @@ -54,7 +53,6 @@ func InitConfig() { Bootstrap: *DefaultRouterConfig().Bootstrap, } - // Marshal config to YAML yamlData, err := yaml.Marshal(defaultConfig) if err != nil { log.Fatalf("Could not marshal default config: %s", err) @@ -77,7 +75,6 @@ func InitConfig() { // Load defaults setDefaults() - // Read config file if err := viper.ReadInConfig(); err != nil { log.Warnf("Error reading config file: %s", err) } else { diff --git a/main.go b/main.go index 2fd2206..c53b101 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/spf13/cobra" "github.com/spf13/viper" + "gopkg.in/yaml.v3" "os" ) @@ -58,10 +59,32 @@ var configCmd = &cobra.Command{ }, } +func debugPrintConfig() { + currentConfig := struct { + BaseDir string `yaml:"base_dir"` + WorkingDir string `yaml:"working_dir"` + NetDB config.NetDbConfig `yaml:"netdb"` + Bootstrap config.BootstrapConfig `yaml:"bootstrap"` + }{ + BaseDir: config.RouterConfigProperties.BaseDir, + WorkingDir: config.RouterConfigProperties.WorkingDir, + NetDB: *config.RouterConfigProperties.NetDb, + Bootstrap: *config.RouterConfigProperties.Bootstrap, + } + + yamlData, err := yaml.Marshal(currentConfig) + if err != nil { + log.Errorf("Error marshaling config for debug: %s", err) + return + } + + log.Debugf("Current configuration:\n%s", string(yamlData)) +} func main() { config.RootCmd.AddCommand(configCmd) if err := config.RootCmd.Execute(); err != nil { log.Error(err) + debugPrintConfig() os.Exit(1) } /* From 39b683dac845e1d8ebeb9aef9f491300e42462a8 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Wed, 30 Oct 2024 11:20:15 -0400 Subject: [PATCH 89/94] fixed circular dependency --- lib/config/config.go | 52 +++----------------------------- lib/router/router.go | 15 +++++----- main.go | 70 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 69 insertions(+), 68 deletions(-) diff --git a/lib/config/config.go b/lib/config/config.go index 43d0bd5..ae5944f 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -1,10 +1,7 @@ package config import ( - "github.com/go-i2p/go-i2p/lib/router" "github.com/go-i2p/go-i2p/lib/util/logger" - "github.com/go-i2p/go-i2p/lib/util/signals" - "github.com/spf13/cobra" "github.com/spf13/viper" "gopkg.in/yaml.v3" "os" @@ -12,19 +9,10 @@ import ( ) var ( - CfgFile string - routerInstance *router.Router - log = logger.GetGoI2PLogger() + CfgFile string + log = logger.GetGoI2PLogger() ) -var RootCmd = &cobra.Command{ - Use: "go-i2p", - Short: "I2P Router implementation in Go", - Run: func(cmd *cobra.Command, args []string) { - runRouter() - }, -} - func InitConfig() { defaultConfigDir := filepath.Join(os.Getenv("HOME"), ".go-i2p") defaultConfigFile := filepath.Join(defaultConfigDir, "config.yaml") @@ -82,7 +70,7 @@ func InitConfig() { } // Update RouterConfigProperties - updateRouterConfig() + UpdateRouterConfig() } func setDefaults() { @@ -98,7 +86,7 @@ func setDefaults() { viper.SetDefault("bootstrap.reseed_servers", []ReseedConfig{}) } -func updateRouterConfig() { +func UpdateRouterConfig() { // Update Router configuration RouterConfigProperties.BaseDir = viper.GetString("base_dir") RouterConfigProperties.WorkingDir = viper.GetString("working_dir") @@ -120,35 +108,3 @@ func updateRouterConfig() { ReseedServers: reseedServers, } } - -func runRouter() { - go signals.Handle() - - log.Debug("parsing i2p router configuration") - log.Debug("using netDb in:", RouterConfigProperties.NetDb.Path) - log.Debug("starting up i2p router") - - var err error - routerInstance, err = router.CreateRouter() - if err == nil { - signals.RegisterReloadHandler(func() { - if err := viper.ReadInConfig(); err != nil { - log.Errorf("failed to reload config: %s", err) - return - } - updateRouterConfig() - }) - - signals.RegisterInterruptHandler(func() { - if routerInstance != nil { - routerInstance.Stop() - } - }) - - routerInstance.Start() - routerInstance.Wait() - routerInstance.Close() - } else { - log.Errorf("failed to create i2p router: %s", err) - } -} diff --git a/lib/router/router.go b/lib/router/router.go index 70927ed..c4c0a30 100644 --- a/lib/router/router.go +++ b/lib/router/router.go @@ -20,17 +20,16 @@ type Router struct { running bool } -// create router with default configuration -func CreateRouter() (r *Router, err error) { - log.Debug("Creating router with default configuration") - cfg := config.RouterConfigProperties - r, err = FromConfig(cfg) +// CreateRouter creates a router with the provided configuration +func CreateRouter(cfg *config.RouterConfig) (*Router, error) { + log.Debug("Creating router with provided configuration") + r, err := FromConfig(cfg) if err != nil { - log.WithError(err).Error("Failed to create router from default configuration") + log.WithError(err).Error("Failed to create router from configuration") } else { - log.Debug("Router created successfully with default configuration") + log.Debug("Router created successfully with provided configuration") } - return + return r, err } // create router from configuration diff --git a/main.go b/main.go index c53b101..10f8573 100644 --- a/main.go +++ b/main.go @@ -3,37 +3,50 @@ package main import ( "fmt" "github.com/go-i2p/go-i2p/lib/config" + "github.com/go-i2p/go-i2p/lib/router" "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/go-i2p/go-i2p/lib/util/signals" "github.com/spf13/cobra" "github.com/spf13/viper" "gopkg.in/yaml.v3" "os" ) -var log = logger.GetGoI2PLogger() +var ( + routerInstance *router.Router + log = logger.GetGoI2PLogger() +) + +var RootCmd = &cobra.Command{ + Use: "go-i2p", + Short: "I2P Router implementation in Go", + Run: func(cmd *cobra.Command, args []string) { + runRouter() + }, +} func init() { cobra.OnInitialize(config.InitConfig) // Global flags - config.RootCmd.PersistentFlags().StringVar(&config.CfgFile, "config", "", "config file (default is $HOME/.go-i2p/config.yaml)") + RootCmd.PersistentFlags().StringVar(&config.CfgFile, "config", "", "config file (default is $HOME/.go-i2p/config.yaml)") // Router configuration flags - config.RootCmd.PersistentFlags().String("base-dir", config.DefaultRouterConfig().BaseDir, "Base directory for I2P router") - config.RootCmd.PersistentFlags().String("working-dir", config.DefaultRouterConfig().WorkingDir, "Working directory for I2P router") + RootCmd.PersistentFlags().String("base-dir", config.DefaultRouterConfig().BaseDir, "Base directory for I2P router") + RootCmd.PersistentFlags().String("working-dir", config.DefaultRouterConfig().WorkingDir, "Working directory for I2P router") // NetDb flags - config.RootCmd.PersistentFlags().String("netdb.path", config.DefaultNetDbConfig.Path, "Path to the netDb") + RootCmd.PersistentFlags().String("netdb.path", config.DefaultNetDbConfig.Path, "Path to the netDb") // Bootstrap flags - config.RootCmd.PersistentFlags().Int("bootstrap.low-peer-threshold", config.DefaultBootstrapConfig.LowPeerThreshold, + RootCmd.PersistentFlags().Int("bootstrap.low-peer-threshold", config.DefaultBootstrapConfig.LowPeerThreshold, "Minimum number of peers before reseeding") // Bind flags to viper - viper.BindPFlag("base_dir", config.RootCmd.PersistentFlags().Lookup("base-dir")) - viper.BindPFlag("working_dir", config.RootCmd.PersistentFlags().Lookup("working-dir")) - viper.BindPFlag("netdb.path", config.RootCmd.PersistentFlags().Lookup("netdb.path")) - viper.BindPFlag("bootstrap.low_peer_threshold", config.RootCmd.PersistentFlags().Lookup("bootstrap.low-peer-threshold")) + viper.BindPFlag("base_dir", RootCmd.PersistentFlags().Lookup("base-dir")) + viper.BindPFlag("working_dir", RootCmd.PersistentFlags().Lookup("working-dir")) + viper.BindPFlag("netdb.path", RootCmd.PersistentFlags().Lookup("netdb.path")) + viper.BindPFlag("bootstrap.low_peer_threshold", RootCmd.PersistentFlags().Lookup("bootstrap.low-peer-threshold")) } // configCmd shows current configuration @@ -80,9 +93,42 @@ func debugPrintConfig() { log.Debugf("Current configuration:\n%s", string(yamlData)) } + +func runRouter() { + go signals.Handle() + + log.Debug("parsing i2p router configuration") + log.Debug("using netDb in:", config.RouterConfigProperties.NetDb.Path) + log.Debug("starting up i2p router") + + var err error + routerInstance, err = router.CreateRouter(config.RouterConfigProperties) + if err == nil { + signals.RegisterReloadHandler(func() { + if err := viper.ReadInConfig(); err != nil { + log.Errorf("failed to reload config: %s", err) + return + } + config.UpdateRouterConfig() + }) + + signals.RegisterInterruptHandler(func() { + if routerInstance != nil { + routerInstance.Stop() + } + }) + + routerInstance.Start() + routerInstance.Wait() + routerInstance.Close() + } else { + log.Errorf("failed to create i2p router: %s", err) + } +} + func main() { - config.RootCmd.AddCommand(configCmd) - if err := config.RootCmd.Execute(); err != nil { + RootCmd.AddCommand(configCmd) + if err := RootCmd.Execute(); err != nil { log.Error(err) debugPrintConfig() os.Exit(1) From 423f616d53604f339cf157fdcb40b041af95e0b2 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Wed, 30 Oct 2024 23:29:46 -0400 Subject: [PATCH 90/94] Info -> Debug --- lib/config/config.go | 2 +- lib/crypto/dsa_test.go | 2 +- lib/crypto/elg_test.go | 4 ++-- lib/netdb/std.go | 5 ++--- lib/transport/multi.go | 2 +- lib/transport/noise/session.go | 2 +- lib/transport/noise/transport.go | 6 +++--- 7 files changed, 11 insertions(+), 12 deletions(-) diff --git a/lib/config/config.go b/lib/config/config.go index ae5944f..054ca55 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -51,7 +51,7 @@ func InitConfig() { log.Fatalf("Could not write default config file: %s", err) } - log.Infof("Created default configuration at: %s", defaultConfigFile) + log.Debugf("Created default configuration at: %s", defaultConfigFile) } // Set up viper to use the config file diff --git a/lib/crypto/dsa_test.go b/lib/crypto/dsa_test.go index d1c8f3f..4229053 100644 --- a/lib/crypto/dsa_test.go +++ b/lib/crypto/dsa_test.go @@ -84,5 +84,5 @@ func BenchmarkDSASignVerify(b *testing.B) { fail++ } } - log.Infof("%d fails %d signs", fail, b.N) + log.Debugf("%d fails %d signs", fail, b.N) } diff --git a/lib/crypto/elg_test.go b/lib/crypto/elg_test.go index 8178b71..64d9522 100644 --- a/lib/crypto/elg_test.go +++ b/lib/crypto/elg_test.go @@ -45,7 +45,7 @@ func BenchmarkElgDecrypt(b *testing.B) { fails++ } } - log.Infof("%d fails %d rounds", fails, b.N) + log.Debugf("%d fails %d rounds", fails, b.N) } func BenchmarkElgEncrypt(b *testing.B) { @@ -68,7 +68,7 @@ func BenchmarkElgEncrypt(b *testing.B) { fails++ } } - log.Infof("%d fails %d rounds", fails, b.N) + log.Debugf("%d fails %d rounds", fails, b.N) } func TestElg(t *testing.T) { diff --git a/lib/netdb/std.go b/lib/netdb/std.go index e9df933..ee087db 100644 --- a/lib/netdb/std.go +++ b/lib/netdb/std.go @@ -31,7 +31,7 @@ type StdNetDB struct { } func NewStdNetDB(db string) StdNetDB { - log.WithField("db_path", db).Info("Creating new StdNetDB") + log.WithField("db_path", db).Debug("Creating new StdNetDB") return StdNetDB{ DB: db, RouterInfos: make(map[common.Hash]Entry), @@ -189,7 +189,7 @@ func (db *StdNetDB) RecalculateSize() (err error) { return err }) if err == nil { - log.WithField("count", count).Info("Finished recalculating NetDB size") + log.WithField("count", count).Debug("Finished recalculating NetDB size") str := fmt.Sprintf("%d", count) var f *os.File f, err = os.OpenFile(db.cacheFilePath(), os.O_CREATE|os.O_WRONLY, 0o600) @@ -286,7 +286,6 @@ func (db *StdNetDB) Ensure() (err error) { func (db *StdNetDB) Create() (err error) { mode := os.FileMode(0o700) p := db.Path() - // log.Infof("Create network database in %s", p) log.WithField("path", p).Debug("Creating network database directory") // create root for skiplist err = os.MkdirAll(p, mode) diff --git a/lib/transport/multi.go b/lib/transport/multi.go index 8538839..383a293 100644 --- a/lib/transport/multi.go +++ b/lib/transport/multi.go @@ -87,7 +87,7 @@ func (tmux *TransportMuxer) GetSession(routerInfo router_info.RouterInfo) (s Tra continue } // we got a session - log.WithField("transport_index", i).Info("TransportMuxer: Successfully got session from transport") + log.WithField("transport_index", i).Debug("TransportMuxer: Successfully got session from transport") return } } diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index 24b9d69..6c0e02e 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -131,7 +131,7 @@ func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSes RouterInfo: ri, Conn: socket, } - log.WithField("local_addr", socket.LocalAddr().String()).Info("NoiseTransportSession created successfully") + log.WithField("local_addr", socket.LocalAddr().String()).Debug("NoiseTransportSession created successfully") return session, nil } log.Error("Failed to create NoiseTransportSession, all addresses failed") diff --git a/lib/transport/noise/transport.go b/lib/transport/noise/transport.go index 0431a58..3d11690 100644 --- a/lib/transport/noise/transport.go +++ b/lib/transport/noise/transport.go @@ -50,7 +50,7 @@ func (noopt *NoiseTransport) Accept() (net.Conn, error) { if err != nil { log.WithError(err).Error("NoiseTransport: Failed to accept connection") } else { - log.WithField("remote_addr", conn.RemoteAddr().String()).Info("NoiseTransport: Accepted new connection") + log.WithField("remote_addr", conn.RemoteAddr().String()).Debug("NoiseTransport: Accepted new connection") } return conn, err } @@ -156,7 +156,7 @@ func (noopt *NoiseTransport) Close() error { // NewNoiseTransport create a NoiseTransport using a supplied net.Listener func NewNoiseTransport(netSocket net.Listener) *NoiseTransport { - log.WithField("listener_addr", netSocket.Addr().String()).Info("Creating new NoiseTransport") + log.WithField("listener_addr", netSocket.Addr().String()).Debug("Creating new NoiseTransport") return &NoiseTransport{ peerConnections: make(map[data.Hash]transport.TransportSession), Listener: netSocket, @@ -174,6 +174,6 @@ func NewNoiseTransportSocket() (*NoiseTransport, error) { } // return NewNoiseTransport(netSocket), nil _transport := NewNoiseTransport(netSocket) - log.WithField("addr", netSocket.Addr().String()).Info("Created new NoiseTransportSocket") + log.WithField("addr", netSocket.Addr().String()).Debug("Created new NoiseTransportSocket") return _transport, nil } From a5d2f0de8cfa0bf7715787814de8001b8140a473 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 31 Oct 2024 00:01:22 -0400 Subject: [PATCH 91/94] lib/transport/noise/doc.md --- lib/transport/noise/doc.md | 300 +++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 lib/transport/noise/doc.md diff --git a/lib/transport/noise/doc.md b/lib/transport/noise/doc.md new file mode 100644 index 0000000..348df1a --- /dev/null +++ b/lib/transport/noise/doc.md @@ -0,0 +1,300 @@ + +# noise + +## Overview + +The `noise` package implements the Noise Protocol to establish secure, authenticated sessions over TCP. This package includes functions for session management, handshake initiation, packet encryption, decryption, and transport abstraction. + + +- [handshake.go](#handshakego) +- [i2np.go](#i2npgo) +- [incoming_handshake.go](#incoming_handshakego) +- [outgoing_handshake.go](#outgoing_handshakego) +- [noise_constants.go](#noise_constantsgo) +- [read_session.go](#read_sessiongo) +- [session.go](#sessiongo) +- [transport.go](#transportgo) +- [write_session.go](#write_sessiongo) + +--- + +## handshake.go + +Defines the `Handshake` function, which initiates the Noise handshake process for secure, authenticated sessions. + +### Package + +```go +package noise +``` + +### Imports + +```go +import ( + "sync" + "github.com/go-i2p/go-i2p/lib/util/logger" + "github.com/go-i2p/go-i2p/lib/common/router_info" +) +``` + +### Variables + +- **`log`**: Logger instance for capturing debug and error messages related to the handshake process. + +### Function: `Handshake` + +#### Definition + +```go +func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error +``` + +#### Parameters +- `routerInfo`: Information about the router with which the handshake is established. + +#### Returns +- `error`: Returns `nil` on success, or an error if the handshake fails. + +#### Description +The `Handshake` function initiates an authenticated handshake with a router, establishing a secure session. + +#### Workflow +1. **Logging Start**: Logs initiation of the handshake. +2. **Lock Mutex**: Locks `c.Mutex` to prevent concurrent access. +3. **Session Retrieval**: Calls `c.getSession(routerInfo)`. +4. **Condition Variable Setup**: Sets a `Cond` for the session. +5. **Outgoing Handshake**: Executes `RunOutgoingHandshake`. +6. **Completion Broadcast**: Broadcasts to waiting goroutines. +7. **Finalize and Unlock**: Logs success. + +--- + +## i2np.go + +Provides functions to queue and send I2NP messages using a `NoiseSession`. + +### Package + +```go +package noise +``` + +### Imports + +```go +import "github.com/go-i2p/go-i2p/lib/i2np" +``` + +### Functions + +#### `QueueSendI2NP` + +Queues an I2NP message for sending. + +```go +func (s *NoiseSession) QueueSendI2NP(msg i2np.I2NPMessage) +``` + +#### Parameters +- `msg`: The I2NP message. + +--- + +#### `SendQueueSize` + +Returns the size of the send queue. + +```go +func (s *NoiseSession) SendQueueSize() int +``` + +--- + +#### `ReadNextI2NP` + +Attempts to read the next I2NP message from the queue. + +```go +func (s *NoiseSession) ReadNextI2NP() (i2np.I2NPMessage, error) +``` + +--- + +## incoming_handshake.go + +Defines functions for the incoming (receiver) side of the handshake. + +### Functions + +#### `ComposeReceiverHandshakeMessage` + +Creates a receiver handshake message using Noise patterns. + +```go +func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) +``` + +- **`s`**: Static Diffie-Hellman key. +- **`rs`**: Remote static key. +- **`payload`**: Optional payload data. +- **`ePrivate`**: Private ephemeral key. + +--- + +#### `RunIncomingHandshake` + +Executes an incoming handshake process. + +```go +func (c *NoiseSession) RunIncomingHandshake() error +``` + +- Initializes and sends the negotiation data and handshake message. + +--- + +## outgoing_handshake.go + +Defines functions for the outgoing (initiator) side of the handshake. + +### Functions + +#### `ComposeInitiatorHandshakeMessage` + +Creates an initiator handshake message. + +```go +func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) +``` + +--- + +#### `RunOutgoingHandshake` + +Executes the outgoing handshake process. + +```go +func (c *NoiseSession) RunOutgoingHandshake() error +``` + +- Sends negotiation data and handshake message. + +--- + +## noise_constants.go + +Defines constants and utility functions for configuring Noise protocol parameters. + +### Constants + +```go +const ( + NOISE_DH_CURVE25519 = 1 + NOISE_CIPHER_CHACHAPOLY = 1 + NOISE_HASH_SHA256 = 3 + NOISE_PATTERN_XK = 11 + uint16Size = 2 + MaxPayloadSize = 65537 +) +``` + +### Functions + +#### `initNegotiationData` + +Initializes negotiation data with default values. + +```go +func initNegotiationData(negotiationData []byte) []byte +``` + +--- + +## read_session.go + +Functions related to reading encrypted data in a Noise session. + +### Functions + +#### `Read` + +Reads from the Noise session. + +```go +func (c *NoiseSession) Read(b []byte) (int, error) +``` + +#### `decryptPacket` + +Decrypts a packet. + +```go +func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) +``` + +--- + +## session.go + +Defines the `NoiseSession` struct and associated methods for session management. + +### Struct: `NoiseSession` + +Defines session properties. + +```go +type NoiseSession struct { + // Session properties here +} +``` + +--- + +## transport.go + +Defines the `NoiseTransport` struct and its methods for session compatibility, accepting connections, etc. + +### Struct: `NoiseTransport` + +```go +type NoiseTransport struct { + sync.Mutex + router_identity.RouterIdentity + *noise.CipherState + Listener net.Listener + peerConnections map[data.Hash]transport.TransportSession +} +``` + +#### Methods + +- `Compatible`: Checks compatibility. +- `Accept`: Accepts a connection. +- `Addr`: Returns the address. +- `SetIdentity`: Sets the router identity. +- `GetSession`: Obtains a session. + +--- + +## write_session.go + +Functions for writing encrypted data in a Noise session. + +### Functions + +#### `Write` + +Writes data in a Noise session. + +```go +func (c *NoiseSession) Write(b []byte) (int, error) +``` + +#### `encryptPacket` + +Encrypts a packet. + +```go +func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) +``` \ No newline at end of file From 24e0baa8791c67fa7e81299ff13c8f2e095bce95 Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 31 Oct 2024 10:45:42 -0400 Subject: [PATCH 92/94] Moved functions -encryptPacketDeux -> testEncryptPacket in encrdecr_packet_test.go -decryptPacketDeux -> testDecryptPacket in encrdecr_packet_test.go --- lib/transport/noise/encrdecr_packet_test.go | 54 +++++++++++++++++++-- lib/transport/noise/read_session.go | 29 ----------- lib/transport/noise/write_session.go | 20 -------- 3 files changed, 50 insertions(+), 53 deletions(-) diff --git a/lib/transport/noise/encrdecr_packet_test.go b/lib/transport/noise/encrdecr_packet_test.go index dad90c2..091ca50 100644 --- a/lib/transport/noise/encrdecr_packet_test.go +++ b/lib/transport/noise/encrdecr_packet_test.go @@ -5,6 +5,7 @@ import ( "crypto/cipher" "crypto/rand" "encoding/binary" + "fmt" "testing" "github.com/go-i2p/go-i2p/lib/crypto" @@ -14,6 +15,51 @@ import ( "github.com/stretchr/testify/assert" ) +func (ns *NoiseSession) testEncryptPacket(plaintext []byte) (int, []byte, error) { + if ns.CipherState == nil { + return 0, nil, fmt.Errorf("CipherState is nil") + } + + // Encrypt the data + ciphertext, err := ns.CipherState.Encrypt(nil, nil, plaintext) + if err != nil { + log.Fatalf("unimplemented\nerror:%v\n", err) + } + + // Prepend the length of the ciphertext as a 2-byte big-endian value + packetLength := uint16(len(ciphertext)) + packet := make([]byte, 2+len(ciphertext)) + binary.BigEndian.PutUint16(packet[:2], packetLength) + copy(packet[2:], ciphertext) + + return len(packet), packet, nil +} +func (ns *NoiseSession) testPacketDeux(packet []byte) (int, []byte, error) { + if ns.CipherState == nil { + return 0, nil, fmt.Errorf("CipherState is nil") + } + + if len(packet) < 2 { + return 0, nil, fmt.Errorf("Packet too short to contain length prefix") + } + + // Extract the length prefix + packetLength := binary.BigEndian.Uint16(packet[:2]) + + if len(packet[2:]) < int(packetLength) { + return 0, nil, fmt.Errorf("Packet data is shorter than indicated length") + } + + ciphertext := packet[2 : 2+packetLength] + + // Decrypt the data + plaintext, err := ns.CipherState.Decrypt(nil, nil, ciphertext) + if err != nil { + return 0, nil, err + } + + return len(plaintext), plaintext, nil +} func TestEncryptDecryptPacketOffline(t *testing.T) { // Generate static keypairs initiatorStatic, err := noise.DH25519.GenerateKeypair(rand.Reader) @@ -587,12 +633,12 @@ func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) { } originalData := []byte("This is a test message.") - _, encryptedPacket, err := initiatorSession.encryptPacketDeux(originalData) + _, encryptedPacket, err := initiatorSession.testEncryptPacket(originalData) if err != nil { t.Fatalf("Encryption failed: %v", err) } - _, decryptedData, err := responderSession.decryptPacketDeux(encryptedPacket) + _, decryptedData, err := responderSession.testPacketDeux(encryptedPacket) if err != nil { t.Fatalf("Decryption failed: %v", err) } @@ -608,12 +654,12 @@ func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) { } responseData := []byte("This is a response message.") - _, encryptedResponse, err := responderSession.encryptPacketDeux(responseData) + _, encryptedResponse, err := responderSession.testEncryptPacket(responseData) if err != nil { t.Fatalf("Responder encryption failed: %v", err) } - _, decryptedResponse, err := initiatorSession.decryptPacketDeux(encryptedResponse) + _, decryptedResponse, err := initiatorSession.testPacketDeux(encryptedResponse) if err != nil { t.Fatalf("Initiator decryption failed: %v", err) } diff --git a/lib/transport/noise/read_session.go b/lib/transport/noise/read_session.go index 1eb1804..b8f8833 100644 --- a/lib/transport/noise/read_session.go +++ b/lib/transport/noise/read_session.go @@ -1,9 +1,7 @@ package noise import ( - "encoding/binary" "errors" - "fmt" "sync/atomic" "github.com/sirupsen/logrus" @@ -86,33 +84,6 @@ func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) { //c.freeBlock(packet) } -func (ns *NoiseSession) decryptPacketDeux(packet []byte) (int, []byte, error) { - if ns.CipherState == nil { - return 0, nil, fmt.Errorf("CipherState is nil") - } - - if len(packet) < 2 { - return 0, nil, fmt.Errorf("Packet too short to contain length prefix") - } - - // Extract the length prefix - packetLength := binary.BigEndian.Uint16(packet[:2]) - - if len(packet[2:]) < int(packetLength) { - return 0, nil, fmt.Errorf("Packet data is shorter than indicated length") - } - - ciphertext := packet[2 : 2+packetLength] - - // Decrypt the data - plaintext, err := ns.CipherState.Decrypt(nil, nil, ciphertext) - if err != nil { - return 0, nil, err - } - - return len(plaintext), plaintext, nil -} - func (c *NoiseSession) readPacketLocked(data []byte) (int, error) { log.WithField("data_length", len(data)).Debug("Starting readPacketLocked") diff --git a/lib/transport/noise/write_session.go b/lib/transport/noise/write_session.go index 8525e0f..19c098a 100644 --- a/lib/transport/noise/write_session.go +++ b/lib/transport/noise/write_session.go @@ -98,26 +98,6 @@ func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) { //c.freeBlock(packet) } -func (ns *NoiseSession) encryptPacketDeux(plaintext []byte) (int, []byte, error) { - if ns.CipherState == nil { - return 0, nil, fmt.Errorf("CipherState is nil") - } - - // Encrypt the data - ciphertext, err := ns.CipherState.Encrypt(nil, nil, plaintext) - if err != nil { - log.Fatalf("unimplemented\nerror:%v\n", err) - } - - // Prepend the length of the ciphertext as a 2-byte big-endian value - packetLength := uint16(len(ciphertext)) - packet := make([]byte, 2+len(ciphertext)) - binary.BigEndian.PutUint16(packet[:2], packetLength) - copy(packet[2:], ciphertext) - - return len(packet), packet, nil -} - func (c *NoiseSession) writePacketLocked(data []byte) (int, error) { log.WithField("data_length", len(data)).Debug("NoiseSession: Starting writePacketLocked") From 487815f8f1ac655a1e34be9c9f4c365b068a7aee Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 31 Oct 2024 10:50:21 -0400 Subject: [PATCH 93/94] tests --- doc/tests/noise.mk | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/tests/noise.mk b/doc/tests/noise.mk index 39f3d52..6977b66 100644 --- a/doc/tests/noise.mk +++ b/doc/tests/noise.mk @@ -1,4 +1,4 @@ -test-noise-transport-all: test-noise-packet-encryption test-noise-transport-connection +test-noise-transport-all: test-noise-packet-encryption test-noise-transport-connection test-noise-packet-obfuscation test-noise-packet-obfuscation-func test-noise-packet-encryption: go test -v ./lib/transport/noise -run TestEncryptDecryptPacketOffline @@ -6,6 +6,14 @@ test-noise-packet-encryption: test-noise-transport-connection: go test -v ./lib/transport/noise -run TestTransport +test-noise-packet-obfuscation: + go test -v ./lib/transport/noise -run TestEncryptDecryptPacketObfsOffline + +test-noise-packet-obfuscation-func: + go test -v ./lib/transport/noise -run TestEncryptDecryptPacketObfsOfflineWithFunc + .PHONY: test-noise-transport-all \ test-noise-packet-encryption \ - test-noise-transport-connection + test-noise-transport-connection \ + test-noise-packet-obfuscation \ + test-noise-packet-obfuscation-func \ No newline at end of file From a17f0208ddf592723b5352bf700698eab196dcff Mon Sep 17 00:00:00 2001 From: Haris Khan Date: Thu, 31 Oct 2024 10:53:22 -0400 Subject: [PATCH 94/94] gofumpt adjustment --- lib/config/config.go | 9 +++++---- lib/transport/noise/encrdecr_packet_test.go | 2 ++ main.go | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/config/config.go b/lib/config/config.go index 054ca55..9e1c08e 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -1,11 +1,12 @@ package config import ( + "os" + "path/filepath" + "github.com/go-i2p/go-i2p/lib/util/logger" "github.com/spf13/viper" "gopkg.in/yaml.v3" - "os" - "path/filepath" ) var ( @@ -24,7 +25,7 @@ func InitConfig() { // Create default config if it doesn't exist if _, err := os.Stat(defaultConfigFile); os.IsNotExist(err) { // Ensure directory exists - if err := os.MkdirAll(defaultConfigDir, 0755); err != nil { + if err := os.MkdirAll(defaultConfigDir, 0o755); err != nil { log.Fatalf("Could not create config directory: %s", err) } @@ -47,7 +48,7 @@ func InitConfig() { } // Write default config file - if err := os.WriteFile(defaultConfigFile, yamlData, 0644); err != nil { + if err := os.WriteFile(defaultConfigFile, yamlData, 0o644); err != nil { log.Fatalf("Could not write default config file: %s", err) } diff --git a/lib/transport/noise/encrdecr_packet_test.go b/lib/transport/noise/encrdecr_packet_test.go index 091ca50..4f5d2fc 100644 --- a/lib/transport/noise/encrdecr_packet_test.go +++ b/lib/transport/noise/encrdecr_packet_test.go @@ -34,6 +34,7 @@ func (ns *NoiseSession) testEncryptPacket(plaintext []byte) (int, []byte, error) return len(packet), packet, nil } + func (ns *NoiseSession) testPacketDeux(packet []byte) (int, []byte, error) { if ns.CipherState == nil { return 0, nil, fmt.Errorf("CipherState is nil") @@ -60,6 +61,7 @@ func (ns *NoiseSession) testPacketDeux(packet []byte) (int, []byte, error) { return len(plaintext), plaintext, nil } + func TestEncryptDecryptPacketOffline(t *testing.T) { // Generate static keypairs initiatorStatic, err := noise.DH25519.GenerateKeypair(rand.Reader) diff --git a/main.go b/main.go index 10f8573..7fc5aae 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,8 @@ package main import ( "fmt" + "os" + "github.com/go-i2p/go-i2p/lib/config" "github.com/go-i2p/go-i2p/lib/router" "github.com/go-i2p/go-i2p/lib/util/logger" @@ -9,7 +11,6 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "gopkg.in/yaml.v3" - "os" ) var (