go_i2cp

package module
v0.0.0-...-294b34d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 1, 2025 License: MIT Imports: 26 Imported by: 1

README

go-i2cp

A low-level Go implementation of the I2P Client Protocol (I2CP) focused on developing anonymous services and applications. This library provides cryptographically secure primitives for establishing I2P destinations and managing end-to-end encrypted communication sessions.

Features

  • Pure Go I2CP client implementation with minimal dependencies
  • Complete I2CP client
  • Secure session establishment and management
  • Cryptographic operations (DSA/SHA1/SHA256)
  • Stream-based encrypted messaging
  • Anonymous addressing (Base32/Base64)
  • Comprehensive test coverage
  • TLS support for I2CP connections

Installation

go get github.com/go-i2p/go-i2cp

Basic Usage

// Create I2CP client with default settings
client := go_i2cp.NewClient(nil)

// Connect to local I2P router
if err := client.Connect(); err != nil {
    log.Fatal(err)
}
defer client.Disconnect()

// Create session with callbacks
session := go_i2cp.NewSession(client, go_i2cp.SessionCallbacks{
    onDestination: func(session *go_i2cp.Session, requestId uint32, 
                       address string, dest *go_i2cp.Destination) {
        // Handle destination lookups
    },
    onStatus: func(session *go_i2cp.Session, status go_i2cp.SessionStatus) {
        // Handle session status changes
    },
    onMessage: func(session *go_i2cp.Session, protocol uint8,
                    srcPort, destPort uint16, payload *go_i2cp.Stream) {
        // Handle incoming messages
    },
})

// Configure session
session.config.SetProperty(go_i2cp.SESSION_CONFIG_PROP_OUTBOUND_NICKNAME, "example")
session.config.SetProperty(go_i2cp.SESSION_CONFIG_PROP_OUTBOUND_QUANTITY, "4")

// Generate destination
if session.config.destination, err = go_i2cp.NewDestination(); err != nil {
    log.Fatal(err)
}

// Create session
if err := client.CreateSession(session); err != nil {
    log.Fatal(err) 
}

Security Configuration

The library supports extensive session configuration for privacy tuning:

// Security settings
config.SetProperty(SESSION_CONFIG_PROP_INBOUND_LENGTH, "3")          // Tunnel length
config.SetProperty(SESSION_CONFIG_PROP_OUTBOUND_LENGTH, "3")         
config.SetProperty(SESSION_CONFIG_PROP_INBOUND_QUANTITY, "4")        // Number of tunnels
config.SetProperty(SESSION_CONFIG_PROP_OUTBOUND_QUANTITY, "4")
config.SetProperty(SESSION_CONFIG_PROP_INBOUND_BACKUP_QUANTITY, "2") // Backup tunnels
config.SetProperty(SESSION_CONFIG_PROP_OUTBOUND_BACKUP_QUANTITY, "2")

Privacy Considerations

This library implements core I2P networking primitives. When using it:

  • Never mix I2P and clearnet traffic
  • Use appropriate tunnel lengths for your threat model
  • Handle all errors privately without leaking metadata
  • Implement proper session isolation
  • Consider timing attack mitigations
  • Use TLS for I2CP connections when remote
  • Rotate destinations if necessary
  • Monitor tunnel health

Roadmap

Core I2CP Protocol Features
  • Message Priority Support - Implement priority levels for I2CP messages (SendMessageExpires with priority flags)
  • Bandwidth Limiting - Add support for bandwidth limiting properties (i2cp.inboundBytesPerSecond, i2cp.outboundBytesPerSecond)
  • LS2 Support - Implement LeaseSet2 format for enhanced metadata and multiple signature types
  • ECIES-X25519 Encryption - Add support for modern ECIES encryption alongside existing ElGamal
  • Ed25519 Signatures - Implement Ed25519 signature support for improved performance and security
  • BlindedInfo Support - Add support for blinded destinations and encrypted leaseset publishing
  • Meta LeaseSet Support - Implement support for multi-destination meta leaseset format
Extended I2CP Features
  • Session Persistence - Implement session state saving/loading for graceful restart
  • Advanced Tunnel Configuration - Support for tunnel variance, randomization options
  • Client Authentication - Implement I2CP client authentication mechanisms
  • Streaming Support - Add higher-level streaming protocol implementation over I2CP
  • Datagram Support - Implement repliable datagram messaging
  • Destination Lookup Caching - Add intelligent caching for destination resolution
Modern Crypto & Protocol
  • RedDSA Signatures - Support for RedDSA signature algorithm
  • ChaCha20/Poly1305 - Modern AEAD cipher support for tunnel encryption
  • SipHash - Implement SipHash for improved hash table security
  • Noise Protocol - Add Noise-based handshakes for enhanced forward secrecy
Quality & Performance
  • Connection Pooling - Implement I2CP connection pooling for better resource usage
  • Async Message Handling - Non-blocking message processing with goroutine pools
  • Metrics & Monitoring - Add comprehensive metrics collection and health monitoring
  • Zero-Copy Operations - Optimize buffer management to reduce memory allocations

Testing

go test -v ./...

Requirements

  • Go 1.16+
  • Running I2P router with I2CP enabled (default port 7654)
  • SAM API v3.3 enabled in router

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/enhancement)
  3. Commit changes (git commit -m 'Add enhancement')
  4. Push to branch (git push origin feature/enhancement)
  5. Open a Pull Request

License

MIT License - See LICENSE file

Documentation

Index

Constants

View Source
const (
	CERTIFICATE_NULL     uint8 = iota
	CERTIFICATE_HASHCASH uint8 = iota
	CERTIFICATE_SIGNED   uint8 = iota
	CERTIFICATE_MULTIPLE uint8 = iota
)
View Source
const (
	PROTOCOL_STREAMING    = 6
	PROTOCOL_DATAGRAM     = 17
	PROTOCOL_RAW_DATAGRAM = 18
)
View Source
const (
	HOST_LOOKUP_TYPE_HASH = iota
	HOST_LOOKUP_TYPE_HOST = iota
)
View Source
const (
	HASH_SHA1   uint8 = iota
	HASH_SHA256 uint8 = iota
)

Supported Hash algorithms

View Source
const (
	DSA_SHA1   uint32 = iota
	DSA_SHA256 uint32 = iota
)

Supported signature algorithms

View Source
const (
	CODEC_BASE32 uint8 = iota
	CODEC_BASE64 uint8 = iota
)

Supported codec algorithms

View Source
const (
	PROTOCOL = 1 << 0
	LOGIC    = 1 << 1

	DEBUG   = 1 << 4
	INFO    = 1 << 5
	WARNING = 1 << 6
	ERROR   = 1 << 7
	FATAL   = 1 << 8

	STRINGMAP      = 1 << 9
	INTMAP         = 1 << 10
	QUEUE          = 1 << 11
	STREAM         = 1 << 12
	CRYPTO         = 1 << 13
	TCP            = 1 << 14
	CLIENT         = 1 << 15
	CERTIFICATE    = 1 << 16
	LEASE          = 1 << 17
	DESTINATION    = 1 << 18
	SESSION        = 1 << 19
	SESSION_CONFIG = 1 << 20
	TEST           = 1 << 21
	DATAGRAM       = 1 << 22
	CONFIG_FILE    = 1 << 23
	VERSION        = 1 << 24

	TAG_MASK       = 0x0000000f
	LEVEL_MASK     = 0x000001f0
	COMPONENT_MASK = 0xfffffe00

	ALL = 0xffffffff
)
View Source
const DEST_SIZE = 4096
View Source
const DIGEST_SIZE = 40
View Source
const I2CP_CLIENT_VERSION = "0.9.33"
View Source
const I2CP_MAX_SESSIONS = 0xffff
View Source
const I2CP_MAX_SESSIONS_PER_CLIENT = 32
View Source
const I2CP_MESSAGE_SIZE = 0xffff
View Source
const I2CP_MSG_ANY uint8 = 0
View Source
const I2CP_MSG_BANDWIDTH_LIMITS uint8 = 23
View Source
const I2CP_MSG_CREATE_LEASE_SET uint8 = 4
View Source
const I2CP_MSG_CREATE_SESSION uint8 = 1
View Source
const I2CP_MSG_DESTROY_SESSION uint8 = 3
View Source
const I2CP_MSG_DEST_LOOKUP uint8 = 34
View Source
const I2CP_MSG_DEST_REPLY uint8 = 35
View Source
const I2CP_MSG_DISCONNECT uint8 = 30
View Source
const I2CP_MSG_GET_BANDWIDTH_LIMITS uint8 = 8
View Source
const I2CP_MSG_GET_DATE uint8 = 32
View Source
const I2CP_MSG_HOST_LOOKUP uint8 = 38
View Source
const I2CP_MSG_HOST_REPLY uint8 = 39
View Source
const I2CP_MSG_MESSAGE_STATUS uint8 = 22
View Source
const I2CP_MSG_PAYLOAD_MESSAGE uint8 = 31
View Source
const I2CP_MSG_REQUEST_LEASESET uint8 = 21
View Source
const I2CP_MSG_REQUEST_VARIABLE_LEASESET uint8 = 37
View Source
const I2CP_MSG_SEND_MESSAGE uint8 = 5
View Source
const I2CP_MSG_SESSION_STATUS uint8 = 20
View Source
const I2CP_MSG_SET_DATE uint8 = 33
View Source
const I2CP_PROTOCOL_INIT uint8 = 0x2a
View Source
const PUB_KEY_SIZE = 256
View Source
const ROUTER_CAN_HOST_LOOKUP uint32 = 1

Router capabilities

View Source
const TAG = CLIENT
View Source
const USE_TLS = false

Variables

View Source
var CAFile = "/etc/ssl/certs/ca-certificates.crt"

Functions

func Debug

func Debug(tags LoggerTags, message string, args ...interface{})

func Error

func Error(tags LoggerTags, message string, args ...interface{})

func Fatal

func Fatal(tags LoggerTags, message string, args ...interface{})

func Info

func Info(tags LoggerTags, message string, args ...interface{})

func LogInit

func LogInit(callbacks *LoggerCallbacks, level int)

TODO filter

func ParseConfig

func ParseConfig(s string, cb func(string, string))

func Warning

func Warning(tags LoggerTags, message string, args ...interface{})

Types

type Certificate

type Certificate struct {
	// contains filtered or unexported fields
}

func NewCertificate

func NewCertificate(typ uint8) (cert Certificate)

func NewCertificateFromMessage

func NewCertificateFromMessage(stream *Stream) (cert Certificate, err error)

func NewCertificateFromStream

func NewCertificateFromStream(stream *Stream) (Certificate, error)

func (*Certificate) Copy

func (cert *Certificate) Copy() (newCert Certificate)

func (*Certificate) WriteToMessage

func (cert *Certificate) WriteToMessage(stream *Stream) (err error)

func (*Certificate) WriteToStream

func (cert *Certificate) WriteToStream(stream *Stream) error

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(callbacks *ClientCallBacks) (c *Client)

NewClient creates a new i2p client with the specified callbacks

func (*Client) Connect

func (c *Client) Connect() error

func (*Client) CreateSession

func (c *Client) CreateSession(sess *Session) error

func (*Client) DestinationLookup

func (c *Client) DestinationLookup(session *Session, address string) (requestId uint32)

func (*Client) Disconnect

func (c *Client) Disconnect()

func (*Client) IsConnected

func (c *Client) IsConnected() bool

func (*Client) ProcessIO

func (c *Client) ProcessIO() error

func (*Client) SetProperty

func (c *Client) SetProperty(name, value string)

type ClientCallBacks

type ClientCallBacks struct {
	// contains filtered or unexported fields
}

type ClientProperty

type ClientProperty int
const (
	CLIENT_PROP_ROUTER_ADDRESS ClientProperty = iota
	CLIENT_PROP_ROUTER_PORT
	CLIENT_PROP_ROUTER_USE_TLS
	CLIENT_PROP_USERNAME
	CLIENT_PROP_PASSWORD
	NR_OF_I2CP_CLIENT_PROPERTIES
)

type Crypto

type Crypto struct {
	// contains filtered or unexported fields
}

func GetCryptoInstance

func GetCryptoInstance() *Crypto

func (*Crypto) DecodeStream

func (c *Crypto) DecodeStream(algorithmTyp uint8, src *Stream) (dst *Stream, err error)

func (*Crypto) EncodeStream

func (c *Crypto) EncodeStream(algorithmTyp uint8, src *Stream) (dst *Stream)

func (*Crypto) HashStream

func (c *Crypto) HashStream(algorithmTyp uint8, src *Stream) *Stream

func (*Crypto) PublicKeyFromStream

func (c *Crypto) PublicKeyFromStream(keyType uint32, stream *Stream) (key *big.Int, err error)

func (*Crypto) SignStream

func (c *Crypto) SignStream(sgk *SignatureKeyPair, stream *Stream) (err error)

Sign a stream using the specified algorithm

func (*Crypto) SignatureKeyPairFromStream

func (c *Crypto) SignatureKeyPairFromStream(stream *Stream) (sgk SignatureKeyPair, err error)

Read and initialize signature keypair from stream

func (*Crypto) SignatureKeygen

func (c *Crypto) SignatureKeygen(algorithmTyp uint32) (sgk SignatureKeyPair, err error)

Generate a signature keypair

func (*Crypto) VerifyStream

func (c *Crypto) VerifyStream(sgk *SignatureKeyPair, stream *Stream) (verified bool, err error)

Verify Stream

func (*Crypto) WritePublicSignatureToStream

func (c *Crypto) WritePublicSignatureToStream(sgk *SignatureKeyPair, stream *Stream) (err error)

Write public signature key to stream

func (*Crypto) WriteSignatureToStream

func (c *Crypto) WriteSignatureToStream(sgk *SignatureKeyPair, stream *Stream) (err error)

Write Signature keypair to stream

type Destination

type Destination struct {
	// contains filtered or unexported fields
}

func NewDestination

func NewDestination() (dest *Destination, err error)

func NewDestinationFromBase64

func NewDestinationFromBase64(base64 string) (dest *Destination, err error)

func NewDestinationFromFile

func NewDestinationFromFile(file *os.File) (*Destination, error)

func NewDestinationFromMessage

func NewDestinationFromMessage(stream *Stream) (dest *Destination, err error)

func NewDestinationFromStream

func NewDestinationFromStream(stream *Stream) (dest *Destination, err error)

func (*Destination) Copy

func (dest *Destination) Copy() (newDest Destination)

func (*Destination) Verify

func (dest *Destination) Verify() (verified bool, err error)

Doesn't seem to be used anywhere??

func (*Destination) WriteToFile

func (dest *Destination) WriteToFile(filename string) (err error)

func (*Destination) WriteToMessage

func (dest *Destination) WriteToMessage(stream *Stream) (err error)

func (*Destination) WriteToStream

func (dest *Destination) WriteToStream(stream *Stream) (err error)

type Lease

type Lease struct {
	// contains filtered or unexported fields
}

func NewLeaseFromStream

func NewLeaseFromStream(stream *Stream) (l *Lease, err error)

func (*Lease) WriteToMessage

func (l *Lease) WriteToMessage(stream *Stream) (err error)

type Logger

type Logger struct {
	// contains filtered or unexported fields
}

type LoggerCallbacks

type LoggerCallbacks struct {
	// contains filtered or unexported fields
}

type LoggerTags

type LoggerTags = uint32

type LookupEntry

type LookupEntry struct {
	// contains filtered or unexported fields
}

type RouterInfo

type RouterInfo struct {
	// contains filtered or unexported fields
}

type Session

type Session struct {
	// contains filtered or unexported fields
}

func NewSession

func NewSession(client *Client, callbacks SessionCallbacks) (sess *Session)

func (*Session) Destination

func (session *Session) Destination() *Destination

func (*Session) SendMessage

func (session *Session) SendMessage(destination *Destination, protocol uint8, srcPort, destPort uint16, payload *Stream, nonce uint32)

type SessionCallbacks

type SessionCallbacks struct {
	// contains filtered or unexported fields
}

type SessionConfig

type SessionConfig struct {
	// contains filtered or unexported fields
}

func NewSessionConfigFromDestinationFile

func NewSessionConfigFromDestinationFile(filename string) (config SessionConfig)

func (*SessionConfig) SetProperty

func (config *SessionConfig) SetProperty(prop SessionConfigProperty, value string)

type SessionConfigProperty

type SessionConfigProperty int
const (
	SESSION_CONFIG_PROP_CRYPTO_LOW_TAG_THRESHOLD SessionConfigProperty = iota
	SESSION_CONFIG_PROP_CRYPTO_TAGS_TO_SEND

	SESSION_CONFIG_PROP_I2CP_DONT_PUBLISH_LEASE_SET
	SESSION_CONFIG_PROP_I2CP_FAST_RECEIVE
	SESSION_CONFIG_PROP_I2CP_GZIP
	SESSION_CONFIG_PROP_I2CP_MESSAGE_RELIABILITY
	SESSION_CONFIG_PROP_I2CP_PASSWORD
	SESSION_CONFIG_PROP_I2CP_USERNAME

	SESSION_CONFIG_PROP_INBOUND_ALLOW_ZERO_HOP
	SESSION_CONFIG_PROP_INBOUND_BACKUP_QUANTITY
	SESSION_CONFIG_PROP_INBOUND_IP_RESTRICTION
	SESSION_CONFIG_PROP_INBOUND_LENGTH
	SESSION_CONFIG_PROP_INBOUND_LENGTH_VARIANCE
	SESSION_CONFIG_PROP_INBOUND_NICKNAME
	SESSION_CONFIG_PROP_INBOUND_QUANTITY

	SESSION_CONFIG_PROP_OUTBOUND_ALLOW_ZERO_HOP
	SESSION_CONFIG_PROP_OUTBOUND_BACKUP_QUANTITY
	SESSION_CONFIG_PROP_OUTBOUND_IP_RESTRICTION
	SESSION_CONFIG_PROP_OUTBOUND_LENGTH
	SESSION_CONFIG_PROP_OUTBOUND_LENGTH_VARIANCE
	SESSION_CONFIG_PROP_OUTBOUND_NICKNAME
	SESSION_CONFIG_PROP_OUTBOUND_PRIORITY
	SESSION_CONFIG_PROP_OUTBOUND_QUANTITY

	NR_OF_SESSION_CONFIG_PROPERTIES
)

type SessionMessageStatus

type SessionMessageStatus int
const (
	I2CP_MSG_STATUS_AVAILABLE SessionMessageStatus = iota
	I2CP_MSG_STATUS_ACCEPTED
	I2CP_MSG_STATUS_BEST_EFFORT_SUCCESS
	I2CP_MSG_STATUS_BEST_EFFORT_FAILURE
	I2CP_MSG_STATUS_GUARANTEED_SUCCESS
	I2CP_MSG_STATUS_GUARANTEED_FAILURE
	I2CP_MSG_STATUS_LOCAL_SUCCESS
	I2CP_MSG_STATUS_LOCAL_FAILURE
	I2CP_MSG_STATUS_ROUTER_FAILURE
	I2CP_MSG_STATUS_NETWORK_FAILURE
	I2CP_MSG_STATUS_BAD_SESSION
	I2CP_MSG_STATUS_BAD_MESSAGE
	I2CP_MSG_STATUS_OVERFLOW_FAILURE
	I2CP_MSG_STATUS_MESSAGE_EXPIRED
	I2CP_MSG_STATUS_MESSAGE_BAD_LOCAL_LEASESET
	I2CP_MSG_STATUS_MESSAGE_NO_LOCAL_TUNNELS
	I2CP_MSG_STATUS_MESSAGE_UNSUPPORTED_ENCRYPTION
	I2CP_MSG_STATUS_MESSAGE_BAD_DESTINATION
	I2CP_MSG_STATUS_MESSAGE_BAD_LEASESET
	I2CP_MSG_STATUS_MESSAGE_EXPIRED_LEASESET
	I2CP_MSG_STATUS_MESSAGE_NO_LEASESET
)

type SessionStatus

type SessionStatus int
const (
	I2CP_SESSION_STATUS_DESTROYED SessionStatus = iota
	I2CP_SESSION_STATUS_CREATED
	I2CP_SESSION_STATUS_UPDATED
	I2CP_SESSION_STATUS_INVALID
)

type SignatureKeyPair

type SignatureKeyPair struct {
	// contains filtered or unexported fields
}

type Stream

type Stream struct {
	*bytes.Buffer
}

func NewStream

func NewStream(buf []byte) (s *Stream)

func (*Stream) ChLen

func (s *Stream) ChLen(len int)

func (*Stream) ReadUint16

func (s *Stream) ReadUint16() (r uint16, err error)

func (*Stream) ReadUint32

func (s *Stream) ReadUint32() (r uint32, err error)

func (*Stream) ReadUint64

func (s *Stream) ReadUint64() (r uint64, err error)

func (*Stream) WriteLenPrefixedString

func (stream *Stream) WriteLenPrefixedString(s string) (err error)

func (*Stream) WriteMapping

func (stream *Stream) WriteMapping(m map[string]string) (err error)

func (*Stream) WriteUint16

func (s *Stream) WriteUint16(i uint16) (err error)

func (*Stream) WriteUint32

func (s *Stream) WriteUint32(i uint32) (err error)

func (*Stream) WriteUint64

func (s *Stream) WriteUint64(i uint64) (err error)

type Tcp

type Tcp struct {
	// contains filtered or unexported fields
}

func (*Tcp) CanRead

func (tcp *Tcp) CanRead() bool

func (*Tcp) Connect

func (tcp *Tcp) Connect() (err error)

func (*Tcp) Disconnect

func (tcp *Tcp) Disconnect()

func (*Tcp) GetProperty

func (tcp *Tcp) GetProperty(property TcpProperty) string

func (*Tcp) Init

func (tcp *Tcp) Init() (err error)

func (*Tcp) IsConnected

func (tcp *Tcp) IsConnected() bool

func (*Tcp) Receive

func (tcp *Tcp) Receive(buf *Stream) (i int, err error)

func (*Tcp) Send

func (tcp *Tcp) Send(buf *Stream) (i int, err error)

func (*Tcp) SetProperty

func (tcp *Tcp) SetProperty(property TcpProperty, value string)

type TcpProperty

type TcpProperty int
const (
	TCP_PROP_ADDRESS TcpProperty = iota
	TCP_PROP_PORT
	TCP_PROP_USE_TLS
	TCP_PROP_TLS_CLIENT_CERTIFICATE
	NR_OF_TCP_PROPERTIES
)

type Version

type Version struct {
	// contains filtered or unexported fields
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL