Documentation
¶
Overview ¶
Blinding Crypto Implementation for I2CP
This file implements blinding key derivation and cryptographic operations for accessing encrypted LeaseSets via I2CP BlindingInfoMessage.
The implementation delegates to github.com/go-i2p/crypto/kdf and ed25519 packages which provide I2P-compliant blinding operations per Proposal 123.
Blinding workflow:
- Service publishes encrypted LeaseSet with blinded destination
- Client derives blinding factor from secret + date
- Client blinds destination's public key with the factor
- Router uses blinded key to locate encrypted LeaseSet
- Client decrypts LeaseSet using derived keys
Since: I2CP 0.9.43+ Reference: I2P Proposal 123 - Encrypted LeaseSet
DH/PSK Authentication Implementation for I2CP Encrypted LeaseSets
This file implements Diffie-Hellman and Pre-Shared Key authentication for accessing encrypted LeaseSets via I2CP BlindingInfoMessage.
Per I2P Proposal 123 and 149, encrypted LeaseSets can require client authentication using either:
- DH (BLINDING_AUTH_SCHEME_DH = 0): X25519 Diffie-Hellman key exchange
- PSK (BLINDING_AUTH_SCHEME_PSK = 1): Pre-shared symmetric key
The authentication produces a 32-byte decryption key that is sent in the BlindingInfoMessage to enable the router to decrypt the LeaseSet.
Workflow for DH:
- Client has X25519 private key (client identity)
- Client knows server's X25519 public key (from blinded b32 address)
- Client performs DH: sharedSecret = X25519(clientPrivKey, serverPubKey)
- Client derives decryptionKey = HKDF(sharedSecret, salt, info)
- Client sends decryptionKey in BlindingInfoMessage
Workflow for PSK:
- Client and server share a 32-byte pre-shared key
- Client derives decryptionKey = HKDF(psk, salt, info)
- Client sends decryptionKey in BlindingInfoMessage
Since: I2CP 0.9.43+ Reference: I2P Proposal 123 - Encrypted LeaseSet, Proposal 149 - Per-Client Auth
meta_leaseset.go - MetaLeaseSet creation and management for I2CP per I2CP specification 0.9.38+ - MetaLeaseSet (type 7)
SessionCallbacks struct definition Moved from: session.go
Session struct definition Moved from: session.go
SignatureKeyPair struct definition Moved from: crypto.go
Index ¶
- Constants
- Variables
- func BlindPrivateKey(privateKey [64]byte, alpha [32]byte) ([64]byte, error)
- func BlindPublicKey(publicKey, alpha [32]byte) ([32]byte, error)
- func BuildSendMessageFlags(tagThreshold, tagCount uint8) uint16
- func CertLength(cert *Certificate) uint16
- func CertType(cert *Certificate) uint8
- func Debug(message string, args ...interface{})
- func DeriveBlindingFactor(secret []byte, date string) ([32]byte, error)
- func DeriveBlindingFactorForToday(secret []byte) ([32]byte, error)
- func DeriveBlindingFactorWithTimestamp(secret []byte, unixTimestamp int64) ([32]byte, error)
- func DerivePerClientAuthKey(scheme uint8, clientKey, serverKey [32]byte) ([32]byte, error)
- func DerivePerClientAuthKeyWithOptions(scheme uint8, clientKey, serverKey [32]byte, salt, info []byte) ([32]byte, error)
- func DisableBufferPool()
- func Ed25519PublicKeyFromStream(stream *Stream) (ed25519.PublicKey, error)
- func EnableBufferPool()
- func Error(message string, args ...interface{})
- func Fatal(message string, args ...interface{})
- func FormatDateForBlinding(t time.Time) string
- func GenerateRandomPrivateKey() ([32]byte, error)
- func GetCurrentBlindingDate() string
- func GetMessageStatusCategory(status SessionMessageStatus) string
- func HandleHostReplyAuthError(errorCode uint8) (message, action string)
- func Info(message string, args ...interface{})
- func IsBufferPoolEnabled() bool
- func IsFatal(err error) bool
- func IsMessageStatusFailure(status SessionMessageStatus) bool
- func IsMessageStatusRetriable(status SessionMessageStatus) bool
- func IsMessageStatusSuccess(status SessionMessageStatus) bool
- func IsTemporary(err error) bool
- func LogInit(level int)
- func NewMessageError(messageType uint8, operation string, err error) error
- func NewProtocolError(message string, code int, fatal bool) error
- func NewSessionError(sessionID uint16, operation string, err error) error
- func ParseConfig(s string, cb func(string, string))
- func ParseSendMessageFlags(flags uint16) (noLeaseSet bool, tagThreshold, tagCount uint8, err error)
- func ReleaseStream(s *Stream)
- func ResolveAddr(address string) (net.Addr, error)
- func RetryWithBackoff(ctx context.Context, maxRetries int, initialBackoff time.Duration, ...) error
- func UnblindPublicKey(blindedPublicKey, alpha [32]byte) ([32]byte, error)
- func ValidateSendMessageFlags(flags uint16) error
- func ValidateX25519PublicKey(publicKey [32]byte) bool
- func VerifyBlindedDestination(blindedPubKey, expectedPubKey, alpha [32]byte) bool
- func VerifyDHSharedSecret(clientPrivateKey, serverPublicKey [32]byte) (bool, error)
- func VerifyPSKDerivation(preSharedKey [32]byte) (bool, error)
- func Warning(message string, args ...interface{})
- func WriteCertificateToMessage(cert *Certificate, stream *Stream) error
- func WriteCertificateToStream(cert *Certificate, stream *Stream) error
- func WriteLeaseToLeaseSet2(l *Lease, stream *Stream) error
- func WriteLeaseToMessage(l *Lease, stream *Stream) error
- func X25519PublicKeyFromStream(stream *Stream) ([32]byte, error)
- type AuthResult
- type BandwidthLimits
- func (b *BandwidthLimits) InboundBytesPerSecond() int
- func (b *BandwidthLimits) OutboundBytesPerSecond() int
- func (b *BandwidthLimits) RouterInboundBurstBytesPerSecond() int
- func (b *BandwidthLimits) RouterInboundBytesPerSecond() int
- func (b *BandwidthLimits) RouterOutboundBurstBytesPerSecond() int
- func (b *BandwidthLimits) RouterOutboundBytesPerSecond() int
- func (b *BandwidthLimits) String() string
- type BlindingInfo
- func CreateDHBlindingInfo(destHash []byte, clientPrivateKey, serverPublicKey [32]byte, ...) (*BlindingInfo, error)
- func CreateDHBlindingInfoForHostname(hostname string, clientPrivateKey, serverPublicKey [32]byte, ...) (*BlindingInfo, error)
- func CreatePSKBlindingInfo(destHash []byte, preSharedKey [32]byte, blindedSigType uint16, ...) (*BlindingInfo, error)
- func CreatePSKBlindingInfoForHostname(hostname string, preSharedKey [32]byte, blindedSigType uint16, ...) (*BlindingInfo, error)
- func NewBlindingInfoWithDestination(destBytes []byte, blindedSigType uint16, expiration uint32) (*BlindingInfo, error)
- func NewBlindingInfoWithHash(hash []byte, blindedSigType uint16, expiration uint32) (*BlindingInfo, error)
- func NewBlindingInfoWithHostname(hostname string, blindedSigType uint16, expiration uint32) (*BlindingInfo, error)
- func NewBlindingInfoWithSigningKey(sigType uint16, signingPublicKey []byte, blindedSigType uint16, ...) (*BlindingInfo, error)
- func (info *BlindingInfo) ClearPerClientAuth()
- func (info *BlindingInfo) GetAuthSchemeName() string
- func (info *BlindingInfo) IsPerClientAuthEnabled() bool
- func (info *BlindingInfo) SetLookupPassword(password string)
- func (info *BlindingInfo) SetPerClientAuth(config *PerClientAuthConfig) error
- func (info *BlindingInfo) String() string
- type BlindingKeyDerivation
- type BufferPoolStats
- type Certificate
- type ChaCha20Poly1305Cipher
- func (c *ChaCha20Poly1305Cipher) AlgorithmType() uint32
- func (c *ChaCha20Poly1305Cipher) Decrypt(ciphertext, additionalData []byte) ([]byte, error)
- func (c *ChaCha20Poly1305Cipher) DecryptStream(src, dst *Stream, additionalData []byte) error
- func (c *ChaCha20Poly1305Cipher) Encrypt(plaintext, additionalData []byte) ([]byte, error)
- func (c *ChaCha20Poly1305Cipher) EncryptStream(src, dst *Stream, additionalData []byte) error
- func (c *ChaCha20Poly1305Cipher) Key() [32]byte
- func (c *ChaCha20Poly1305Cipher) NonceSize() int
- func (c *ChaCha20Poly1305Cipher) Overhead() int
- func (c *ChaCha20Poly1305Cipher) WriteToStream(stream *Stream) error
- type CircuitBreaker
- func (cb *CircuitBreaker) Execute(fn func() error) error
- func (cb *CircuitBreaker) Failures() int
- func (cb *CircuitBreaker) IsClosed() bool
- func (cb *CircuitBreaker) IsHalfOpen() bool
- func (cb *CircuitBreaker) IsOpen() bool
- func (cb *CircuitBreaker) RecordFailure()
- func (cb *CircuitBreaker) Reset()
- func (cb *CircuitBreaker) State() CircuitState
- func (cb *CircuitBreaker) String() string
- type CircuitState
- type Client
- func (c *Client) Close() error
- func (c *Client) Connect(ctx context.Context) error
- func (c *Client) CreateSession(ctx context.Context, sess *Session) error
- func (c *Client) CreateSessionSync(ctx context.Context, sess *Session) error
- func (c *Client) DestinationLookup(ctx context.Context, session *Session, address string) (uint32, error)
- func (c *Client) DisableAllDebugging()
- func (c *Client) DisableAutoReconnect()
- func (c *Client) DisableBatching() error
- func (c *Client) DisableMessageStats()
- func (c *Client) Disconnect()
- func (c *Client) EnableAllDebugging() error
- func (c *Client) EnableAutoReconnect(maxRetries int, initialBackoff time.Duration)
- func (c *Client) EnableBatching(flushTimer time.Duration, sizeThreshold int)
- func (c *Client) EnableDebugging(config *DebugConfig) error
- func (c *Client) EnableMessageStats()
- func (c *Client) GetCircuitBreakerState() CircuitState
- func (c *Client) GetConnectionState() *ConnectionState
- func (c *Client) GetMessageStats() *MessageStats
- func (c *Client) GetMetrics() MetricsCollector
- func (c *Client) GetProtocolDebugger() *ProtocolDebugger
- func (c *Client) GetStateTracker() *SessionStateTracker
- func (c *Client) IsAutoReconnectEnabled() bool
- func (c *Client) IsBatchingEnabled() bool
- func (c *Client) IsConnected() bool
- func (c *Client) PrintDiagnostics()
- func (c *Client) PrintFullDiagnostics()
- func (c *Client) ProcessIO(ctx context.Context) error
- func (c *Client) ReconnectAttempts() int
- func (c *Client) ResetCircuitBreaker() error
- func (c *Client) RouterCapabilities() uint32
- func (c *Client) RouterDate() uint64
- func (c *Client) RouterVersion() Version
- func (c *Client) SetMetrics(metrics MetricsCollector)
- func (c *Client) SetProperty(name, value string)
- func (c *Client) SupportsHostLookup() bool
- func (c *Client) SupportsMultiSession() bool
- func (c *Client) SupportsVersion(minVersion Version) bool
- func (c *Client) ValidatePerClientAuthSupport() error
- type ClientCallBacks
- type ClientProperty
- type ConnectionState
- type CreateSessionDump
- type Crypto
- func (c *Crypto) ChaCha20Poly1305CipherKeygen() (*ChaCha20Poly1305Cipher, error)
- func (c *Crypto) Ed25519SignatureKeygen() (*Ed25519KeyPair, error)
- func (c *Crypto) Random32() uint32
- func (c *Crypto) SignatureKeygen(algorithmTyp uint32) (sgk SignatureKeyPair, err error)
- func (c *Crypto) WriteEd25519SignatureToStream(kp *Ed25519KeyPair, stream *Stream) error
- func (c *Crypto) X25519KeyExchangeKeygen() (*X25519KeyPair, error)
- type DHAuthenticator
- type DebugConfig
- type Destination
- func NewDestination(crypto *Crypto) (dest *Destination, err error)
- func NewDestinationFromBase64(base64Str string, crypto *Crypto) (dest *Destination, err error)
- func NewDestinationFromFile(file *os.File, crypto *Crypto) (*Destination, error)
- func NewDestinationFromMessage(stream *Stream, crypto *Crypto) (dest *Destination, err error)
- func NewDestinationFromStream(stream *Stream, crypto *Crypto) (dest *Destination, err error)
- func (dest *Destination) Base32() string
- func (dest *Destination) Base64() string
- func (dest *Destination) Copy() (newDest Destination)
- func (dest *Destination) Hash() [32]byte
- func (dest *Destination) SigningKeyPair() (*Ed25519KeyPair, error)
- func (dest *Destination) SigningPublicKey() *Ed25519KeyPair
- func (dest *Destination) VerifySignature(message, signature []byte) bool
- func (dest *Destination) WriteForSignature(stream *Stream) (err error)
- func (dest *Destination) WriteToFile(filename string) (err error)
- func (dest *Destination) WriteToMessage(stream *Stream) (err error)
- func (dest *Destination) WriteToStream(stream *Stream) (err error)
- type DisconnectInfo
- type Ed25519KeyPair
- func (kp *Ed25519KeyPair) AlgorithmType() uint32
- func (kp *Ed25519KeyPair) PrivateKey() ed25519.PrivateKey
- func (kp *Ed25519KeyPair) PublicKey() ed25519.PublicKey
- func (kp *Ed25519KeyPair) Sign(message []byte) ([]byte, error)
- func (kp *Ed25519KeyPair) SignStream(stream *Stream) error
- func (kp *Ed25519KeyPair) Verify(message, signature []byte) bool
- func (kp *Ed25519KeyPair) VerifyStream(stream *Stream) (bool, error)
- func (kp *Ed25519KeyPair) WritePublicKeyToStream(stream *Stream) error
- func (kp *Ed25519KeyPair) WriteToStream(stream *Stream) error
- type InMemoryMetrics
- func (m *InMemoryMetrics) ActiveSessions() int
- func (m *InMemoryMetrics) AddBytesReceived(bytes uint64)
- func (m *InMemoryMetrics) AddBytesSent(bytes uint64)
- func (m *InMemoryMetrics) AllErrors() map[string]uint64
- func (m *InMemoryMetrics) AvgLatency(messageType uint8) time.Duration
- func (m *InMemoryMetrics) BytesReceived() uint64
- func (m *InMemoryMetrics) BytesSent() uint64
- func (m *InMemoryMetrics) ConnectionState() string
- func (m *InMemoryMetrics) Errors(errorType string) uint64
- func (m *InMemoryMetrics) IncrementError(errorType string)
- func (m *InMemoryMetrics) IncrementMessageReceived(messageType uint8)
- func (m *InMemoryMetrics) IncrementMessageSent(messageType uint8)
- func (m *InMemoryMetrics) MaxLatency(messageType uint8) time.Duration
- func (m *InMemoryMetrics) MessagesReceived(messageType uint8) uint64
- func (m *InMemoryMetrics) MessagesSent(messageType uint8) uint64
- func (m *InMemoryMetrics) MinLatency(messageType uint8) time.Duration
- func (m *InMemoryMetrics) RecordMessageLatency(messageType uint8, duration time.Duration)
- func (m *InMemoryMetrics) Reset()
- func (m *InMemoryMetrics) SetActiveSessions(count int)
- func (m *InMemoryMetrics) SetConnectionState(state string)
- type Lease
- type LeaseSet2
- func (ls *LeaseSet2) Destination() *Destination
- func (ls *LeaseSet2) Expires() time.Time
- func (ls *LeaseSet2) ExpiresSeconds() uint32
- func (ls *LeaseSet2) Flags() uint16
- func (ls *LeaseSet2) HasOfflineSignature() bool
- func (ls *LeaseSet2) IsExpired() bool
- func (ls *LeaseSet2) LeaseCount() int
- func (ls *LeaseSet2) Leases() []*lease.Lease2
- func (ls *LeaseSet2) OfflineSignature() *OfflineSignature
- func (ls *LeaseSet2) Properties() map[string]string
- func (ls *LeaseSet2) Published() time.Time
- func (ls *LeaseSet2) PublishedSeconds() uint32
- func (ls *LeaseSet2) Signature() []byte
- func (ls *LeaseSet2) String() string
- func (ls *LeaseSet2) Type() uint8
- func (ls *LeaseSet2) VerifySignature() bool
- type LeaseSetWaitInfo
- type LoggerTags
- type LookupEntry
- type MaxRetriesExceededError
- type MessageError
- type MessageStats
- func (ms *MessageStats) DiagnosticReport() string
- func (ms *MessageStats) Disable()
- func (ms *MessageStats) Enable()
- func (ms *MessageStats) GetLastReceived(msgType uint8) (time.Time, bool)
- func (ms *MessageStats) GetLastSent(msgType uint8) (time.Time, bool)
- func (ms *MessageStats) GetReceivedCount(msgType uint8) uint64
- func (ms *MessageStats) GetSentCount(msgType uint8) uint64
- func (ms *MessageStats) IsEnabled() bool
- func (ms *MessageStats) RecordReceived(msgType uint8, size uint64)
- func (ms *MessageStats) RecordSent(msgType uint8, size uint64)
- func (ms *MessageStats) Reset()
- func (ms *MessageStats) Summary() string
- type MetaLease
- type MetaLeaseSetConfig
- type MetricsCollector
- type OfflineSignature
- func (os *OfflineSignature) Expires() time.Time
- func (os *OfflineSignature) ExpiresSeconds() uint32
- func (sig *OfflineSignature) GetExpires() uint32
- func (sig *OfflineSignature) GetTransientKey() []byte
- func (sig *OfflineSignature) IsExpired() bool
- func (os *OfflineSignature) Signature() []byte
- func (os *OfflineSignature) SigningKey() []byte
- func (os *OfflineSignature) SigningKeyType() uint16
- func (os *OfflineSignature) String() string
- func (os *OfflineSignature) TransientKey() []byte
- func (os *OfflineSignature) TransientKeyType() uint16
- func (sig *OfflineSignature) Verify() error
- type PSKAuthenticator
- type PendingMessage
- type PerClientAuthConfig
- type ProtocolDebugger
- func (pd *ProtocolDebugger) DiagnosticReport() string
- func (pd *ProtocolDebugger) Disable()
- func (pd *ProtocolDebugger) DumpCreateSessionMessage(data []byte, destSize, mappingSize int, timestamp uint64, sigSize int)
- func (pd *ProtocolDebugger) Enable()
- func (pd *ProtocolDebugger) GetDisconnectInfo() *DisconnectInfo
- func (pd *ProtocolDebugger) GetMessageLog(limit int) []ProtocolMessage
- func (pd *ProtocolDebugger) IsEnabled() bool
- func (pd *ProtocolDebugger) LogMessage(direction string, msgType uint8, size uint32, data []byte, sessionID uint16)
- func (pd *ProtocolDebugger) RecordDisconnect(reason string, rawBytes []byte)
- func (pd *ProtocolDebugger) SetDumpDir(dir string)
- type ProtocolError
- type ProtocolMessage
- type RetryableFunc
- type RouterInfo
- type Session
- func (session *Session) BlindingFlags() uint16
- func (session *Session) BlindingParams() []byte
- func (session *Session) BlindingScheme() uint16
- func (session *Session) ClearBlinding()
- func (session *Session) ClearPendingMessages() int
- func (session *Session) Close() error
- func (session *Session) ClosedAt() time.Time
- func (session *Session) CompleteMessage(nonce uint32, status SessionMessageStatus) (*PendingMessage, bool)
- func (session *Session) Config() *SessionConfig
- func (s *Session) CreateMetaLeaseSet(config *MetaLeaseSetConfig) error
- func (s *Session) CreateMetaLeaseSetQueued(config *MetaLeaseSetConfig) error
- func (session *Session) CreatedAt() time.Time
- func (s *Session) DeriveBlindingKeysForDestination(date string) (*BlindingKeyDerivation, error)
- func (session *Session) Destination() *Destination
- func (session *Session) GetPendingMessage(nonce uint32) (*PendingMessage, bool)
- func (session *Session) GetPendingMessages() map[uint32]*PendingMessage
- func (session *Session) GetProperty(prop SessionConfigProperty) string
- func (session *Session) GetTunnelLength(inbound bool) int
- func (session *Session) GetTunnelQuantity(inbound bool) int
- func (session *Session) ID() uint16
- func (session *Session) IsBlindingEnabled() bool
- func (session *Session) IsClosed() bool
- func (session *Session) IsOffline() bool
- func (session *Session) IsPrimary() bool
- func (session *Session) LookupDestination(address string, timeout time.Duration) error
- func (session *Session) LookupDestinationWithContext(ctx context.Context, address string, timeout time.Duration) error
- func (session *Session) PendingMessageCount() int
- func (session *Session) PrimarySession() *Session
- func (session *Session) ReconfigureSession(properties map[string]string) error
- func (session *Session) ReconfigureSessionWithContext(ctx context.Context, properties map[string]string) error
- func (session *Session) SendBlindingInfo(info *BlindingInfo) error
- func (s *Session) SendBlindingInfoForHash(hash []byte, blindedSigType uint16, expiration uint32, ...) error
- func (s *Session) SendBlindingInfoForHostname(hostname string, blindedSigType uint16, expiration uint32, ...) error
- func (s *Session) SendBlindingInfoWithAuth(endpointType uint8, endpoint []byte, blindedSigType uint16, expiration uint32, ...) error
- func (session *Session) SendMessage(destination *Destination, protocol uint8, srcPort, destPort uint16, ...) error
- func (session *Session) SendMessageExpires(dest *Destination, protocol uint8, srcPort, destPort uint16, payload *Stream, ...) error
- func (session *Session) SendMessageExpiresWithContext(ctx context.Context, dest *Destination, protocol uint8, ...) error
- func (session *Session) SendMessageWithContext(ctx context.Context, destination *Destination, protocol uint8, ...) error
- func (session *Session) SessionID() uint16
- func (session *Session) SetBlindingFlags(flags uint16)
- func (session *Session) SetBlindingParams(params []byte)
- func (session *Session) SetBlindingScheme(scheme uint16)
- func (session *Session) SetID(id uint16)
- func (session *Session) SetPrimary(isPrimary bool)
- func (session *Session) SetPrimarySession(primary *Session) error
- func (session *Session) SigningKeyPair() (*Ed25519KeyPair, error)
- func (s *Session) StoreBlindingInfo(scheme, flags uint16, params []byte)
- func (session *Session) TrackMessage(nonce uint32, dest *Destination, protocol uint8, srcPort, destPort uint16, ...) error
- func (session *Session) TransientSigningKeyPair() (*Ed25519KeyPair, error)
- func (session *Session) ValidateProtocol(protocol uint8) error
- type SessionCallbacks
- type SessionConfig
- func (config *SessionConfig) GetOfflineSignatureBytes() []byte
- func (config *SessionConfig) GetOfflineSignatureExpiration() uint32
- func (config *SessionConfig) GetOfflineSignatureTransientKey() []byte
- func (config *SessionConfig) GetProperty(prop SessionConfigProperty) string
- func (config *SessionConfig) GetTransientKeyPair() *Ed25519KeyPair
- func (config *SessionConfig) HasOfflineSignature() bool
- func (config *SessionConfig) SetOfflineSignature(expiration uint32, transientPublicKey, signature []byte) error
- func (config *SessionConfig) SetProperty(prop SessionConfigProperty, value string)
- func (config *SessionConfig) SetTransientKeyPair(keyPair *Ed25519KeyPair) error
- func (config *SessionConfig) ValidateOfflineSignature() error
- func (config *SessionConfig) ValidateTimestamp() error
- type SessionConfigProperty
- type SessionError
- type SessionMessageStatus
- type SessionState
- type SessionStateTracker
- func (sst *SessionStateTracker) DiagnosticReport() string
- func (sst *SessionStateTracker) Disable()
- func (sst *SessionStateTracker) Enable()
- func (sst *SessionStateTracker) GetLeaseSetWaitDiagnostics() string
- func (sst *SessionStateTracker) GetState(sessionID uint16) (SessionState, bool)
- func (sst *SessionStateTracker) IsEnabled() bool
- func (sst *SessionStateTracker) RecordLeaseSetReceived(sessionID uint16, tunnelCount uint8)
- func (sst *SessionStateTracker) SetState(sessionID uint16, newState SessionState, reason string)
- func (sst *SessionStateTracker) StartLeaseSetWait(sessionID uint16, timeout time.Duration)
- type SessionStatus
- type SignatureKeyPair
- type StateTransition
- type Stream
- func (stream *Stream) ReadMapping() (map[string]string, error)
- func (s *Stream) ReadUint16() (uint16, error)
- func (s *Stream) ReadUint32() (uint32, error)
- func (s *Stream) ReadUint64() (uint64, error)
- func (s *Stream) Seek(offset int64, whence int) (int64, error)
- func (stream *Stream) WriteLenPrefixedString(s string) error
- func (stream *Stream) WriteMapping(m map[string]string) error
- func (s *Stream) WriteUint16(i uint16) error
- func (s *Stream) WriteUint32(i uint32) error
- func (s *Stream) WriteUint64(i uint64) error
- type Tcp
- func (tcp *Tcp) CanRead() bool
- func (tcp *Tcp) Connect() (err error)
- func (tcp *Tcp) Disconnect()
- func (tcp *Tcp) GetProperty(property TcpProperty) string
- func (tcp *Tcp) Init(routerAddress ...string) (err error)
- func (tcp *Tcp) IsConnected() bool
- func (tcp *Tcp) Receive(buf *Stream) (i int, err error)
- func (tcp *Tcp) Send(buf *Stream) (i int, err error)
- func (tcp *Tcp) SetProperty(property TcpProperty, value string)
- func (tcp *Tcp) SetupTLS(certFile, keyFile, caFile string, insecure bool) error
- type TcpProperty
- type Version
- type X25519KeyPair
- func (kp *X25519KeyPair) AlgorithmType() uint32
- func (kp *X25519KeyPair) GenerateSharedSecret(peerPublicKey [32]byte) ([32]byte, error)
- func (kp *X25519KeyPair) PrivateKey() [32]byte
- func (kp *X25519KeyPair) PublicKey() [32]byte
- func (kp *X25519KeyPair) WritePublicKeyToStream(stream *Stream) error
- func (kp *X25519KeyPair) WriteToStream(stream *Stream) error
Constants ¶
const ( // ProtoStreaming is reserved for I2P streaming connections. // Do not use this for datagrams. ProtoStreaming uint8 = 6 // ProtoDatagram (Datagram1) is for repliable, authenticated datagrams. // The sender's Destination is included and signed for authentication. // WARNING: Does NOT support offline signatures. Use ProtoDatagram2 for offline keys. ProtoDatagram uint8 = 17 // ProtoDatagramRaw is for raw, non-repliable datagrams. // No sender information is included - the receiver cannot reply. ProtoDatagramRaw uint8 = 18 // ProtoDatagram2 is for repliable datagrams with replay prevention. // Includes sender Destination, authentication, and timestamp for replay protection. // Supports offline signatures (LS2 offline keys). ProtoDatagram2 uint8 = 19 // ProtoDatagram3 is for repliable datagrams without authentication. // Includes sender Destination but no signature verification. ProtoDatagram3 uint8 = 20 )
I2P Application Protocol Number Constants
These protocol numbers identify the application-layer protocol within I2P messages. They are passed in the protocol field of SendMessage/SendMessageExpires messages and received in payload messages. These constants match the Java I2PSession interface.
Per I2P Datagram Specification (https://geti2p.net/spec/datagrams):
- Protocol 6 (Streaming) is reserved for streaming connections
- Protocol 17 (Datagram) is for repliable, authenticated datagrams (Datagram1)
- Protocol 18 (DatagramRaw) is for raw, non-repliable datagrams
- Protocol 19 (Datagram2) is for repliable datagrams with replay prevention
- Protocol 20 (Datagram3) is for repliable datagrams without authentication
IMPORTANT: Datagram1 (protocol 17) does NOT support offline signatures (LS2 offline keys). If Session.IsOffline() returns true, use Datagram2 (protocol 19) instead.
const ( I2CP_CLIENT_VERSION = "0.9.66" I2CP_PROTOCOL_INIT uint8 = 0x2a I2CP_MESSAGE_SIZE = 0xffff I2CP_MAX_MESSAGE_PAYLOAD_SIZE = 65536 // 64KB max payload per I2CP spec (spec says "about 64 KB") I2CP_SAFE_MESSAGE_SIZE = 64000 // Conservative limit for universal router compatibility I2CP_MAX_SESSIONS = 0xffff I2CP_MAX_SESSIONS_PER_CLIENT = 32 // Session ID 0xFFFF is reserved per I2CP spec for "no session" operations // Used for hostname lookups and other operations that don't require a session I2CP_SESSION_ID_NONE uint16 = 0xFFFF )
I2CP Client Constants Moved from: client.go
const ( I2CP_MSG_ANY uint8 = 0 I2CP_MSG_BANDWIDTH_LIMITS uint8 = 23 I2CP_MSG_CREATE_LEASE_SET uint8 = 4 I2CP_MSG_CREATE_LEASE_SET2 uint8 = 41 I2CP_MSG_CREATE_SESSION uint8 = 1 I2CP_MSG_DEST_LOOKUP uint8 = 34 I2CP_MSG_DEST_REPLY uint8 = 35 I2CP_MSG_DESTROY_SESSION uint8 = 3 I2CP_MSG_DISCONNECT uint8 = 30 I2CP_MSG_GET_BANDWIDTH_LIMITS uint8 = 8 I2CP_MSG_GET_DATE uint8 = 32 I2CP_MSG_HOST_LOOKUP uint8 = 38 I2CP_MSG_HOST_REPLY uint8 = 39 I2CP_MSG_MESSAGE_STATUS uint8 = 22 I2CP_MSG_PAYLOAD_MESSAGE uint8 = 31 I2CP_MSG_RECEIVE_MESSAGE_BEGIN uint8 = 6 // DEPRECATED: Not used in fastReceive mode (default since 0.9.4) I2CP_MSG_RECEIVE_MESSAGE_END uint8 = 7 // DEPRECATED: Not used in fastReceive mode (default since 0.9.4) I2CP_MSG_RECONFIGURE_SESSION uint8 = 2 I2CP_MSG_REPORT_ABUSE uint8 = 29 // DEPRECATED: Never fully implemented, unsupported I2CP_MSG_REQUEST_LEASESET uint8 = 21 I2CP_MSG_REQUEST_VARIABLE_LEASESET uint8 = 37 I2CP_MSG_SEND_MESSAGE uint8 = 5 I2CP_MSG_SEND_MESSAGE_EXPIRES uint8 = 36 I2CP_MSG_SESSION_STATUS uint8 = 20 I2CP_MSG_SET_DATE uint8 = 33 I2CP_MSG_BLINDING_INFO uint8 = 42 )
I2CP Message Type Constants Moved from: client.go
const ( AUTH_METHOD_NONE uint8 = 0 // No authentication required AUTH_METHOD_USERNAME_PWD uint8 = 1 // Username/password authentication (0.9.11+) AUTH_METHOD_SSL_TLS uint8 = 2 // SSL/TLS certificate authentication (0.8.3+) AUTH_METHOD_PER_CLIENT_DH uint8 = 3 // Per-client DH for BlindingInfo (0.9.43+) - NOT for session auth AUTH_METHOD_PER_CLIENT_PSK uint8 = 4 // Per-client PSK for BlindingInfo (0.9.43+) - NOT for session auth )
Authentication Method Constants per I2CP specification for GetDateMessage protocol initialization authentication
IMPORTANT: Methods 0-2 are I2CP session authentication methods for GetDateMessage. Methods 3-4 are NOT I2CP session auth methods - they are for encrypted LeaseSet per-client authentication via BlindingInfoMessage (see per_client_auth.go).
Support Status in go-i2cp:
- AUTH_METHOD_NONE (0): ✅ Fully supported
- AUTH_METHOD_USERNAME_PWD (1): ✅ Fully supported (via i2cp.username, i2cp.password)
- AUTH_METHOD_SSL_TLS (2): ✅ Fully supported (via i2cp.SSL configuration)
- AUTH_METHOD_PER_CLIENT_DH (3): ✅ Supported via BlindingInfoMessage (see per_client_auth.go)
- AUTH_METHOD_PER_CLIENT_PSK (4): ✅ Supported via BlindingInfoMessage (see per_client_auth.go)
For per-client authentication to encrypted LeaseSets, use:
- NewPerClientAuthDH() for DH authentication
- NewPerClientAuthPSK() for PSK authentication
- BlindingInfo.SetPerClientAuth() to configure
const ( HOST_REPLY_SUCCESS uint8 = 0 // Lookup successful HOST_REPLY_FAILURE uint8 = 1 // General lookup failure HOST_REPLY_PASSWORD_REQUIRED uint8 = 2 // Password required for encrypted LeaseSet (since 0.9.43) HOST_REPLY_PRIVATE_KEY_REQUIRED uint8 = 3 // Private key required for per-client auth (since 0.9.43) HOST_REPLY_PASSWORD_AND_KEY_REQUIRED uint8 = 4 // Both password and key required (since 0.9.43) HOST_REPLY_DECRYPTION_FAILURE uint8 = 5 // Failed to decrypt LeaseSet (since 0.9.43) HOST_REPLY_LEASESET_LOOKUP_FAILURE uint8 = 6 // LeaseSet not found in network database (since 0.9.66) HOST_REPLY_LOOKUP_TYPE_UNSUPPORTED uint8 = 7 // Lookup type not supported by router (since 0.9.66) )
HostReply Error Codes (I2CP Proposal 167) per I2CP specification for HostReplyMessage error handling
const ( LEASESET_TYPE_LEGACY uint8 = 1 // Legacy LeaseSet (deprecated) LEASESET_TYPE_STANDARD uint8 = 3 // Standard LeaseSet2 LEASESET_TYPE_ENCRYPTED uint8 = 5 // EncryptedLeaseSet LEASESET_TYPE_META uint8 = 7 // MetaLeaseSet (preliminary) )
LeaseSet Type Constants per I2CP specification for CreateLeaseSet2Message
const ( BLINDING_AUTH_SCHEME_DH uint8 = 0 // Diffie-Hellman client authentication (or no per-client auth) BLINDING_AUTH_SCHEME_PSK uint8 = 1 // Pre-Shared Key client authentication )
Blinding Authentication Scheme Constants per I2CP specification for BlindingInfoMessage authentication
Blinding is used for encrypted LeaseSet access (I2CP 0.9.43+). The client sends BlindingInfoMessage to advise the router about blinded destinations with optional lookup passwords and/or private keys for decryption.
Support Status in go-i2cp:
- BLINDING_AUTH_SCHEME_DH (0): ✅ Supported via msgBlindingInfo()
- BLINDING_AUTH_SCHEME_PSK (1): ✅ Supported via msgBlindingInfo()
Blinding workflow:
- Client sends BlindingInfoMessage to router before messaging a blinded destination
- Router uses the info to look up and decrypt the destination's LeaseSet
- Router does NOT reply to this message
Per SPEC.md § BlindingInfoMessage: "Before a client sends a message to a blinded destination, it must either lookup the 'b33' in a Host Lookup message, or send a Blinding Info message."
const ( BLINDING_ENDPOINT_HASH uint8 = 0 // 32-byte SHA-256 hash of destination BLINDING_ENDPOINT_HOSTNAME uint8 = 1 // hostname String (address book lookup) BLINDING_ENDPOINT_DESTINATION uint8 = 2 // full binary Destination BLINDING_ENDPOINT_SIGKEY uint8 = 3 // 2-byte sig type + SigningPublicKey )
Blinding Endpoint Type Constants per I2CP specification for BlindingInfoMessage endpoint identification
The endpoint identifies which blinded destination the blinding info applies to. Different types allow specifying the destination by hash, hostname, full destination, or signing key.
const ( BLINDING_FLAG_PER_CLIENT uint8 = 0x01 // Bit 0: per-client authentication enabled BLINDING_FLAG_SECRET uint8 = 0x10 // Bit 4: lookup password required BLINDING_FLAG_AUTH_DH uint8 = 0x00 // Bits 3-1: DH authentication (000) BLINDING_FLAG_AUTH_PSK uint8 = 0x02 // Bits 3-1: PSK authentication (001) BLINDING_FLAG_AUTH_MASK uint8 = 0x0E // Bits 3-1: authentication scheme mask BLINDING_FLAG_RESERVED_MASK uint8 = 0xE0 // Bits 7-5: reserved, must be 0 )
Blinding Flag Constants per I2CP specification for BlindingInfoMessage flags field
Flags field is 1 byte with bit layout: 76543210
- Bit 0: 0=everybody, 1=per-client authentication
- Bits 3-1: Auth scheme (if bit 0 is 1), otherwise 000
- Bit 4: 1=secret (lookup password) required
- Bits 7-5: Reserved, must be 0
const ( // Bit masks for validation SEND_MSG_FLAGS_RESERVED_MASK uint16 = 0xF800 // Bits 15-11: reserved, must be 0 SEND_MSG_FLAGS_RELIABILITY_MASK uint16 = 0x0600 // Bits 10-9: deprecated reliability override SEND_MSG_FLAGS_TAG_THRESHOLD uint16 = 0x00F0 // Bits 7-4: low tag threshold (ElGamal only) SEND_MSG_FLAGS_TAG_COUNT uint16 = 0x000F // Bits 3-0: tags to send (ElGamal only) // Bit 8: LeaseSet bundling control (the only modern flag still used) SEND_MSG_FLAG_NO_LEASESET uint16 = 0x0100 // Don't bundle LeaseSet with message )
SendMessageExpires Flag Constants per I2CP specification § SendMessageExpiresMessage (I2CP 0.8.4+)
These flags control message delivery options for SendMessageExpiresMessage (type 36). The flags field is 2 bytes (16 bits) with the following layout (bit order 15...0):
Bits 15-11: Reserved, must be 0 Bits 10-9: Message Reliability Override (DEPRECATED - unimplemented, to be removed) Bit 8: Don't bundle LeaseSet (SEND_MSG_FLAG_NO_LEASESET) Bits 7-4: Low tag threshold (ElGamal only, ignored for ECIES-Ratchet) Bits 3-0: Tags to send (ElGamal only, ignored for ECIES-Ratchet)
IMPORTANT: ElGamal-specific flags (bits 7-0) are obsolete in modern I2P. As of I2CP 0.9.39+, all encryption uses ECIES-Ratchet, which does not use session tags. These flags are kept for backward compatibility but have no effect with ECIES-Ratchet.
Usage Example:
flags := SEND_MSG_FLAG_NO_LEASESET | BuildSendMessageFlags(0, 0) session.SendMessageExpires(dest, protocol, srcPort, destPort, payload, flags, expiration)
const ( SEND_MSG_TAG_THRESHOLD_DEFAULT uint8 = 0 // Use session key manager settings SEND_MSG_TAG_THRESHOLD_2 uint8 = 1 // Threshold: 2 tags SEND_MSG_TAG_THRESHOLD_3 uint8 = 2 // Threshold: 3 tags SEND_MSG_TAG_THRESHOLD_6 uint8 = 3 // Threshold: 6 tags SEND_MSG_TAG_THRESHOLD_9 uint8 = 4 // Threshold: 9 tags SEND_MSG_TAG_THRESHOLD_14 uint8 = 5 // Threshold: 14 tags SEND_MSG_TAG_THRESHOLD_20 uint8 = 6 // Threshold: 20 tags SEND_MSG_TAG_THRESHOLD_27 uint8 = 7 // Threshold: 27 tags SEND_MSG_TAG_THRESHOLD_35 uint8 = 8 // Threshold: 35 tags SEND_MSG_TAG_THRESHOLD_45 uint8 = 9 // Threshold: 45 tags SEND_MSG_TAG_THRESHOLD_57 uint8 = 10 // Threshold: 57 tags SEND_MSG_TAG_THRESHOLD_72 uint8 = 11 // Threshold: 72 tags SEND_MSG_TAG_THRESHOLD_92 uint8 = 12 // Threshold: 92 tags SEND_MSG_TAG_THRESHOLD_117 uint8 = 13 // Threshold: 117 tags SEND_MSG_TAG_THRESHOLD_147 uint8 = 14 // Threshold: 147 tags SEND_MSG_TAG_THRESHOLD_192 uint8 = 15 // Threshold: 192 tags )
SendMessageExpires Tag Threshold Values (ElGamal Only - OBSOLETE) per I2CP specification § SendMessageExpiresMessage Flags Field
NOTE: These are only relevant for ElGamal encryption, which is deprecated. Modern ECIES-Ratchet encryption ignores these values. These constants are provided for completeness but should not be used in new code.
Tag threshold: if there are fewer than this many tags available, send more. This is advisory and does not force tags to be delivered.
const ( SEND_MSG_TAG_COUNT_DEFAULT uint8 = 0 // Use session key manager settings SEND_MSG_TAG_COUNT_2 uint8 = 1 // Send 2 tags SEND_MSG_TAG_COUNT_4 uint8 = 2 // Send 4 tags SEND_MSG_TAG_COUNT_6 uint8 = 3 // Send 6 tags SEND_MSG_TAG_COUNT_8 uint8 = 4 // Send 8 tags SEND_MSG_TAG_COUNT_12 uint8 = 5 // Send 12 tags SEND_MSG_TAG_COUNT_16 uint8 = 6 // Send 16 tags SEND_MSG_TAG_COUNT_24 uint8 = 7 // Send 24 tags SEND_MSG_TAG_COUNT_32 uint8 = 8 // Send 32 tags SEND_MSG_TAG_COUNT_40 uint8 = 9 // Send 40 tags SEND_MSG_TAG_COUNT_51 uint8 = 10 // Send 51 tags SEND_MSG_TAG_COUNT_64 uint8 = 11 // Send 64 tags SEND_MSG_TAG_COUNT_80 uint8 = 12 // Send 80 tags SEND_MSG_TAG_COUNT_100 uint8 = 13 // Send 100 tags SEND_MSG_TAG_COUNT_125 uint8 = 14 // Send 125 tags SEND_MSG_TAG_COUNT_160 uint8 = 15 // Send 160 tags )
SendMessageExpires Tags to Send Values (ElGamal Only - OBSOLETE) per I2CP specification § SendMessageExpiresMessage Flags Field
NOTE: These are only relevant for ElGamal encryption, which is deprecated. Modern ECIES-Ratchet encryption ignores these values. These constants are provided for completeness but should not be used in new code.
Number of tags to send if required. This is advisory and does not force tags to be delivered.
const ( HOST_LOOKUP_TYPE_HASH = 0 // Basic hash lookup (since 0.9.11) HOST_LOOKUP_TYPE_HOSTNAME = 1 // Basic hostname lookup (since 0.9.11) HOST_LOOKUP_TYPE_HASH_WITH_OPTIONS = 2 // Hash + LeaseSet options mapping (since 0.9.66) HOST_LOOKUP_TYPE_HOSTNAME_WITH_OPTIONS = 3 // Hostname + LeaseSet options mapping (since 0.9.66) HOST_LOOKUP_TYPE_DEST_WITH_OPTIONS = 4 // Destination + LeaseSet options mapping (since 0.9.66) )
Host Lookup Type Constants (I2CP § HostLookupMessage)
Per I2CP 0.9.11+, extended in 0.9.66 with options mappings (Proposal 167 - Service Records).
Basic lookups (types 0-1) resolve an I2P destination from either a hash or hostname. Service record lookups (types 2-4) additionally return the LeaseSet's options Mapping, which can contain service-specific metadata like protocol information.
Router Version Requirements:
- Types 0-1: Require I2CP 0.9.11+ router
- Types 2-4: Require I2CP 0.9.66+ router (Proposal 167)
Note: If the router does not support the requested lookup type, it returns HOST_REPLY_LOOKUP_TYPE_UNSUPPORTED (code 7).
const ( CERTIFICATE_NULL uint8 = 0 CERTIFICATE_HASHCASH uint8 = 1 CERTIFICATE_SIGNED uint8 = 2 CERTIFICATE_MULTIPLE uint8 = 3 CERTIFICATE_KEY uint8 = 5 )
Certificate Type Constants Moved from: certificate.go
const ( PUB_KEY_SIZE = 256 DIGEST_SIZE = 32 // SHA-256 digest size for Ed25519 DEST_SIZE = 4096 )
Destination Size Constants Moved from: destination.go
const ( HASH_SHA1 uint8 = iota HASH_SHA256 uint8 = iota )
Hash Algorithm Constants Moved from: crypto.go
const ( CODEC_BASE32 uint8 = iota CODEC_BASE64 uint8 = iota )
Codec Algorithm Constants Moved from: crypto.go
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 )
Logger Level Constants Moved from: logger.go
const ( MSG_STATUS_AVAILABLE uint8 = 0 // DEPRECATED: Message available for pickup MSG_STATUS_ACCEPTED uint8 = 1 // Message accepted by router MSG_STATUS_BEST_EFFORT_SUCCESS uint8 = 2 // Best-effort delivery succeeded MSG_STATUS_BEST_EFFORT_FAILURE uint8 = 3 // Best-effort delivery failed MSG_STATUS_GUARANTEED_SUCCESS uint8 = 4 // Guaranteed delivery succeeded MSG_STATUS_GUARANTEED_FAILURE uint8 = 5 // Guaranteed delivery failed MSG_STATUS_LOCAL_SUCCESS uint8 = 6 // Local delivery succeeded MSG_STATUS_LOCAL_FAILURE uint8 = 7 // Local delivery failed MSG_STATUS_ROUTER_FAILURE uint8 = 8 // Router error MSG_STATUS_NETWORK_FAILURE uint8 = 9 // Network error MSG_STATUS_BAD_SESSION uint8 = 10 // Invalid session ID MSG_STATUS_BAD_MESSAGE uint8 = 11 // Malformed message MSG_STATUS_BAD_OPTIONS uint8 = 12 // Invalid message options or expiration (I2CP 0.9.5+) MSG_STATUS_OVERFLOW_FAILURE uint8 = 13 // Queue overflow MSG_STATUS_MESSAGE_EXPIRED uint8 = 14 // Message expired MSG_STATUS_BAD_LOCAL_LEASESET uint8 = 15 // Local LeaseSet invalid MSG_STATUS_NO_LOCAL_TUNNELS uint8 = 16 // No local tunnels available MSG_STATUS_UNSUPPORTED_ENCRYPTION uint8 = 17 // Encryption type unsupported MSG_STATUS_BAD_DESTINATION uint8 = 18 // Destination invalid MSG_STATUS_BAD_LEASESET uint8 = 19 // Remote LeaseSet invalid MSG_STATUS_EXPIRED_LEASESET uint8 = 20 // Remote LeaseSet expired MSG_STATUS_NO_LEASESET uint8 = 21 // Remote LeaseSet not found MSG_STATUS_META_LEASESET uint8 = 22 // MetaLeaseSet received (since 0.9.41) MSG_STATUS_LOOPBACK_DENIED uint8 = 23 // Loopback message denied (since 0.9.62) )
MessageStatus Codes (I2CP MessageStatusMessage) Complete status codes 0-23 per I2CP specification Used in MessageStatusMessage (type 22) to report delivery status
const ( // ELS2AuthInfo is the HKDF info string for Encrypted LeaseSet2 per-client auth // per I2P Proposal 149 ELS2AuthInfo = "ELS2_L1K" // ELS2AuthSalt is the default salt for ELS2 auth derivation // (empty per specification - salt comes from blinding factor) ELS2AuthSalt = "" )
I2P context strings for HKDF derivation
const ( META_LEASE_TYPE_UNKNOWN uint8 = 0 // Unknown type META_LEASE_TYPE_LEASESET uint8 = 1 // Legacy LeaseSet META_LEASE_TYPE_LEASESET2 uint8 = 3 // LeaseSet2 META_LEASE_TYPE_META uint8 = 5 // Nested MetaLeaseSet )
MetaLeaseSet type constants for the Flags field
const (
CHACHA20_POLY1305 uint32 = 4
)
Encryption Algorithm Constants
const (
ED25519_SHA256 uint32 = 7
)
Signature Algorithm Constants Moved from: crypto.go Modern I2CP uses Ed25519 (type 7) exclusively
const ROUTER_CAN_HOST_LOOKUP uint32 = 1
Router Capabilities Constants Moved from: client.go
const (
TAG = CLIENT
)
Tag Constants Moved from: crypto.go, destination.go, client.go
const (
X25519 uint32 = 4
)
Key Exchange Algorithm Constants
Variables ¶
var ( // ErrSessionInvalid indicates an operation was attempted on an invalid or closed session. // This typically occurs when trying to use a session ID that doesn't exist or has been destroyed. // I2CP spec: SessionStatusMessage status code 3 (Invalid) ErrSessionInvalid = errors.New("i2cp: session invalid or closed") // ErrConnectionClosed indicates the TCP connection to the I2P router was closed. // This may occur due to network issues, router shutdown, or explicit disconnect. ErrConnectionClosed = errors.New("i2cp: connection closed") // ErrMessageTooLarge indicates a message exceeds the I2CP protocol size limit. // I2CP spec: Maximum message size is approximately 64 KB (0xFFFF bytes) ErrMessageTooLarge = errors.New("i2cp: message exceeds size limit") // ErrAuthenticationFailed indicates authentication with the router failed. // This may occur with username/password, TLS certificate, or per-client authentication. // I2CP spec: Authentication support added in protocol version 0.9.11+ ErrAuthenticationFailed = errors.New("i2cp: authentication failed") // ErrProtocolVersion indicates an unsupported I2CP protocol version was detected. // The client should gracefully degrade or refuse connection. // I2CP spec: Supports versions 0.6.5 through 0.9.66 ErrProtocolVersion = errors.New("i2cp: unsupported protocol version") // ErrTimeout indicates an operation exceeded its allowed time limit. // Operations should respect context.Context deadlines when provided. ErrTimeout = errors.New("i2cp: operation timed out") // ErrNoPrimarySession indicates a subsession operation was attempted without a primary session. // I2CP spec: Multi-session support added in protocol version 0.9.21+ ErrNoPrimarySession = errors.New("i2cp: no primary session exists for subsession creation") // ErrMultiSessionUnsupported indicates the router doesn't support multiple sessions. // I2CP spec: Check router version >= 0.9.21 before creating subsessions ErrMultiSessionUnsupported = errors.New("i2cp: router does not support multi-session") // ErrInvalidDestination indicates a malformed or invalid destination was provided. // Destinations must contain valid cryptographic keys and certificates. ErrInvalidDestination = errors.New("i2cp: invalid destination format") // ErrInvalidLeaseSet indicates a malformed or invalid LeaseSet was received. // LeaseSets must contain valid leases, signatures, and cryptographic data. ErrInvalidLeaseSet = errors.New("i2cp: invalid leaseset format") // ErrMessageParsing indicates a failure to parse an incoming I2CP message. // This typically indicates protocol violations or corrupted data. ErrMessageParsing = errors.New("i2cp: message parsing failed") // ErrInvalidSessionID indicates an invalid session ID was used. // Session IDs must be 2-byte integers assigned by the router. // Session ID 0xFFFF is reserved for no-session operations. ErrInvalidSessionID = errors.New("i2cp: invalid session id") // ErrSessionRefused indicates the router refused to create the session. // This may occur due to resource limits or configuration issues. // I2CP spec: SessionStatusMessage status code 4 (Refused) added in 0.9.12 ErrSessionRefused = errors.New("i2cp: session creation refused by router") // ErrNotConnected indicates an operation requires an active connection but none exists. ErrNotConnected = errors.New("i2cp: not connected to router") // ErrAlreadyConnected indicates Connect() was called on an already-connected client. ErrAlreadyConnected = errors.New("i2cp: already connected") // ErrInvalidConfiguration indicates the session configuration is invalid. // Configuration must include valid destination, options, and signature. ErrInvalidConfiguration = errors.New("i2cp: invalid session configuration") // ErrDestinationLookupFailed indicates a destination lookup operation failed. // This is equivalent to a DNS lookup failure in the I2P network. // I2CP spec: MessageStatusMessage status code 21 (No Leaseset) ErrDestinationLookupFailed = errors.New("i2cp: destination lookup failed") // ErrBlindingRequired indicates a blinded destination requires BlindingInfo. // Blinded destinations (b33 addresses) need authentication parameters. // I2CP spec: BlindingInfoMessage support added in protocol version 0.9.43+ ErrBlindingRequired = errors.New("i2cp: blinding info required for encrypted leaseset") // ErrUnsupportedCrypto indicates an unsupported cryptographic algorithm was encountered. // The library supports Ed25519 signatures, X25519 key exchange, and ChaCha20-Poly1305 AEAD. ErrUnsupportedCrypto = errors.New("i2cp: unsupported cryptographic algorithm") // ErrInvalidSignature indicates a cryptographic signature verification failed. // This typically indicates data corruption or a security issue. ErrInvalidSignature = errors.New("i2cp: invalid signature") // ErrOfflineSignatureExpired indicates an offline signature has expired. // Offline signatures have an expiration timestamp and must be rejected after expiry. // I2CP spec: LeaseSet2 § Offline Signatures ErrOfflineSignatureExpired = errors.New("i2cp: offline signature expired") // ErrOfflineSignatureInvalid indicates offline signature cryptographic verification failed. // The signature over [signingKey||expires||transientKey] did not match. // I2CP spec: LeaseSet2 § Offline Signatures ErrOfflineSignatureInvalid = errors.New("i2cp: offline signature verification failed") // ErrMaxSessionsReached indicates the maximum number of sessions per client has been reached. // I2CP spec: Maximum sessions per client is defined by I2CP_MAX_SESSIONS_PER_CLIENT ErrMaxSessionsReached = errors.New("i2cp: maximum sessions per client reached") // ErrClientClosed indicates an operation was attempted on a closed client. // All operations will fail after Close() has been called. ErrClientClosed = errors.New("i2cp: client is closed") // ErrClientNotInitialized indicates an operation was attempted on an uninitialized client. // Clients must be created using NewClient() to ensure proper initialization. // Zero-value Client{} instances are not safe to use. ErrClientNotInitialized = errors.New("i2cp: client not initialized (use NewClient)") // ErrSessionNotInitialized indicates an operation was attempted on an uninitialized session. // Sessions must be created using NewSession() or NewSessionWithContext() to ensure proper initialization. // Zero-value Session{} instances are not safe to use. ErrSessionNotInitialized = errors.New("i2cp: session not initialized (use NewSession)") // ErrInvalidArgument indicates a nil or invalid argument was passed to a public API method. // All public methods validate their parameters and return this error for nil values. ErrInvalidArgument = errors.New("i2cp: invalid argument (nil or empty value)") )
Sentinel errors for common I2CP protocol violations and failures
var ( // VersionFastReceive is the minimum version for fast receive mode (deprecates ReceiveMessageBegin/End) VersionFastReceive = Version{/* contains filtered or unexported fields */} // VersionHostLookup is the minimum version for HostLookup/HostReply (deprecates DestLookup/DestReply) VersionHostLookup = Version{/* contains filtered or unexported fields */} // VersionMultiSession is the minimum version for multi-session support VersionMultiSession = Version{/* contains filtered or unexported fields */} // VersionCreateLeaseSet2 is the minimum version for CreateLeaseSet2Message (type 41) VersionCreateLeaseSet2 = Version{/* contains filtered or unexported fields */} // VersionBlindingInfo is the minimum version for BlindingInfoMessage (type 42) VersionBlindingInfo = Version{/* contains filtered or unexported fields */} // VersionProposal167 is the minimum version for Proposal 167 (HostReply options mapping) VersionProposal167 = Version{/* contains filtered or unexported fields */} )
Predefined router version requirements for I2CP features. These match the I2CP spec version notes and can be used with SupportsVersion().
Functions ¶
func BlindPrivateKey ¶
BlindPrivateKey blinds an Ed25519 private key using a blinding factor. The blinding operation: d' = d + alpha (mod L)
The blinded private key can sign on behalf of the blinded public key. Both the public and private key must be blinded with the same alpha.
Parameters:
- privateKey: 64-byte Ed25519 private key to blind
- alpha: 32-byte blinding factor from DeriveBlindingFactor
Returns:
- Blinded 64-byte value [scalar][pubkey]
- Error if private key is invalid or alpha is invalid
func BlindPublicKey ¶
BlindPublicKey blinds an Ed25519 public key using a blinding factor. The blinding operation: P' = P + [alpha]B
This is used to create unlinkable blinded destinations for EncryptedLeaseSet. The same alpha applied to different public keys produces different blinded keys, ensuring destinations cannot be correlated.
Parameters:
- publicKey: 32-byte Ed25519 public key to blind
- alpha: 32-byte blinding factor from DeriveBlindingFactor
Returns:
- Blinded 32-byte public key
- Error if public key is invalid or alpha is invalid
func BuildSendMessageFlags ¶
BuildSendMessageFlags constructs the flags field for SendMessageExpiresMessage per I2CP specification § SendMessageExpiresMessage (I2CP 0.8.4+)
IMPORTANT: Tag threshold and tag count are OBSOLETE parameters. They are only relevant for ElGamal encryption (deprecated). Modern I2P uses ECIES-Ratchet encryption which does not use session tags. These parameters are kept for backward compatibility but have no effect with ECIES-Ratchet.
Modern usage should use:
flags := BuildSendMessageFlags(0, 0) // Use defaults (tag params ignored) flags |= SEND_MSG_FLAG_NO_LEASESET // Optionally prevent LeaseSet bundling
Parameters:
- tagThreshold: Low tag threshold (0-15), ElGamal only. Use 0 for default.
- tagCount: Tags to send (0-15), ElGamal only. Use 0 for default.
Returns the flags value suitable for use with Session.SendMessageExpires()
func CertLength ¶ added in v0.1.52
func CertLength(cert *Certificate) uint16
CertLength is a helper that returns the certificate data length as uint16. Returns 0 if length extraction fails.
func CertType ¶ added in v0.1.52
func CertType(cert *Certificate) uint8
CertType is a helper that returns the certificate type as uint8. Returns 0 (CERTIFICATE_NULL) if type extraction fails.
func Debug ¶
func Debug(message string, args ...interface{})
Debug logs a debug message with optional arguments. Deprecated: Use github.com/go-i2p/logger directly for new code. The tags parameter has been removed; use logger.Debug() or logger.Debugf() instead.
func DeriveBlindingFactor ¶
DeriveBlindingFactor derives a blinding factor (alpha) from a secret and date. This creates a unique per-day blinding factor for EncryptedLeaseSet rotation.
The derivation uses HKDF-SHA256 with the date as salt, producing a 32-byte canonical Ed25519 scalar suitable for key blinding.
Parameters:
- secret: Secret key material (at least 32 bytes, typically from private key seed)
- date: Date in "YYYY-MM-DD" format (use kdf.GetCurrentBlindingDate() for today)
Returns:
- alpha: 32-byte blinding factor
- error: If secret is too short or date format is invalid
Example:
secret := privateKey.Seed()
alpha, err := DeriveBlindingFactor(secret, "2025-11-24")
if err != nil {
return err
}
func DeriveBlindingFactorForToday ¶
DeriveBlindingFactorForToday derives a blinding factor for the current UTC date. This is a convenience wrapper for DeriveBlindingFactor with today's date.
func DeriveBlindingFactorWithTimestamp ¶
DeriveBlindingFactorWithTimestamp derives a blinding factor from a Unix timestamp. The timestamp is converted to a UTC date in YYYY-MM-DD format.
func DerivePerClientAuthKey ¶
DerivePerClientAuthKey is a convenience function that derives the decryption key for per-client authentication. It handles both DH and PSK schemes.
For DH: clientKey is your X25519 private key, serverKey is server's public key For PSK: clientKey is the pre-shared key, serverKey is ignored (can be zero)
Returns the 32-byte decryption key to use in BlindingInfoMessage.
func DerivePerClientAuthKeyWithOptions ¶
func DerivePerClientAuthKeyWithOptions(scheme uint8, clientKey, serverKey [32]byte, salt, info []byte) ([32]byte, error)
DerivePerClientAuthKeyWithOptions derives the decryption key with custom HKDF parameters.
func DisableBufferPool ¶
func DisableBufferPool()
DisableBufferPool disables global buffer pooling. After calling this, NewStream will allocate fresh buffers.
func Ed25519PublicKeyFromStream ¶
Ed25519PublicKeyFromStream reads only the public key from a stream. Returns stdlib ed25519.PublicKey for backward compatibility.
func EnableBufferPool ¶
func EnableBufferPool()
EnableBufferPool enables global buffer pooling for Stream allocations. This reduces GC pressure by reusing byte slices across Stream instances.
func Error ¶
func Error(message string, args ...interface{})
Error logs an error message with optional arguments. Deprecated: Use github.com/go-i2p/logger directly for new code. The tags parameter has been removed; use logger.Error() or logger.Errorf() instead.
func Fatal ¶
func Fatal(message string, args ...interface{})
Fatal logs a fatal message with optional arguments. Deprecated: Use github.com/go-i2p/logger directly for new code. The tags parameter has been removed; use logger.Error() or logger.Errorf() instead. Note: Fatal maps to Error level in the logger and sets WARNFAIL_I2P.
func FormatDateForBlinding ¶
FormatDateForBlinding formats a time.Time as YYYY-MM-DD for blinding factor derivation.
func GenerateRandomPrivateKey ¶
GenerateRandomPrivateKey generates a random 32-byte private key for DH authentication. This can be used to create a new client identity for accessing encrypted LeaseSets.
func GetCurrentBlindingDate ¶
func GetCurrentBlindingDate() string
GetCurrentBlindingDate returns today's date in UTC formatted for blinding (YYYY-MM-DD).
func GetMessageStatusCategory ¶
func GetMessageStatusCategory(status SessionMessageStatus) string
GetMessageStatusCategory returns a human-readable category for the message status. Categories: "success", "failure", "retriable", "pending", or "unknown"
func HandleHostReplyAuthError ¶
HandleHostReplyAuthError processes HostReply error codes related to authentication. Returns a descriptive error message and suggested action based on the error code.
Error codes 2-5 indicate authentication requirements for encrypted LeaseSets:
- Code 2: Lookup password required
- Code 3: Private key required (per-client auth)
- Code 4: Both password and private key required
- Code 5: Decryption failure (credentials may be incorrect)
func Info ¶
func Info(message string, args ...interface{})
Info logs an info message with optional arguments. Deprecated: Use github.com/go-i2p/logger directly for new code. The tags parameter has been removed; use logger.Warn() or logger.Warnf() instead. Note: Info maps to Warn level in the logger.
func IsBufferPoolEnabled ¶
func IsBufferPoolEnabled() bool
IsBufferPoolEnabled returns whether buffer pooling is currently enabled.
func IsFatal ¶
IsFatal returns true if the error is fatal and the connection should be closed. Fatal errors indicate serious protocol violations or unrecoverable states.
func IsMessageStatusFailure ¶
func IsMessageStatusFailure(status SessionMessageStatus) bool
IsMessageStatusFailure returns true if the message status indicates a delivery failure. This includes all failure codes except transient/retriable failures.
func IsMessageStatusRetriable ¶
func IsMessageStatusRetriable(status SessionMessageStatus) bool
IsMessageStatusRetriable returns true if the message status indicates a transient failure that may succeed if retried later. This includes queue overflow, network failures, and temporary tunnel unavailability.
func IsMessageStatusSuccess ¶
func IsMessageStatusSuccess(status SessionMessageStatus) bool
IsMessageStatusSuccess returns true if the message status indicates successful delivery. Success statuses include accepted, best-effort success, guaranteed success, and local success.
func IsTemporary ¶
IsTemporary returns true if the error is temporary and the operation can be retried. This checks for specific error types that indicate transient failures.
func LogInit ¶
func LogInit(level int)
LogInit initializes the logger with the specified level Deprecated: Use github.com/go-i2p/logger directly for new code
func NewMessageError ¶
NewMessageError creates a MessageError with the given parameters. Use this to wrap errors that occur during message processing.
Example:
if err := parseMessage(stream); err != nil {
return NewMessageError(I2CP_MSG_CREATE_SESSION, "parsing", err)
}
func NewProtocolError ¶
NewProtocolError creates a ProtocolError for serious protocol violations.
Example:
if msgType > 42 {
return NewProtocolError("unknown message type", int(msgType), false)
}
func NewSessionError ¶
NewSessionError creates a SessionError with the given parameters. Use this to wrap errors that occur during session operations.
Example:
if err := session.sendMessage(); err != nil {
return NewSessionError(session.id, "send message", err)
}
func ParseConfig ¶
ParseConfig parses a configuration file and calls the callback for each key-value pair
func ParseSendMessageFlags ¶
ParseSendMessageFlags extracts flag components from a SendMessageExpires flags field per I2CP specification § SendMessageExpiresMessage (I2CP 0.8.4+)
Returns:
- noLeaseSet: true if LeaseSet bundling is disabled (bit 8)
- tagThreshold: ElGamal tag threshold value (bits 7-4) - OBSOLETE
- tagCount: ElGamal tags to send value (bits 3-0) - OBSOLETE
- err: error if reserved or deprecated bits are set
func ReleaseStream ¶
func ReleaseStream(s *Stream)
ReleaseStream returns a Stream's buffer to the pool for reuse. After calling this, the Stream should not be used. If buffer pooling is disabled, this is a no-op.
func RetryWithBackoff ¶
func UnblindPublicKey ¶
UnblindPublicKey reverses the blinding operation on a public key. The operation: P = P' - [alpha]B
This is used for verification: given a blinded key P' and alpha, recover P.
Parameters:
- blindedPublicKey: 32-byte blinded Ed25519 public key
- alpha: 32-byte blinding factor used to create the blinded key
Returns:
- Original unblinded 32-byte public key
- Error if inputs are invalid
func ValidateSendMessageFlags ¶
ValidateSendMessageFlags validates SendMessageExpires flags per I2CP specification per I2CP specification § SendMessageExpiresMessage (I2CP 0.8.4+)
This function checks that:
- Reserved bits (15-11) are not set
- Deprecated reliability override bits (10-9) are not set
- Tag threshold and count are in valid range (0-15)
Returns an error if validation fails.
func ValidateX25519PublicKey ¶
ValidatePublicKey checks if a public key is valid for X25519
func VerifyBlindedDestination ¶
VerifyBlindedDestination verifies that a blinded public key matches the expected unblinded public key when the same alpha is applied.
This is useful for verifying that a router-provided blinded destination corresponds to a known destination.
Parameters:
- blindedPubKey: The blinded public key to verify
- expectedPubKey: The expected unblinded public key
- alpha: The blinding factor that was used
Returns:
- true if the blinded key corresponds to the expected key
- false otherwise
func VerifyDHSharedSecret ¶
VerifyDHSharedSecret verifies that a DH shared secret can be derived from the given keys. This is useful for testing and debugging authentication issues.
func VerifyPSKDerivation ¶
VerifyPSKDerivation verifies that a PSK can be used to derive a decryption key.
func Warning ¶
func Warning(message string, args ...interface{})
Warning logs a warning message with optional arguments. Deprecated: Use github.com/go-i2p/logger directly for new code. The tags parameter has been removed; use logger.Warn() or logger.Warnf() instead.
func WriteCertificateToMessage ¶ added in v0.1.52
func WriteCertificateToMessage(cert *Certificate, stream *Stream) error
WriteCertificateToMessage writes a Certificate to an I2CP message stream.
func WriteCertificateToStream ¶ added in v0.1.52
func WriteCertificateToStream(cert *Certificate, stream *Stream) error
WriteCertificateToStream is an alias for WriteCertificateToMessage.
func WriteLeaseToLeaseSet2 ¶ added in v0.1.52
WriteLeaseToLeaseSet2 writes a Lease in Lease2 format (40 bytes) for LeaseSet2. Lease2 format: gateway (32 bytes) + tunnel_id (4 bytes) + end_date (4 bytes, seconds) This differs from the I2CP Lease format which uses 8-byte millisecond timestamps.
func WriteLeaseToMessage ¶ added in v0.1.52
WriteLeaseToMessage writes a Lease to an I2CP Stream (44-byte format).
func X25519PublicKeyFromStream ¶
X25519PublicKeyFromStream reads only the public key from a stream
Types ¶
type AuthResult ¶
type AuthResult struct {
// DecryptionKey is the 32-byte key for BlindingInfoMessage
DecryptionKey [32]byte
// Empty for PSK authentication
SharedSecret [32]byte
// Scheme indicates which auth scheme was used (DH=0, PSK=1)
Scheme uint8
}
AuthResult holds the result of DH or PSK authentication.
type BandwidthLimits ¶
type BandwidthLimits struct {
// ClientInbound is the maximum inbound bandwidth for the client in kilobytes per second (KBps).
// This limit applies to data received by the client application.
ClientInbound uint32
// ClientOutbound is the maximum outbound bandwidth for the client in kilobytes per second (KBps).
// This limit applies to data sent by the client application.
ClientOutbound uint32
// RouterInbound is the router's maximum inbound bandwidth in kilobytes per second (KBps).
// This is the router's overall limit, shared across all clients.
RouterInbound uint32
// RouterInboundBurst is the maximum burst bandwidth for inbound router traffic in kilobytes per second (KBps).
// This allows temporary exceeding of the RouterInbound baseline rate during the BurstTime window.
// Per I2CP spec § BandwidthLimitsMessage: This is a RATE (KBps), not a size (bytes).
RouterInboundBurst uint32
// RouterOutbound is the router's maximum outbound bandwidth in kilobytes per second (KBps).
// This is the router's overall limit, shared across all clients.
RouterOutbound uint32
// RouterOutboundBurst is the maximum burst bandwidth for outbound router traffic in kilobytes per second (KBps).
// This allows temporary exceeding of the RouterOutbound baseline rate during the BurstTime window.
// Per I2CP spec § BandwidthLimitsMessage: This is a RATE (KBps), not a size (bytes).
RouterOutboundBurst uint32
// BurstTime is the time window in seconds over which burst limits are calculated.
// For example, if BurstTime=10 and RouterInboundBurst=100, the router can
// burst up to 100 KBps over any 10-second window before throttling.
BurstTime uint32
// Undefined contains 9 reserved 32-bit fields for future protocol extensions.
//
// Per I2CP BandwidthLimitsMessage specification, these fields are currently
// undefined and reserved for future protocol versions. They must be:
// - Parsed by clients for forward compatibility
// - Set to 0 by routers in current protocol versions
// - Ignored by clients until a future I2CP version defines their meaning
//
// Possible future uses (speculative, not in current spec):
// - Per-destination bandwidth limits
// - Quality of service parameters
// - Tunnel-specific bandwidth allocation
// - Congestion control hints
//
// Applications should NOT rely on these fields until officially specified.
Undefined [9]uint32
}
BandwidthLimits represents bandwidth limitation parameters received from the I2P router. This structure contains both client-side and router-side bandwidth limits, plus burst parameters that control how bandwidth constraints are enforced.
I2CP Specification: BandwidthLimitsMessage (type 23) Introduced in I2CP 0.9.3+ to communicate bandwidth constraints from router to client.
Fields represent bytes/second unless otherwise noted. Burst parameters allow temporary exceeding of base limits for bursty traffic patterns.
func (*BandwidthLimits) InboundBytesPerSecond ¶
func (b *BandwidthLimits) InboundBytesPerSecond() int
InboundBytesPerSecond returns the client inbound limit in bytes per second. Converts from KBps (as transmitted in I2CP protocol) to bytes/sec.
func (*BandwidthLimits) OutboundBytesPerSecond ¶
func (b *BandwidthLimits) OutboundBytesPerSecond() int
OutboundBytesPerSecond returns the client outbound limit in bytes per second. Converts from KBps (as transmitted in I2CP protocol) to bytes/sec.
func (*BandwidthLimits) RouterInboundBurstBytesPerSecond ¶
func (b *BandwidthLimits) RouterInboundBurstBytesPerSecond() int
RouterInboundBurstBytesPerSecond returns the router inbound burst limit in bytes per second. Converts from KBps (as transmitted in I2CP protocol) to bytes/sec.
func (*BandwidthLimits) RouterInboundBytesPerSecond ¶
func (b *BandwidthLimits) RouterInboundBytesPerSecond() int
RouterInboundBytesPerSecond returns the router inbound limit in bytes per second. Converts from KBps (as transmitted in I2CP protocol) to bytes/sec.
func (*BandwidthLimits) RouterOutboundBurstBytesPerSecond ¶
func (b *BandwidthLimits) RouterOutboundBurstBytesPerSecond() int
RouterOutboundBurstBytesPerSecond returns the router outbound burst limit in bytes per second. Converts from KBps (as transmitted in I2CP protocol) to bytes/sec.
func (*BandwidthLimits) RouterOutboundBytesPerSecond ¶
func (b *BandwidthLimits) RouterOutboundBytesPerSecond() int
RouterOutboundBytesPerSecond returns the router outbound limit in bytes per second. Converts from KBps (as transmitted in I2CP protocol) to bytes/sec.
func (*BandwidthLimits) String ¶
func (b *BandwidthLimits) String() string
String returns a human-readable representation of the bandwidth limits. Format: BandwidthLimits{Client: inbound/outbound KBps, Router: inbound(burst)/outbound(burst) KBps, Burst: Ns}
type BlindingInfo ¶
type BlindingInfo struct {
// EndpointType specifies how the destination is identified (0-3)
// Use BLINDING_ENDPOINT_* constants
EndpointType uint8
// Endpoint is the destination identifier, format depends on EndpointType:
// Type 0: 32-byte hash
// Type 1: hostname string (will be length-prefixed)
// Type 2: full Destination bytes
// Type 3: 2-byte sig type + SigningPublicKey bytes
Endpoint []byte
// BlindedSigType is the signature type used for blinding (2 bytes)
BlindedSigType uint16
// Expiration is the expiration time in seconds since epoch
Expiration uint32
// PerClientAuth indicates if per-client authentication is required
// When true, DecryptionKey must be provided
PerClientAuth bool
// AuthScheme specifies the authentication scheme when PerClientAuth is true
// Use BLINDING_AUTH_SCHEME_DH (0) or BLINDING_AUTH_SCHEME_PSK (1)
AuthScheme uint8
// DecryptionKey is the 32-byte ECIES_X25519 private key (little-endian)
// Only required when PerClientAuth is true
DecryptionKey []byte
// LookupPassword is the optional password for encrypted LeaseSet lookup
// Only include if the destination requires a secret
LookupPassword string
}
BlindingInfo represents the parameters for a BlindingInfoMessage. This structure encapsulates all the fields needed to advise the router about a blinded destination per I2CP specification 0.9.43+.
func CreateDHBlindingInfo ¶
func CreateDHBlindingInfo( destHash []byte, clientPrivateKey, serverPublicKey [32]byte, blindedSigType uint16, expiration uint32, ) (*BlindingInfo, error)
Returns BlindingInfo ready to send via Session.SendBlindingInfo().
func CreateDHBlindingInfoForHostname ¶
func CreateDHBlindingInfoForHostname( hostname string, clientPrivateKey, serverPublicKey [32]byte, blindedSigType uint16, expiration uint32, ) (*BlindingInfo, error)
CreateDHBlindingInfoForHostname creates BlindingInfo with DH auth for a hostname endpoint.
func CreatePSKBlindingInfo ¶
func CreatePSKBlindingInfo( destHash []byte, preSharedKey [32]byte, blindedSigType uint16, expiration uint32, ) (*BlindingInfo, error)
CreatePSKBlindingInfo creates a complete BlindingInfo with PSK authentication for a hash-based endpoint.
Parameters:
- destHash: 32-byte hash of the blinded destination
- preSharedKey: The 32-byte pre-shared key
- blindedSigType: Signature type used for blinding
- expiration: Expiration time (seconds since epoch)
Returns BlindingInfo ready to send via Session.SendBlindingInfo().
func CreatePSKBlindingInfoForHostname ¶
func CreatePSKBlindingInfoForHostname( hostname string, preSharedKey [32]byte, blindedSigType uint16, expiration uint32, ) (*BlindingInfo, error)
CreatePSKBlindingInfoForHostname creates BlindingInfo with PSK auth for a hostname endpoint.
func NewBlindingInfoWithDestination ¶
func NewBlindingInfoWithDestination(destBytes []byte, blindedSigType uint16, expiration uint32) (*BlindingInfo, error)
NewBlindingInfoWithDestination creates BlindingInfo for a full destination. The destination bytes must be at least 387 bytes.
func NewBlindingInfoWithHash ¶
func NewBlindingInfoWithHash(hash []byte, blindedSigType uint16, expiration uint32) (*BlindingInfo, error)
NewBlindingInfoWithHash creates BlindingInfo for a destination identified by its hash. The hash must be 32 bytes (SHA-256 of the destination).
func NewBlindingInfoWithHostname ¶
func NewBlindingInfoWithHostname(hostname string, blindedSigType uint16, expiration uint32) (*BlindingInfo, error)
NewBlindingInfoWithHostname creates BlindingInfo for a destination identified by hostname. The hostname must be non-empty and at most 255 bytes.
func NewBlindingInfoWithSigningKey ¶
func NewBlindingInfoWithSigningKey(sigType uint16, signingPublicKey []byte, blindedSigType uint16, expiration uint32) (*BlindingInfo, error)
NewBlindingInfoWithSigningKey creates BlindingInfo for a signing key. The sigKey bytes must include 2-byte sig type + SigningPublicKey.
func (*BlindingInfo) ClearPerClientAuth ¶
func (info *BlindingInfo) ClearPerClientAuth()
ClearPerClientAuth removes per-client authentication from BlindingInfo.
func (*BlindingInfo) GetAuthSchemeName ¶
func (info *BlindingInfo) GetAuthSchemeName() string
GetAuthSchemeName returns a human-readable name for the auth scheme.
func (*BlindingInfo) IsPerClientAuthEnabled ¶
func (info *BlindingInfo) IsPerClientAuthEnabled() bool
IsPerClientAuthEnabled returns true if per-client authentication is configured.
func (*BlindingInfo) SetLookupPassword ¶
func (info *BlindingInfo) SetLookupPassword(password string)
SetLookupPassword sets the lookup password for accessing encrypted LeaseSets. This can be used independently of per-client auth.
func (*BlindingInfo) SetPerClientAuth ¶
func (info *BlindingInfo) SetPerClientAuth(config *PerClientAuthConfig) error
SetPerClientAuth configures per-client authentication on BlindingInfo. This enables DH or PSK authentication for accessing the encrypted LeaseSet.
func (*BlindingInfo) String ¶
func (info *BlindingInfo) String() string
String returns a human-readable representation of the BlindingInfo.
type BlindingKeyDerivation ¶
type BlindingKeyDerivation struct {
// Alpha is the 32-byte blinding factor derived from secret + date
Alpha [32]byte
// BlindedPublicKey is the destination's public key after blinding
BlindedPublicKey [32]byte
// BlindedPrivateKey is the private key after blinding (if available)
// This is only populated when calling DeriveBlindingKeysWithPrivate
BlindedPrivateKey [64]byte
// Date is the date used for derivation (for verification/debugging)
Date string
// HasPrivateKey indicates whether BlindedPrivateKey is populated
HasPrivateKey bool
}
BlindingKeyDerivation holds derived blinding keys for accessing encrypted LeaseSets. This structure contains all the cryptographic material needed to access a blinded destination.
func DeriveBlindingKeys ¶
func DeriveBlindingKeys(secret []byte, publicKey [32]byte, date string) (*BlindingKeyDerivation, error)
DeriveBlindingKeys derives blinding factor and blinds a public key. This is a convenience function that combines DeriveBlindingFactor and BlindPublicKey.
Parameters:
- secret: Secret key material (at least 32 bytes)
- publicKey: 32-byte Ed25519 public key to blind
- date: Date in "YYYY-MM-DD" format (or empty for today)
Returns:
- BlindingKeyDerivation containing alpha and blinded public key
- Error if derivation fails
func DeriveBlindingKeysWithPrivate ¶
func DeriveBlindingKeysWithPrivate(secret []byte, publicKey [32]byte, privateKey [64]byte, date string) (*BlindingKeyDerivation, error)
DeriveBlindingKeysWithPrivate derives blinding keys including the blinded private key. This is used by services that need to sign with blinded keys.
Parameters:
- secret: Secret key material (at least 32 bytes)
- publicKey: 32-byte Ed25519 public key
- privateKey: 64-byte Ed25519 private key
- date: Date in "YYYY-MM-DD" format (or empty for today)
Returns:
- BlindingKeyDerivation containing alpha, blinded public and private keys
- Error if derivation fails
type BufferPoolStats ¶
type BufferPoolStats struct {
Gets512 uint64
Gets1K uint64
Gets4K uint64
Gets16K uint64
GetsOversized uint64
Puts512 uint64
Puts1K uint64
Puts4K uint64
Puts16K uint64
}
BufferPoolStats returns statistics about buffer pool usage. Returns nil if buffer pooling is disabled.
func GetBufferPoolStats ¶
func GetBufferPoolStats() *BufferPoolStats
GetBufferPoolStats returns current buffer pool statistics. Returns nil if buffer pooling is disabled.
type Certificate ¶
type Certificate = certificate.Certificate
Certificate is a type alias for certificate.Certificate from the common package. All certificate operations (Type, Length, Data, Bytes, IsValid) are provided by the common package. I2CP-specific stream helpers are defined as package functions.
func CopyCertificate ¶ added in v0.1.52
func CopyCertificate(cert *Certificate) *Certificate
CopyCertificate creates a deep copy of a Certificate by re-parsing its bytes.
func NewCertificate ¶
func NewCertificate(typ uint8) *Certificate
NewCertificate creates a new Certificate with the specified type using the common package.
func NewCertificateFromMessage ¶
func NewCertificateFromMessage(stream *Stream) (*Certificate, error)
NewCertificateFromMessage reads a Certificate from an I2CP message stream. Uses common/certificate.ReadCertificate for parsing.
func NewCertificateFromStream ¶
func NewCertificateFromStream(stream *Stream) (*Certificate, error)
NewCertificateFromStream is an alias for NewCertificateFromMessage.
type ChaCha20Poly1305Cipher ¶
type ChaCha20Poly1305Cipher struct {
// contains filtered or unexported fields
}
ChaCha20Poly1305Cipher provides authenticated encryption using ChaCha20-Poly1305 Wraps github.com/go-i2p/crypto/chacha20poly1305.AEAD
func ChaCha20Poly1305CipherFromStream ¶
func ChaCha20Poly1305CipherFromStream(stream *Stream) (*ChaCha20Poly1305Cipher, error)
ChaCha20Poly1305CipherFromStream reads a ChaCha20-Poly1305 cipher from a stream
func NewChaCha20Poly1305Cipher ¶
func NewChaCha20Poly1305Cipher() (*ChaCha20Poly1305Cipher, error)
NewChaCha20Poly1305Cipher creates a new ChaCha20-Poly1305 cipher with a random key Delegates to github.com/go-i2p/crypto/chacha20poly1305.GenerateKey() and NewAEAD()
func NewChaCha20Poly1305CipherWithKey ¶
func NewChaCha20Poly1305CipherWithKey(key [32]byte) (*ChaCha20Poly1305Cipher, error)
NewChaCha20Poly1305CipherWithKey creates a new ChaCha20-Poly1305 cipher with the provided key Delegates to github.com/go-i2p/crypto/chacha20poly1305.NewAEAD()
func (*ChaCha20Poly1305Cipher) AlgorithmType ¶
func (c *ChaCha20Poly1305Cipher) AlgorithmType() uint32
AlgorithmType returns the algorithm type constant
func (*ChaCha20Poly1305Cipher) Decrypt ¶
func (c *ChaCha20Poly1305Cipher) Decrypt(ciphertext, additionalData []byte) ([]byte, error)
Decrypt decrypts ciphertext with optional associated data using ChaCha20-Poly1305 Expects [nonce][ciphertext+tag] format for I2CP compatibility Uses github.com/go-i2p/crypto/chacha20poly1305.AEAD.Decrypt()
func (*ChaCha20Poly1305Cipher) DecryptStream ¶
func (c *ChaCha20Poly1305Cipher) DecryptStream(src, dst *Stream, additionalData []byte) error
DecryptStream decrypts data from source stream and writes to destination stream
func (*ChaCha20Poly1305Cipher) Encrypt ¶
func (c *ChaCha20Poly1305Cipher) Encrypt(plaintext, additionalData []byte) ([]byte, error)
Encrypt encrypts plaintext with optional associated data using ChaCha20-Poly1305 Returns [nonce][ciphertext+tag] format for I2CP compatibility Uses github.com/go-i2p/crypto/chacha20poly1305.AEAD.Encrypt()
func (*ChaCha20Poly1305Cipher) EncryptStream ¶
func (c *ChaCha20Poly1305Cipher) EncryptStream(src, dst *Stream, additionalData []byte) error
EncryptStream encrypts data from source stream and writes to destination stream
func (*ChaCha20Poly1305Cipher) Key ¶
func (c *ChaCha20Poly1305Cipher) Key() [32]byte
Key returns a copy of the encryption key
func (*ChaCha20Poly1305Cipher) NonceSize ¶
func (c *ChaCha20Poly1305Cipher) NonceSize() int
NonceSize returns the nonce size used by the cipher
func (*ChaCha20Poly1305Cipher) Overhead ¶
func (c *ChaCha20Poly1305Cipher) Overhead() int
Overhead returns the authentication tag overhead
func (*ChaCha20Poly1305Cipher) WriteToStream ¶
func (c *ChaCha20Poly1305Cipher) WriteToStream(stream *Stream) error
WriteToStream writes the cipher key to a stream
type CircuitBreaker ¶
type CircuitBreaker struct {
// contains filtered or unexported fields
}
CircuitBreaker implements the circuit breaker pattern to prevent cascading failures. It monitors operation failures and automatically opens the circuit after a threshold, preventing additional attempts that are likely to fail. After a timeout period, it transitions to half-open state to test if the service has recovered.
States:
- Closed: Normal operation, failures are counted
- Open: Circuit is tripped, all operations fail fast without attempting
- Half-Open: Testing recovery, limited operations allowed
This is particularly useful for I2CP router connections to prevent hammering a router that is down or overloaded.
func NewCircuitBreaker ¶
func NewCircuitBreaker(maxFailures int, resetTimeout time.Duration) *CircuitBreaker
NewCircuitBreaker creates a new circuit breaker with the specified parameters.
Parameters:
- maxFailures: Number of consecutive failures before opening the circuit
- resetTimeout: Duration to wait in open state before attempting half-open
Example:
// Open circuit after 3 failures, try recovery after 30 seconds cb := NewCircuitBreaker(3, 30*time.Second)
func (*CircuitBreaker) Execute ¶
func (cb *CircuitBreaker) Execute(fn func() error) error
Execute runs the given function if the circuit breaker allows it. Returns an error if the circuit is open or if the function fails.
The circuit breaker tracks the success/failure of the operation and automatically manages state transitions.
Example:
err := circuitBreaker.Execute(func() error {
return client.Connect(ctx)
})
if err != nil {
if circuitBreaker.IsOpen() {
// Circuit is open, don't retry immediately
}
}
func (*CircuitBreaker) Failures ¶
func (cb *CircuitBreaker) Failures() int
Failures returns the current failure count.
func (*CircuitBreaker) IsClosed ¶
func (cb *CircuitBreaker) IsClosed() bool
IsClosed returns true if the circuit is currently closed.
func (*CircuitBreaker) IsHalfOpen ¶
func (cb *CircuitBreaker) IsHalfOpen() bool
IsHalfOpen returns true if the circuit is currently half-open.
func (*CircuitBreaker) IsOpen ¶
func (cb *CircuitBreaker) IsOpen() bool
IsOpen returns true if the circuit is currently open.
func (*CircuitBreaker) RecordFailure ¶ added in v0.1.52
func (cb *CircuitBreaker) RecordFailure()
RecordFailure records an external failure in the circuit breaker. This is used for operations not wrapped with Execute(), such as receive errors.
func (*CircuitBreaker) Reset ¶
func (cb *CircuitBreaker) Reset()
Reset manually resets the circuit breaker to closed state with zero failures. This is useful for testing or manual intervention.
func (*CircuitBreaker) State ¶
func (cb *CircuitBreaker) State() CircuitState
State returns the current state of the circuit breaker.
func (*CircuitBreaker) String ¶
func (cb *CircuitBreaker) String() string
String returns a human-readable representation of the circuit breaker state.
type CircuitState ¶
type CircuitState string
CircuitState represents the current state of a circuit breaker.
const ( // CircuitClosed means the circuit is allowing requests through normally. CircuitClosed CircuitState = "closed" // CircuitOpen means the circuit is blocking requests due to too many failures. CircuitOpen CircuitState = "open" // CircuitHalfOpen means the circuit is testing if the service has recovered. CircuitHalfOpen CircuitState = "half-open" )
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 ¶
Connect establishes a connection to the I2P router with context support. The context can be used to cancel the connection attempt or set a timeout. Implements proper error path cleanup with defer pattern per PLAN.md section 1.3. Supports TLS connections per I2CP 0.8.3+ specification (authentication method 2).
Example:
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() err := client.Connect(ctx)
func (*Client) CreateSession ¶
CreateSession creates a new I2CP session with the router. This initiates session establishment which completes asynchronously via ProcessIO.
Parameters:
- ctx: Context for cancellation and timeouts
- sess: Session configuration and callbacks
Returns error if validation fails or message cannot be sent. Success is confirmed via OnStatus callback with I2CP_SESSION_STATUS_CREATED.
I2CP Spec: CreateSessionMessage (type 1), I2CP 0.9.21+ for multi-session support
func (*Client) CreateSessionSync ¶
CreateSessionSync creates a session and waits synchronously for confirmation from the router. This is a convenience wrapper around CreateSession that handles the ProcessIO loop internally and blocks until the session is confirmed or the timeout expires.
IMPORTANT: This function will block until:
- The router confirms the session (I2CP_SESSION_STATUS_CREATED), OR
- The context expires/is cancelled, OR
- The router rejects the session (I2CP_SESSION_STATUS_INVALID)
This function is suitable for simple applications and testing. For production use with multiple sessions or complex I/O patterns, use the async CreateSession with manual ProcessIO.
Parameters:
- ctx: Context for timeout/cancellation (recommended: 30 second timeout)
- sess: Session to create (must have callbacks configured if needed)
Returns:
- nil if session created successfully
- error if creation failed, timed out, or context cancelled
Example:
session := NewSession(client, SessionCallbacks{
OnMessage: func(s *Session, srcDest *Destination, protocol uint8, srcPort, destPort uint16, payload *Stream) {
fmt.Println("Received message!")
},
})
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := client.CreateSessionSync(ctx, session); err != nil {
log.Fatalf("Session creation failed: %v", err)
}
fmt.Println("Session created successfully!")
func (*Client) DestinationLookup ¶
func (*Client) DisableAllDebugging ¶
func (c *Client) DisableAllDebugging()
DisableAllDebugging disables all debugging features.
func (*Client) DisableAutoReconnect ¶
func (c *Client) DisableAutoReconnect()
DisableAutoReconnect disables automatic reconnection.
func (*Client) DisableBatching ¶
DisableBatching disables message batching and stops the flush timer. Any pending messages in the queue will be flushed before disabling.
func (*Client) DisableMessageStats ¶
func (c *Client) DisableMessageStats()
DisableMessageStats disables message statistics tracking.
func (*Client) Disconnect ¶
func (c *Client) Disconnect()
Disconnect is deprecated. Use Close() instead. Kept for backward compatibility.
func (*Client) EnableAllDebugging ¶
EnableAllDebugging enables all debugging features on a client with default config.
func (*Client) EnableAutoReconnect ¶
func (*Client) EnableBatching ¶
EnableBatching enables message batching with the specified flush timer and size threshold. flushTimer: duration to wait before flushing batch (e.g., 10ms) sizeThreshold: size in bytes to trigger immediate flush (e.g., 16KB) This starts a background goroutine that periodically flushes the output queue.
func (*Client) EnableDebugging ¶
func (c *Client) EnableDebugging(config *DebugConfig) error
EnableDebugging enables debugging features based on the provided config.
func (*Client) EnableMessageStats ¶
func (c *Client) EnableMessageStats()
EnableMessageStats enables message statistics tracking for diagnostic purposes. This should be enabled when troubleshooting I2CP protocol issues.
func (*Client) GetCircuitBreakerState ¶
func (c *Client) GetCircuitBreakerState() CircuitState
GetCircuitBreakerState returns the current state of the circuit breaker. Returns CircuitClosed if circuit breaker is disabled (nil).
This allows applications to monitor circuit breaker state and implement custom behavior based on router connectivity health.
Example:
if client.GetCircuitBreakerState() == CircuitOpen {
// Router is unreachable, wait before retrying
time.Sleep(30 * time.Second)
}
func (*Client) GetConnectionState ¶
func (c *Client) GetConnectionState() *ConnectionState
GetConnectionState returns the current connection state for diagnostic purposes.
func (*Client) GetMessageStats ¶
func (c *Client) GetMessageStats() *MessageStats
GetMessageStats returns the current message statistics for diagnostic purposes. Returns nil if message statistics tracking is not enabled.
func (*Client) GetMetrics ¶
func (c *Client) GetMetrics() MetricsCollector
GetMetrics returns the current metrics collector, or nil if disabled.
func (*Client) GetProtocolDebugger ¶
func (c *Client) GetProtocolDebugger() *ProtocolDebugger
GetProtocolDebugger returns the protocol debugger.
func (*Client) GetStateTracker ¶
func (c *Client) GetStateTracker() *SessionStateTracker
GetStateTracker returns the session state tracker.
func (*Client) IsAutoReconnectEnabled ¶
IsAutoReconnectEnabled returns whether auto-reconnect is currently enabled.
func (*Client) IsBatchingEnabled ¶
IsBatchingEnabled returns whether message batching is currently enabled.
func (*Client) IsConnected ¶
func (*Client) PrintDiagnostics ¶
func (c *Client) PrintDiagnostics()
PrintDiagnostics prints a comprehensive diagnostic report to help troubleshoot I2CP issues. This is particularly useful when debugging session creation timeouts.
func (*Client) PrintFullDiagnostics ¶
func (c *Client) PrintFullDiagnostics()
PrintFullDiagnostics prints comprehensive diagnostics including all debug info.
func (*Client) ProcessIO ¶
ProcessIO processes pending I/O operations with context support. This method processes the output queue and receives messages from the router. It respects context cancellation and shutdown signals.
Example:
ctx, cancel := context.WithCancel(context.Background()) defer cancel() err := client.ProcessIO(ctx)
func (*Client) ReconnectAttempts ¶
ReconnectAttempts returns the current number of reconnection attempts.
func (*Client) ResetCircuitBreaker ¶
ResetCircuitBreaker manually resets the circuit breaker to closed state. This is useful for manual recovery after fixing router connectivity issues.
Returns ErrClientNotInitialized if the client was not properly initialized.
Example:
// After fixing router configuration
if err := client.ResetCircuitBreaker(); err != nil {
log.Printf("Failed to reset circuit breaker: %v", err)
}
func (*Client) RouterCapabilities ¶
RouterCapabilities returns the router's capability flags as a bitmask. Returns 0 if the client is not initialized or not connected.
Known capability flags:
- ROUTER_CAN_HOST_LOOKUP (1): Router supports hostname resolution (I2CP 0.9.10+)
This method is safe to call before connecting to the router, but will return meaningful data only after a successful connection.
I2CP Spec: Capabilities are determined from router version during connection.
Example:
caps := client.RouterCapabilities()
if (caps & ROUTER_CAN_HOST_LOOKUP) != 0 {
fmt.Println("Router supports hostname lookups")
}
func (*Client) RouterDate ¶
RouterDate returns the router's timestamp in I2P time format (milliseconds since epoch). Returns 0 if the client is not initialized or not connected.
This timestamp is used for time synchronization and lease expiration calculations. The router date is typically close to the current system time but may differ if the router's clock is skewed.
I2CP Spec: Router date is exchanged during GetDateMessage (type 32) response.
Example:
date := client.RouterDate()
routerTime := time.Unix(int64(date/1000), int64((date%1000)*1000000))
fmt.Printf("Router time: %v\n", routerTime)
func (*Client) RouterVersion ¶
RouterVersion returns the I2P router's version information. Returns a zero-value Version struct if the client is not initialized or not connected.
This method is safe to call before connecting to the router, but will return meaningful data only after a successful connection (after Connect() completes).
I2CP Spec: Router version is exchanged during GetDateMessage (type 32) response.
Example:
version := client.RouterVersion()
fmt.Printf("Router version: %d.%d.%d\n", version.major, version.minor, version.micro)
func (*Client) SetMetrics ¶
func (c *Client) SetMetrics(metrics MetricsCollector)
SetMetrics enables metrics collection with the provided collector. Pass nil to disable metrics collection. This method is safe to call on a running client.
func (*Client) SetProperty ¶
EnableAutoReconnect enables automatic reconnection with exponential backoff. When enabled, the client will automatically attempt to reconnect if the connection is lost unexpectedly (not via explicit Close()).
Parameters:
- maxRetries: Maximum reconnection attempts (0 = infinite retries)
- initialBackoff: Starting delay between reconnect attempts (doubles each time)
The backoff strategy uses exponential backoff capped at 5 minutes. Set maxRetries to 0 for infinite retry attempts.
Example:
// Retry indefinitely with 1 second initial backoff client.EnableAutoReconnect(0, time.Second) // Retry up to 5 times with 2 second initial backoff client.EnableAutoReconnect(5, 2*time.Second)
func (*Client) SupportsHostLookup ¶
SupportsHostLookup returns whether the router supports hostname resolution. Returns false if the client is not initialized or not connected.
Hostname lookup capability was added in I2CP protocol version 0.9.10. Applications should check this capability before calling DestinationLookup with hostname strings (non-base64 destinations).
I2CP Spec: HostLookupMessage (type 38) requires router version >= 0.9.10.
Example:
if !client.SupportsHostLookup() {
return fmt.Errorf("router does not support hostname lookups")
}
client.DestinationLookup(ctx, session, "example.i2p")
func (*Client) SupportsMultiSession ¶
SupportsMultiSession returns whether the router supports multi-session contexts. Returns false if the client is not initialized or not connected.
Multi-session support (primary sessions with subsessions) was added in I2CP protocol version 0.9.21. Subsessions share the tunnel pool of their primary session, enabling efficient resource usage for related services.
Applications should check this capability before creating subsessions. Attempting to create subsessions on routers that don't support this feature will result in ErrMultiSessionUnsupported errors.
I2CP Spec: Multi-session support requires router version >= 0.9.21.
Example:
if !client.SupportsMultiSession() {
return fmt.Errorf("router does not support multi-session contexts")
}
// Safe to create subsessions
func (*Client) SupportsVersion ¶
SupportsVersion returns true if the connected router version is at least minVersion. Returns false if the client is not initialized or not connected.
This method should be used to check feature availability before sending version-specific messages. Per I2CP spec § Version Notes: "Clients and routers should not send messages that are unsupported by the other side"
Common version checks (use predefined Version* constants):
- VersionFastReceive (0.9.4+): Fast receive mode
- VersionHostLookup (0.9.11+): HostLookup/HostReply messages
- VersionMultiSession (0.9.21+): Multi-session support
- VersionCreateLeaseSet2 (0.9.39+): CreateLeaseSet2Message
- VersionBlindingInfo (0.9.43+): BlindingInfoMessage
- VersionProposal167 (0.9.66+): HostReply options mapping
Example:
if client.SupportsVersion(VersionBlindingInfo) {
client.msgBlindingInfo(session, info, true)
} else {
return errors.New("router does not support blinding (requires 0.9.43+)")
}
func (*Client) ValidatePerClientAuthSupport ¶
ValidatePerClientAuthSupport checks if the router supports per-client authentication. Per-client auth requires I2CP 0.9.43+ (BlindingInfoMessage support).
type ClientCallBacks ¶
type ClientCallBacks struct {
// Opaque is user-defined data passed to disconnect callback.
// Can be used to store custom context or state information.
Opaque *interface{}
// OnConnect is called when the client successfully connects to the I2P router.
// This is invoked after the initial GetDate handshake completes.
// Parameter:
// - client: The client that connected
OnConnect func(*Client)
// OnDisconnect is called when the client disconnects from the I2P router.
// This may be triggered by network errors, router shutdown, or explicit disconnection.
// Parameters:
// - client: The client that disconnected
// - reason: Reason for disconnection (e.g., "connection closed", "router shutdown")
// - opaque: User-defined data from Opaque field
OnDisconnect func(*Client, string, *interface{})
// OnLog is called for logging events with structured tags.
// Allows custom log handling and integration with external logging systems.
// Parameters:
// - client: The client generating the log
// - tags: Structured log tags (Debug, Info, Warn, Error)
// - message: Log message string
OnLog func(*Client, LoggerTags, string)
// OnBandwidthLimits is called when the router sends bandwidth limitation parameters.
// I2CP 0.9.3+ - Enables rate limiting and traffic shaping based on router capacity.
// Parameters:
// - client: The client receiving bandwidth limits
// - limits: Bandwidth limit parameters (inbound/outbound, burst, etc.)
//
// Example:
//
// OnBandwidthLimits: func(c *Client, limits *BandwidthLimits) {
// log.Printf("Router limits: inbound=%d, outbound=%d",
// limits.RouterInbound, limits.RouterOutbound)
// // Apply rate limiting using limits.ClientInbound/ClientOutbound
// }
OnBandwidthLimits func(*Client, *BandwidthLimits)
// OnHostLookupWithOptions is called when the router responds to a HostLookup request
// that included options mapping (I2CP 0.9.66+, types 2-4).
// This enables service record retrieval per Proposal 167.
// Parameters:
// - client: The client receiving the response
// - requestID: Lookup request ID for correlation
// - destination: The resolved destination (nil if lookup failed)
// - options: Service record options (e.g., service ports, endpoints, metadata)
//
// Example:
//
// OnHostLookupWithOptions: func(c *Client, reqID uint32, dest *Destination, opts map[string]string) {
// if smtpPort, ok := opts["service.smtp.port"]; ok {
// log.Printf("Destination has SMTP service on port %s", smtpPort)
// }
// }
OnHostLookupWithOptions func(*Client, uint32, *Destination, map[string]string)
}
ClientCallBacks defines callback functions for client-level events. All callbacks are optional and can be set to nil if not needed. Callbacks may be invoked from different goroutines, so implementations should be thread-safe.
Example:
callbacks := &ClientCallBacks{
OnConnect: func(c *Client) {
log.Println("Connected to I2P router")
},
OnDisconnect: func(c *Client, reason string, opaque *interface{}) {
log.Printf("Disconnected: %s", reason)
},
OnBandwidthLimits: func(c *Client, limits *BandwidthLimits) {
log.Printf("Bandwidth limits: %s", limits.String())
},
}
client := NewClient(callbacks)
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 CLIENT_PROP_TLS_CERT_FILE CLIENT_PROP_TLS_KEY_FILE CLIENT_PROP_TLS_CA_FILE CLIENT_PROP_TLS_INSECURE NR_OF_I2CP_CLIENT_PROPERTIES )
type ConnectionState ¶
type ConnectionState struct {
Connected bool
RouterVersion string
RouterDate time.Time
SessionsActive int
PrimarySessions int
SubSessions int
LastError error
LastErrorTime time.Time
ConnectedSince time.Time
}
ConnectionState represents the current state of the I2CP connection.
type CreateSessionDump ¶
type CreateSessionDump struct {
Timestamp time.Time
TotalSize int
DestinationSize int
MappingSize int
TimestampValue uint64
SignatureSize int
HexDump string
FilePath string // Path to dumped file
}
CreateSessionDump captures CreateSession message for analysis.
type Crypto ¶
type Crypto struct {
// contains filtered or unexported fields
}
Crypto provides cryptographic operations for I2CP protocol message handling.
This type is an I2CP protocol adapter that coordinates cryptographic operations for I2CP messages. It maintains state required for protocol operations but delegates all actual cryptographic work to specialized packages.
Fields:
- rng: Random number generator (crypto/rand.Reader) for protocol operations
Usage Example:
crypto := NewCrypto() keyPair, err := crypto.Ed25519SignatureKeygen()
See Also:
- NewCrypto(): Constructor function in crypto.go
- Ed25519SignatureKeygen(): Ed25519 key generation
- X25519KeyExchangeKeygen(): X25519 key exchange
func NewCryptoInstance ¶
func NewCryptoInstance() *Crypto
NewCryptoInstance creates a new crypto instance
func (*Crypto) ChaCha20Poly1305CipherKeygen ¶
func (c *Crypto) ChaCha20Poly1305CipherKeygen() (*ChaCha20Poly1305Cipher, error)
ChaCha20Poly1305CipherKeygen generates a new ChaCha20-Poly1305 cipher
func (*Crypto) Ed25519SignatureKeygen ¶
func (c *Crypto) Ed25519SignatureKeygen() (*Ed25519KeyPair, error)
Ed25519SignatureKeygen generates a new Ed25519 signature key pair
func (*Crypto) Random32 ¶
Random32 generates a cryptographically secure random uint32. Used for I2CP message nonces and request IDs per protocol specification
func (*Crypto) SignatureKeygen ¶
func (c *Crypto) SignatureKeygen(algorithmTyp uint32) (sgk SignatureKeyPair, err error)
Generate a signature keypair
func (*Crypto) WriteEd25519SignatureToStream ¶
func (c *Crypto) WriteEd25519SignatureToStream(kp *Ed25519KeyPair, stream *Stream) error
WriteEd25519SignatureToStream writes an Ed25519 signature keypair to stream
func (*Crypto) X25519KeyExchangeKeygen ¶
func (c *Crypto) X25519KeyExchangeKeygen() (*X25519KeyPair, error)
X25519KeyExchangeKeygen generates a new X25519 key exchange key pair
type DHAuthenticator ¶
type DHAuthenticator struct {
// ClientPrivateKey is the client's X25519 private key (32 bytes)
ClientPrivateKey [32]byte
// ServerPublicKey is the server's X25519 public key (32 bytes)
// This is typically extracted from the blinded b32 address
ServerPublicKey [32]byte
// Salt is optional salt for HKDF derivation (can be nil)
Salt []byte
// Info is contextual info for HKDF (I2P uses "ELS2_L1K" for per-client auth)
Info []byte
}
DHAuthenticator performs DH-based authentication for encrypted LeaseSets. It uses X25519 key exchange to derive a shared secret, then HKDF to derive the decryption key.
func NewDHAuthenticator ¶
func NewDHAuthenticator(clientPrivateKey, serverPublicKey [32]byte) *DHAuthenticator
NewDHAuthenticator creates a new DH authenticator with the given keys. The clientPrivateKey is your X25519 private key. The serverPublicKey is extracted from the blinded destination.
func (*DHAuthenticator) Authenticate ¶
func (d *DHAuthenticator) Authenticate() (*AuthResult, error)
Authenticate performs DH key exchange and derives the decryption key.
The process:
- Validate the server's public key
- Perform X25519 DH: sharedSecret = X25519(clientPriv, serverPub)
- Derive decryptionKey = HKDF-SHA256(sharedSecret, salt, info)
Returns AuthResult containing the decryption key for BlindingInfoMessage.
func (*DHAuthenticator) WithInfo ¶
func (d *DHAuthenticator) WithInfo(info []byte) *DHAuthenticator
WithInfo sets custom info for HKDF derivation.
func (*DHAuthenticator) WithSalt ¶
func (d *DHAuthenticator) WithSalt(salt []byte) *DHAuthenticator
WithSalt sets a custom salt for HKDF derivation.
type DebugConfig ¶
type DebugConfig struct {
EnableMessageStats bool // Enable message statistics tracking
EnableStateTracking bool // Enable session state tracking
EnableProtocolDebug bool // Enable protocol debugging
DumpDirectory string // Directory for debug dumps
LogMessageHex bool // Log message hex dumps to console
LogCreateSessionDetail bool // Extra logging for CreateSession
}
DebugConfig holds debugging configuration options.
func DefaultDebugConfig ¶
func DefaultDebugConfig() *DebugConfig
DefaultDebugConfig returns sensible debug defaults.
type Destination ¶
type Destination struct {
// contains filtered or unexported fields
}
func NewDestination ¶
func NewDestination(crypto *Crypto) (dest *Destination, err error)
func NewDestinationFromBase64 ¶
func NewDestinationFromBase64(base64Str string, crypto *Crypto) (dest *Destination, err error)
func NewDestinationFromFile ¶
func NewDestinationFromFile(file *os.File, crypto *Crypto) (*Destination, error)
func NewDestinationFromMessage ¶
func NewDestinationFromMessage(stream *Stream, crypto *Crypto) (dest *Destination, err error)
NewDestinationFromMessage reads a destination from an I2CP message stream. NOTE: This function supports Ed25519 destinations with KEY certificates only. Legacy DSA destinations are no longer supported.
func NewDestinationFromStream ¶
func NewDestinationFromStream(stream *Stream, crypto *Crypto) (dest *Destination, err error)
NewDestinationFromStream reads a destination from a configuration stream. This format includes the full keypair, not just public keys. NOTE: Only Ed25519 destinations with KEY certificates are supported.
func (*Destination) Base32 ¶
func (dest *Destination) Base32() string
Base32 returns the Base32 address of the destination (e.g., "abc123....xyz.b32.i2p")
func (*Destination) Base64 ¶
func (dest *Destination) Base64() string
Base64 returns the Base64 address of the destination
func (*Destination) Copy ¶
func (dest *Destination) Copy() (newDest Destination)
func (*Destination) Hash ¶ added in v0.1.1
func (dest *Destination) Hash() [32]byte
Hash returns the SHA-256 hash of the destination's canonical wire format serialization. This matches Java I2P's Destination.calculateHash() method.
The hash is computed over the wire format (WriteToMessage):
- pubKey: 256 bytes (encryption public key)
- signingPubKey: 128 bytes (Ed25519 key right-aligned at bytes 96-127)
- certificate: 7+ bytes (KEY certificate with sig/crypto type)
USE CASES:
- Datagram2: Target destination hash for replay prevention
- Datagram3: Sender's fromhash for repliability
- LeaseSet addressing and lookup
- Any protocol requiring canonical destination identification
INTEROPERABILITY: This produces the same hash as Java I2P's calculateHash(), enabling cross-implementation compatibility for datagram protocols.
Returns the 32-byte SHA-256 hash, or a zero hash if serialization fails.
func (*Destination) SigningKeyPair ¶
func (dest *Destination) SigningKeyPair() (*Ed25519KeyPair, error)
SigningKeyPair returns the Ed25519 signing key pair for this destination. This provides access to both signing (with private key) and verification (with public key). For verification-only use cases (without private key access), use SigningPublicKey() instead.
Returns error if the destination has no Ed25519 keypair available.
func (*Destination) SigningPublicKey ¶
func (dest *Destination) SigningPublicKey() *Ed25519KeyPair
SigningPublicKey returns the Ed25519 public key for signature verification. This allows verification of signatures without needing the private key. Returns nil if no Ed25519 keypair is available.
func (*Destination) VerifySignature ¶
func (dest *Destination) VerifySignature(message, signature []byte) bool
VerifySignature verifies a signature against the given message using this destination's signing public key. This is useful for offline signature verification without access to the private key.
Returns true if the signature is valid, false otherwise.
func (*Destination) WriteForSignature ¶
func (dest *Destination) WriteForSignature(stream *Stream) (err error)
WriteForSignature writes the destination in the format used by Java I2P for SIGNATURE COMPUTATION.
SIGNATURE FORMAT (295 bytes for Ed25519):
- pubKey: 256 bytes (same as wire format)
- signingPubKey: 32 bytes (TRUNCATED, not padded to 128 bytes)
- certificate: 7+ bytes (same as wire format)
CRITICAL DIFFERENCE FROM WriteToMessage: When Java reads a Destination from the wire (128-byte signing key field), it extracts the actual key based on the certificate's declared sizes. When re-serializing for signature verification, Java writes the EXTRACTED key sizes, not the padded wire format.
For Ed25519:
- Wire format (WriteToMessage): 128-byte field with 32-byte key at bytes 96-127
- Signature format (WriteForSignature): just 32 bytes
USE THIS METHOD FOR:
- Computing data-to-sign for datagram authentication
- Signature verification (must match sender's computation)
DO NOT USE FOR:
- Transmitting destinations over the network (use WriteToMessage)
- Building datagram envelopes (use WriteToMessage)
See Java I2P: SigningPublicKey.writeTruncatedBytes() for reference implementation.
func (*Destination) WriteToFile ¶
func (dest *Destination) WriteToFile(filename string) (err error)
func (*Destination) WriteToMessage ¶
func (dest *Destination) WriteToMessage(stream *Stream) (err error)
WriteToMessage writes the destination in I2CP/I2NP WIRE FORMAT. This is the format used for transmitting destinations over the network and in datagram envelopes.
WIRE FORMAT (391+ bytes for Ed25519):
- pubKey: 256 bytes (encryption public key, zeros for modern crypto)
- signingPubKey: 128 bytes (Ed25519 key right-aligned at bytes 96-127)
- certificate: 7+ bytes (KEY certificate with sig/crypto type)
USE THIS METHOD FOR:
- Building datagram envelopes (sender destination in Datagram1/2/3)
- Any I2CP message that transmits a destination over the wire
- Hash computation for replay prevention (Datagram2)
The I2P specification says destinations are "387+ bytes" for DSA, but for Ed25519 with KEY certificates, the wire format is 391+ bytes (256 + 128 + 7). The apparent discrepancy is because DSA-SHA1 keys fit exactly in the legacy fields while Ed25519 requires padding and a KEY certificate.
See also:
- WriteForSignature: for signature computation (different signing key format)
- WriteToStream: for file storage (compact format, not wire-compatible)
- NewDestinationFromMessage: reads this format
func (*Destination) WriteToStream ¶
func (dest *Destination) WriteToStream(stream *Stream) (err error)
WriteToStream writes the destination in a COMPACT STORAGE FORMAT. This format is used for saving destinations to files (e.g., .dat files).
STORAGE FORMAT (varies):
- certificate: 3+ bytes
- algorithmType: 4 bytes
- signingKeyPair: algorithm-specific size
- encryptionPubKey: 256 bytes
This format differs from the wire format (WriteToMessage) and is NOT compatible with I2CP/I2NP message parsing. Use WriteToFile() for file operations.
USE THIS METHOD FOR:
- Saving destinations to disk for later loading
- Internal storage operations
DO NOT USE FOR:
- Network transmission (use WriteToMessage)
- Datagram envelopes (use WriteToMessage)
- Signature computation (use WriteForSignature)
See also:
- WriteToFile: convenience wrapper for file I/O
- NewDestinationFromFile: reads this format
type DisconnectInfo ¶
DisconnectInfo captures disconnect message details.
type Ed25519KeyPair ¶
type Ed25519KeyPair struct {
// contains filtered or unexported fields
}
Ed25519KeyPair represents an Ed25519 signature key pair for modern I2P cryptography. This type wraps github.com/go-i2p/crypto/ed25519 keys to provide I2CP-specific functionality while delegating cryptographic operations to the specialized crypto package.
func Ed25519KeyPairFromStream ¶
func Ed25519KeyPairFromStream(stream *Stream) (*Ed25519KeyPair, error)
Ed25519KeyPairFromStream reads an Ed25519 key pair from a stream. Uses github.com/go-i2p/crypto/ed25519 for key reconstruction.
func NewEd25519KeyPair ¶
func NewEd25519KeyPair() (*Ed25519KeyPair, error)
NewEd25519KeyPair generates a new Ed25519 key pair using github.com/go-i2p/crypto. This function delegates to the crypto package for secure key generation.
func (*Ed25519KeyPair) AlgorithmType ¶
func (kp *Ed25519KeyPair) AlgorithmType() uint32
AlgorithmType returns the algorithm type constant
func (*Ed25519KeyPair) PrivateKey ¶
func (kp *Ed25519KeyPair) PrivateKey() ed25519.PrivateKey
PrivateKey returns the private key as stdlib ed25519.PrivateKey for backward compatibility.
func (*Ed25519KeyPair) PublicKey ¶
func (kp *Ed25519KeyPair) PublicKey() ed25519.PublicKey
PublicKey returns the public key as stdlib ed25519.PublicKey for backward compatibility.
func (*Ed25519KeyPair) Sign ¶
func (kp *Ed25519KeyPair) Sign(message []byte) ([]byte, error)
Sign creates a signature for the given message using Ed25519. Uses github.com/go-i2p/crypto/ed25519 Signer interface for cryptographic operations.
func (*Ed25519KeyPair) SignStream ¶
func (kp *Ed25519KeyPair) SignStream(stream *Stream) error
SignStream creates a signature for stream data and appends it to the stream
func (*Ed25519KeyPair) Verify ¶
func (kp *Ed25519KeyPair) Verify(message, signature []byte) bool
Verify verifies a signature against the given message using Ed25519. Uses standard Ed25519 verification which handles SHA-512 hashing internally.
func (*Ed25519KeyPair) VerifyStream ¶
func (kp *Ed25519KeyPair) VerifyStream(stream *Stream) (bool, error)
VerifyStream verifies a signature embedded in the stream data
func (*Ed25519KeyPair) WritePublicKeyToStream ¶
func (kp *Ed25519KeyPair) WritePublicKeyToStream(stream *Stream) error
WritePublicKeyToStream writes only the public key to a stream. Uses crypto package's Bytes() method for key serialization.
func (*Ed25519KeyPair) WriteToStream ¶
func (kp *Ed25519KeyPair) WriteToStream(stream *Stream) error
WriteToStream writes the complete Ed25519 key pair to a stream
type InMemoryMetrics ¶
type InMemoryMetrics struct {
// contains filtered or unexported fields
}
InMemoryMetrics provides a simple in-memory implementation of MetricsCollector. Suitable for development, testing, and applications that want basic metrics without external dependencies.
All operations are thread-safe using atomic operations and minimal locking.
func NewInMemoryMetrics ¶
func NewInMemoryMetrics() *InMemoryMetrics
NewInMemoryMetrics creates a new in-memory metrics collector.
func (*InMemoryMetrics) ActiveSessions ¶
func (m *InMemoryMetrics) ActiveSessions() int
ActiveSessions returns the current count of active sessions.
func (*InMemoryMetrics) AddBytesReceived ¶
func (m *InMemoryMetrics) AddBytesReceived(bytes uint64)
AddBytesReceived adds to the total bytes received.
func (*InMemoryMetrics) AddBytesSent ¶
func (m *InMemoryMetrics) AddBytesSent(bytes uint64)
AddBytesSent adds to the total bytes sent.
func (*InMemoryMetrics) AllErrors ¶
func (m *InMemoryMetrics) AllErrors() map[string]uint64
AllErrors returns a copy of all error counts by type.
func (*InMemoryMetrics) AvgLatency ¶
func (m *InMemoryMetrics) AvgLatency(messageType uint8) time.Duration
AvgLatency returns the average latency for a message type in nanoseconds. Returns 0 if no measurements have been recorded.
func (*InMemoryMetrics) BytesReceived ¶
func (m *InMemoryMetrics) BytesReceived() uint64
BytesReceived returns the total bytes received.
func (*InMemoryMetrics) BytesSent ¶
func (m *InMemoryMetrics) BytesSent() uint64
BytesSent returns the total bytes sent.
func (*InMemoryMetrics) ConnectionState ¶
func (m *InMemoryMetrics) ConnectionState() string
ConnectionState returns the current connection state.
func (*InMemoryMetrics) Errors ¶
func (m *InMemoryMetrics) Errors(errorType string) uint64
Errors returns the total count of errors by type.
func (*InMemoryMetrics) IncrementError ¶
func (m *InMemoryMetrics) IncrementError(errorType string)
IncrementError increments the error counter for the given error type.
func (*InMemoryMetrics) IncrementMessageReceived ¶
func (m *InMemoryMetrics) IncrementMessageReceived(messageType uint8)
IncrementMessageReceived increments the received message counter for the given type.
func (*InMemoryMetrics) IncrementMessageSent ¶
func (m *InMemoryMetrics) IncrementMessageSent(messageType uint8)
IncrementMessageSent increments the sent message counter for the given type.
func (*InMemoryMetrics) MaxLatency ¶
func (m *InMemoryMetrics) MaxLatency(messageType uint8) time.Duration
MaxLatency returns the maximum latency for a message type. Returns 0 if no measurements have been recorded.
func (*InMemoryMetrics) MessagesReceived ¶
func (m *InMemoryMetrics) MessagesReceived(messageType uint8) uint64
MessagesReceived returns the total count of received messages by type.
func (*InMemoryMetrics) MessagesSent ¶
func (m *InMemoryMetrics) MessagesSent(messageType uint8) uint64
MessagesSent returns the total count of sent messages by type.
func (*InMemoryMetrics) MinLatency ¶
func (m *InMemoryMetrics) MinLatency(messageType uint8) time.Duration
MinLatency returns the minimum latency for a message type. Returns 0 if no measurements have been recorded.
func (*InMemoryMetrics) RecordMessageLatency ¶
func (m *InMemoryMetrics) RecordMessageLatency(messageType uint8, duration time.Duration)
RecordMessageLatency records the latency for a message type.
func (*InMemoryMetrics) Reset ¶
func (m *InMemoryMetrics) Reset()
Reset clears all metrics. Useful for testing.
func (*InMemoryMetrics) SetActiveSessions ¶
func (m *InMemoryMetrics) SetActiveSessions(count int)
SetActiveSessions updates the active sessions gauge.
func (*InMemoryMetrics) SetConnectionState ¶
func (m *InMemoryMetrics) SetConnectionState(state string)
SetConnectionState updates the connection state.
type Lease ¶
Lease is a type alias for lease.Lease from the common package. All lease operations (TunnelGateway, TunnelID, Time, Date, Bytes) are provided by the common package. I2CP-specific stream helpers are defined as package functions.
func NewLeaseFromStream ¶
NewLeaseFromStream reads a Lease from an I2CP Stream. Uses common/lease.ReadLease for parsing after reading the 44-byte lease data.
type LeaseSet2 ¶
type LeaseSet2 struct {
// contains filtered or unexported fields
}
LeaseSet2 represents a modern I2CP LeaseSet2 structure (I2CP 0.9.38+). LeaseSet2 supports multiple types: standard (3), encrypted (5), and meta (7). It uses Lease2 structures with 4-byte second timestamps for efficiency.
I2CP Specification: CreateLeaseSet2Message (type 41), section 3.4 Reference: https://geti2p.net/spec/common-structures#leaseset2
func NewLeaseSet2FromStream ¶
NewLeaseSet2FromStream parses a LeaseSet2 structure from an I2CP Stream. This function is called when receiving a CreateLeaseSet2Message from the router.
Stream format (all multi-byte integers in big-endian):
- LeaseSet type (1 byte): 3=standard, 5=encrypted, 7=meta
- Destination (387+ bytes): standard I2CP destination
- Published timestamp (4 bytes): seconds since epoch
- Expires timestamp (4 bytes): seconds since epoch
- Flags (2 bytes): bit 0=offline signature present
- Properties (variable): I2CP mapping structure
- Lease count (1 byte): number of leases (max 16)
- Leases (40 bytes each): Lease2 structures
- [Optional] Offline signature (variable): if flags bit 0 set
- Signature (variable): signature over all previous data
Parameters:
stream - I2CP Stream containing the LeaseSet2 data crypto - Crypto instance for parsing destination
Returns:
LeaseSet2 structure and any error encountered
I2CP Spec: CreateLeaseSet2Message format, I2CP 0.9.38+
func (*LeaseSet2) Destination ¶
func (ls *LeaseSet2) Destination() *Destination
Destination returns the destination this LeaseSet is for
func (*LeaseSet2) ExpiresSeconds ¶
ExpiresSeconds returns the expiration timestamp in seconds since epoch
func (*LeaseSet2) HasOfflineSignature ¶
HasOfflineSignature returns true if the LeaseSet2 has an offline signature
func (*LeaseSet2) LeaseCount ¶
LeaseCount returns the number of leases
func (*LeaseSet2) OfflineSignature ¶
func (ls *LeaseSet2) OfflineSignature() *OfflineSignature
OfflineSignature returns the offline signature (may be nil)
func (*LeaseSet2) Properties ¶
Properties returns the properties mapping
func (*LeaseSet2) PublishedSeconds ¶
PublishedSeconds returns the published timestamp in seconds since epoch
func (*LeaseSet2) VerifySignature ¶
VerifySignature verifies the LeaseSet2 cryptographic signature. Uses the destination's signing public key to verify the signature over all LeaseSet2 data preceding the signature field.
I2CP 0.9.38+ - Supports DSA-SHA1 (legacy) and Ed25519-SHA512 (modern) signatures.
Returns true if signature is cryptographically valid, false otherwise. Basic validation (non-empty signature, correct length) is performed first.
type LeaseSetWaitInfo ¶
type LeaseSetWaitInfo struct {
SessionID uint16
StartedAt time.Time
Timeout time.Duration
Received bool
ReceivedAt time.Time
TunnelCount uint8
}
LeaseSetWaitInfo tracks waiting for RequestVariableLeaseSet message.
type LoggerTags ¶
type LoggerTags = uint32
LoggerTags defines the type for logger tags Deprecated: Tags are now formatted as strings using fmt.Sprintf
type LookupEntry ¶
type LookupEntry struct {
// contains filtered or unexported fields
}
LookupEntry represents a destination lookup request entry. Stores the original lookup parameters to support processing the HostReply response.
I2CP Specification:
- Basic lookups (types 0-1): Only address/session tracked
- Service record lookups (types 2-4): Also tracks lookupType for parsing optional Mapping
I2CP 0.9.66+ Proposal 167: Service Record Support
type MaxRetriesExceededError ¶
MaxRetriesExceededError is returned when the maximum number of retries is exceeded.
func (*MaxRetriesExceededError) Error ¶
func (e *MaxRetriesExceededError) Error() string
func (*MaxRetriesExceededError) Unwrap ¶
func (e *MaxRetriesExceededError) Unwrap() error
type MessageError ¶
type MessageError struct {
MessageType uint8 // I2CP message type constant
Operation string // What operation failed (e.g., "parsing", "sending")
Err error // Underlying error
}
MessageError represents an error related to I2CP message processing. It includes the message type and additional context about what failed.
func (*MessageError) Error ¶
func (e *MessageError) Error() string
func (*MessageError) Unwrap ¶
func (e *MessageError) Unwrap() error
type MessageStats ¶
type MessageStats struct {
// contains filtered or unexported fields
}
MessageStats tracks sent and received message counts by type for diagnostic purposes. This is useful for debugging I2CP protocol interactions and identifying message flow issues.
func NewMessageStats ¶
func NewMessageStats() *MessageStats
NewMessageStats creates a new message statistics tracker.
func (*MessageStats) DiagnosticReport ¶
func (ms *MessageStats) DiagnosticReport() string
DiagnosticReport generates a diagnostic report for troubleshooting session creation issues. This is particularly useful when debugging "no SessionCreated response" problems.
func (*MessageStats) Disable ¶
func (ms *MessageStats) Disable()
Disable disables message statistics tracking.
func (*MessageStats) Enable ¶
func (ms *MessageStats) Enable()
Enable enables message statistics tracking.
func (*MessageStats) GetLastReceived ¶
func (ms *MessageStats) GetLastReceived(msgType uint8) (time.Time, bool)
GetLastReceived returns the timestamp of the last received message of the given type.
func (*MessageStats) GetLastSent ¶
func (ms *MessageStats) GetLastSent(msgType uint8) (time.Time, bool)
GetLastSent returns the timestamp of the last sent message of the given type.
func (*MessageStats) GetReceivedCount ¶
func (ms *MessageStats) GetReceivedCount(msgType uint8) uint64
GetReceivedCount returns the number of received messages of the given type.
func (*MessageStats) GetSentCount ¶
func (ms *MessageStats) GetSentCount(msgType uint8) uint64
GetSentCount returns the number of sent messages of the given type.
func (*MessageStats) IsEnabled ¶
func (ms *MessageStats) IsEnabled() bool
IsEnabled returns whether statistics tracking is enabled.
func (*MessageStats) RecordReceived ¶
func (ms *MessageStats) RecordReceived(msgType uint8, size uint64)
RecordReceived records a received message of the given type.
func (*MessageStats) RecordSent ¶
func (ms *MessageStats) RecordSent(msgType uint8, size uint64)
RecordSent records a sent message of the given type.
func (*MessageStats) Summary ¶
func (ms *MessageStats) Summary() string
Summary returns a human-readable summary of message statistics.
type MetaLease ¶
type MetaLease struct {
Hash [32]byte // SHA256 hash of the target LeaseSet destination
Flags uint32 // 3 bytes of flags (bits 0-3 = LeaseSet type)
Cost uint8 // Priority cost, 0-255, lower is better
EndDate uint32 // Expiration in seconds since epoch
}
MetaLease represents a single entry in a MetaLeaseSet. Unlike regular Lease2, MetaLease contains references to other LeaseSets rather than tunnel information.
Format (40 bytes):
- Hash (32 bytes): SHA256 hash of the target destination/LeaseSet
- Flags (3 bytes): bit 0-3 = type (0=unknown, 1=LeaseSet, 3=LeaseSet2, 5=MetaLeaseSet)
- Cost (1 byte): 0-255, lower value = higher priority
- EndDate (4 bytes): seconds since epoch
I2CP Specification: MetaLease structure
func NewMetaLease ¶
NewMetaLease creates a new MetaLease entry with the given parameters.
Parameters:
- hash: SHA256 hash of the target destination
- leaseSetType: Type of LeaseSet (1=LeaseSet, 3=LeaseSet2, 5=MetaLeaseSet)
- cost: Priority cost (0=highest priority, 255=lowest)
- endDate: Expiration timestamp in seconds since epoch
func ReadMetaLeaseFromStream ¶
ReadMetaLeaseFromStream reads a MetaLease from an I2CP stream. Returns the MetaLease and any error encountered.
func (*MetaLease) WriteToStream ¶
WriteToStream writes the MetaLease to an I2CP stream in the spec format. Format: hash(32) + flags(3) + cost(1) + endDate(4) = 40 bytes
type MetaLeaseSetConfig ¶
type MetaLeaseSetConfig struct {
MetaLeases []*MetaLease // References to other LeaseSets (max 16)
Revocations [][32]byte // Hashes of revoked LeaseSets
Properties map[string]string
}
MetaLeaseSetConfig holds the configuration for creating a MetaLeaseSet. Used when calling msgCreateMetaLeaseSet.
func NewMetaLeaseSetConfig ¶
func NewMetaLeaseSetConfig() *MetaLeaseSetConfig
NewMetaLeaseSetConfig creates a new MetaLeaseSetConfig with default values.
func (*MetaLeaseSetConfig) AddMetaLease ¶
func (c *MetaLeaseSetConfig) AddMetaLease(ml *MetaLease) error
AddMetaLease adds a MetaLease entry to the configuration. Returns an error if the maximum of 16 entries would be exceeded.
func (*MetaLeaseSetConfig) AddRevocation ¶
func (c *MetaLeaseSetConfig) AddRevocation(hash [32]byte)
AddRevocation adds a revocation hash to the configuration.
type MetricsCollector ¶
type MetricsCollector interface {
// IncrementMessageSent increments the count of messages sent by type.
// messageType should be an I2CP message type constant (e.g., I2CP_MSG_SEND_MESSAGE).
IncrementMessageSent(messageType uint8)
// IncrementMessageReceived increments the count of messages received by type.
// messageType should be an I2CP message type constant (e.g., I2CP_MSG_PAYLOAD_MESSAGE).
IncrementMessageReceived(messageType uint8)
// SetActiveSessions updates the gauge of currently active sessions.
SetActiveSessions(count int)
// IncrementError increments the error counter by error type.
// errorType should describe the error category (e.g., "network", "protocol", "timeout").
IncrementError(errorType string)
// RecordMessageLatency records the latency of a message send operation.
// messageType is the I2CP message type, duration is the operation time.
RecordMessageLatency(messageType uint8, duration time.Duration)
// SetConnectionState updates the current connection state.
// state should be "connected", "disconnected", or "reconnecting".
SetConnectionState(state string)
// AddBytesSent adds to the total bytes sent counter.
AddBytesSent(bytes uint64)
// AddBytesReceived adds to the total bytes received counter.
AddBytesReceived(bytes uint64)
}
MetricsCollector defines the interface for collecting I2CP client metrics. This interface allows applications to plug in custom metrics implementations (e.g., Prometheus, StatsD, custom logging) for production monitoring.
All methods are safe for concurrent use and should be non-blocking.
type OfflineSignature ¶
type OfflineSignature struct {
// contains filtered or unexported fields
}
OfflineSignature represents offline signing data for LeaseSet2. Offline signatures allow separation of online and offline keys for enhanced security.
The offline signature proves that the long-term signing key authorized a transient key for a limited time period. This allows the long-term key to remain offline while the transient key signs LeaseSets.
Signature Format (signed data):
signingKeyType (2 bytes) || signingKeyLen (2 bytes) || signingKey (variable) || expires (4 bytes) || transientKeyType (2 bytes) || transientKeyLen (2 bytes) || transientKey (variable)
The signature field contains the signature over the above data, signed by the long-term key.
Validation:
- ✅ Expiration checking via IsExpired()
- ✅ Cryptographic verification via Verify()
- ✅ Transient key validation via signature verification
I2CP Specification: LeaseSet2 § Offline Signatures
func (*OfflineSignature) Expires ¶
func (os *OfflineSignature) Expires() time.Time
Expires returns the expiration timestamp as time.Time
func (*OfflineSignature) ExpiresSeconds ¶
func (os *OfflineSignature) ExpiresSeconds() uint32
ExpiresSeconds returns the expiration timestamp in seconds since epoch
func (*OfflineSignature) GetExpires ¶
func (sig *OfflineSignature) GetExpires() uint32
GetExpires returns the expiration timestamp (seconds since epoch)
func (*OfflineSignature) GetTransientKey ¶
func (sig *OfflineSignature) GetTransientKey() []byte
GetTransientKey returns the transient public key bytes. This key should be used to verify the LeaseSet2 signature, not the signing key.
func (*OfflineSignature) IsExpired ¶
func (sig *OfflineSignature) IsExpired() bool
IsExpired checks if the offline signature has expired. Returns true if the current time is past the expiration timestamp.
I2CP Spec: Offline signatures must be rejected if expired to prevent unauthorized use of transient keys beyond their authorized period.
func (*OfflineSignature) Signature ¶
func (os *OfflineSignature) Signature() []byte
Signature returns the signature bytes
func (*OfflineSignature) SigningKey ¶
func (os *OfflineSignature) SigningKey() []byte
SigningKey returns the signing public key
func (*OfflineSignature) SigningKeyType ¶
func (os *OfflineSignature) SigningKeyType() uint16
SigningKeyType returns the signing key type
func (*OfflineSignature) String ¶
func (os *OfflineSignature) String() string
String returns a debug-friendly string representation
func (*OfflineSignature) TransientKey ¶
func (os *OfflineSignature) TransientKey() []byte
TransientKey returns the transient public signing key
func (*OfflineSignature) TransientKeyType ¶
func (os *OfflineSignature) TransientKeyType() uint16
TransientKeyType returns the transient signing key type
func (*OfflineSignature) Verify ¶
func (sig *OfflineSignature) Verify() error
Verify cryptographically verifies the offline signature. This validates that the long-term signing key actually authorized the transient key.
Verification process:
- Reconstruct signed data: signingKeyType || signingKeyLen || signingKey || expires || transientKeyType || transientKeyLen || transientKey
- Verify signature over this data using the signing key
Returns:
- nil if signature is valid
- ErrOfflineSignatureInvalid if verification fails
- ErrUnsupportedCrypto if signature type is not supported
I2CP Spec: LeaseSet2 § Offline Signatures
type PSKAuthenticator ¶
type PSKAuthenticator struct {
PreSharedKey [32]byte
// Salt is optional salt for HKDF derivation (can be nil)
Salt []byte
// Info is contextual info for HKDF (I2P uses "ELS2_L1K" for per-client auth)
Info []byte
}
PSKAuthenticator performs PSK-based authentication for encrypted LeaseSets. It uses HKDF to derive the decryption key from a pre-shared secret.
func NewPSKAuthenticator ¶
func NewPSKAuthenticator(preSharedKey [32]byte) *PSKAuthenticator
NewPSKAuthenticator creates a new PSK authenticator with the given pre-shared key.
func (*PSKAuthenticator) Authenticate ¶
func (p *PSKAuthenticator) Authenticate() (*AuthResult, error)
Authenticate derives the decryption key from the pre-shared key.
The process:
- Derive decryptionKey = HKDF-SHA256(psk, salt, info)
Returns AuthResult containing the decryption key for BlindingInfoMessage.
func (*PSKAuthenticator) WithInfo ¶
func (p *PSKAuthenticator) WithInfo(info []byte) *PSKAuthenticator
WithInfo sets custom info for HKDF derivation.
func (*PSKAuthenticator) WithSalt ¶
func (p *PSKAuthenticator) WithSalt(salt []byte) *PSKAuthenticator
WithSalt sets a custom salt for HKDF derivation.
type PendingMessage ¶
type PendingMessage struct {
Nonce uint32 // Message nonce (unique identifier)
Destination *Destination // Target destination
Protocol uint8 // Protocol identifier
SrcPort uint16 // Source port
DestPort uint16 // Destination port
PayloadSize uint32 // Payload size in bytes
SentAt time.Time // When message was sent
Status SessionMessageStatus // Current delivery status (0 if pending)
CompletedAt time.Time // When status was received (zero if pending)
Flags uint16 // Message flags (for SendMessageExpires)
Expiration uint64 // Expiration time in seconds (0 if no expiration)
}
PendingMessage represents a message awaiting delivery status Tracks messages from SendMessage call to MessageStatus callback
type PerClientAuthConfig ¶
type PerClientAuthConfig struct {
// AuthScheme specifies the authentication scheme to use.
// Use BLINDING_AUTH_SCHEME_DH (0) for Diffie-Hellman or
// BLINDING_AUTH_SCHEME_PSK (1) for Pre-Shared Key.
AuthScheme uint8
// PrivateKey is the 32-byte ECIES_X25519 private key (little-endian).
// This key is used to derive the shared secret for decrypting the LeaseSet.
// For DH scheme: This is your X25519 private key for DH exchange.
// For PSK scheme: This is the pre-shared secret key.
PrivateKey [32]byte
// LookupPassword is an optional password for encrypted LeaseSet lookup.
// Some destinations require both per-client auth AND a lookup password.
LookupPassword string
}
PerClientAuthConfig holds configuration for per-client authentication when accessing encrypted LeaseSets via BlindingInfoMessage.
func AuthenticateForBlindedDestination ¶
func AuthenticateForBlindedDestination(scheme uint8, clientKey, serverPublicKey [32]byte) (*PerClientAuthConfig, error)
AuthenticateForBlindedDestination performs per-client authentication for accessing a blinded destination and returns a configured PerClientAuthConfig.
Parameters:
- scheme: BLINDING_AUTH_SCHEME_DH (0) or BLINDING_AUTH_SCHEME_PSK (1)
- clientKey: For DH: your X25519 private key. For PSK: the pre-shared key.
- serverPublicKey: For DH: server's X25519 public key. For PSK: ignored.
Returns a PerClientAuthConfig ready to use with BlindingInfo.
func NewPerClientAuthDH ¶
func NewPerClientAuthDH(privateKey []byte) (*PerClientAuthConfig, error)
NewPerClientAuthDH creates a new per-client authentication config using Diffie-Hellman key exchange. The provided private key must be 32 bytes.
Usage:
privKey := generateX25519PrivateKey() // Your X25519 private key
authConfig, err := NewPerClientAuthDH(privKey)
if err != nil {
return err
}
blindingInfo := NewBlindingInfoWithAuth(endpoint, authConfig)
session.SendBlindingInfo(blindingInfo)
func NewPerClientAuthPSK ¶
func NewPerClientAuthPSK(presharedKey []byte) (*PerClientAuthConfig, error)
NewPerClientAuthPSK creates a new per-client authentication config using Pre-Shared Key. The provided key must be 32 bytes.
Usage:
psk := getPresharedKey() // The pre-shared key from the destination owner
authConfig, err := NewPerClientAuthPSK(psk)
if err != nil {
return err
}
blindingInfo := NewBlindingInfoWithAuth(endpoint, authConfig)
session.SendBlindingInfo(blindingInfo)
func (*PerClientAuthConfig) WithLookupPassword ¶
func (c *PerClientAuthConfig) WithLookupPassword(password string) *PerClientAuthConfig
WithLookupPassword sets the optional lookup password for the auth config. Some destinations require both per-client auth AND a lookup password.
type ProtocolDebugger ¶
type ProtocolDebugger struct {
// contains filtered or unexported fields
}
ProtocolDebugger provides enhanced protocol debugging capabilities.
func NewProtocolDebugger ¶
func NewProtocolDebugger() *ProtocolDebugger
NewProtocolDebugger creates a new protocol debugger.
func (*ProtocolDebugger) DiagnosticReport ¶
func (pd *ProtocolDebugger) DiagnosticReport() string
DiagnosticReport generates a comprehensive debug report.
func (*ProtocolDebugger) Disable ¶
func (pd *ProtocolDebugger) Disable()
Disable disables protocol debugging.
func (*ProtocolDebugger) DumpCreateSessionMessage ¶
func (pd *ProtocolDebugger) DumpCreateSessionMessage(data []byte, destSize, mappingSize int, timestamp uint64, sigSize int)
DumpCreateSessionMessage saves a CreateSession message for analysis.
func (*ProtocolDebugger) Enable ¶
func (pd *ProtocolDebugger) Enable()
Enable enables protocol debugging.
func (*ProtocolDebugger) GetDisconnectInfo ¶
func (pd *ProtocolDebugger) GetDisconnectInfo() *DisconnectInfo
GetDisconnectInfo returns the last disconnect information.
func (*ProtocolDebugger) GetMessageLog ¶
func (pd *ProtocolDebugger) GetMessageLog(limit int) []ProtocolMessage
GetMessageLog returns recent message log.
func (*ProtocolDebugger) IsEnabled ¶
func (pd *ProtocolDebugger) IsEnabled() bool
IsEnabled returns whether debugging is enabled.
func (*ProtocolDebugger) LogMessage ¶
func (pd *ProtocolDebugger) LogMessage(direction string, msgType uint8, size uint32, data []byte, sessionID uint16)
LogMessage records a protocol message.
func (*ProtocolDebugger) RecordDisconnect ¶
func (pd *ProtocolDebugger) RecordDisconnect(reason string, rawBytes []byte)
RecordDisconnect records disconnect message details.
func (*ProtocolDebugger) SetDumpDir ¶
func (pd *ProtocolDebugger) SetDumpDir(dir string)
SetDumpDir sets the directory for hex dumps.
type ProtocolError ¶
type ProtocolError struct {
Message string // Human-readable error description
Code int // Optional error code for programmatic handling
Fatal bool // Whether this error should terminate the connection
}
ProtocolError represents a protocol-level error with detailed information. Use this for serious protocol violations that may indicate bugs or attacks.
func (*ProtocolError) Error ¶
func (e *ProtocolError) Error() string
type ProtocolMessage ¶
type ProtocolMessage struct {
Timestamp time.Time
Direction string // "SENT" or "RECEIVED"
Type uint8
TypeName string
Size uint32
HexDump string // First 256 bytes as hex
SessionID uint16 // If applicable
}
ProtocolMessage records an I2CP message for debugging.
type RetryableFunc ¶
type RetryableFunc func() error
RetryableFunc is a function that can be retried. It should return an error implementing Temporary() for retry control.
type RouterInfo ¶
type RouterInfo struct {
// contains filtered or unexported fields
}
RouterInfo contains information about the I2P router. Moved from: client.go
MINOR FIX: Router Version Tracking Documentation Per I2CP § Set Date (0.8.7+) and § Version Notes: The router sends its I2CP API version string in SetDateMessage, which clients should use for feature detection and compatibility checks.
Router Version Features by Release:
- 0.8.7+: Version exchange in Get/Set Date messages
- 0.9.4+: Fast receive mode (deprecates ReceiveMessageBegin/End)
- 0.9.7+: RequestVariableLeaseSet (deprecates RequestLeaseSet)
- 0.9.11+: HostLookup/HostReply with session IDs (deprecates DestLookup/DestReply)
- 0.9.21+: Enhanced bandwidth limits, session reconfiguration
- 0.9.38+: ECIES-X25519 encryption support
- 0.9.46+: BlindingInfoMessage, offline signature keys
- 0.9.56+: MetaLeaseSet support
The Client uses router.version for automatic feature detection:
- HostLookup vs DestLookup selection (0.9.11+ check)
- Authentication method validation (0.9.46+ for auth 3-4)
- Bandwidth limits interpretation (0.9.21+ enhanced features)
This enables graceful degradation when connecting to older routers and prevents use of unsupported features that would cause protocol errors.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session represents an I2CP session with modern concurrency and lifecycle management per I2CP specification - supports primary/subsession relationships and proper resource cleanup
func NewSession ¶
func NewSession(client *Client, callbacks SessionCallbacks) *Session
NewSession creates a new I2CP session with the specified client and callbacks per I2CP specification - creates session with proper initialization and error handling This is the exported version of the session constructor for public API usage
func NewSessionWithContext ¶
func NewSessionWithContext(ctx context.Context, client *Client, callbacks SessionCallbacks) (*Session, error)
NewSessionWithContext creates a new I2CP session with context support for timeout control per I2CP specification 0.9.21+ - supports multi-session contexts and cancellation
func (*Session) BlindingFlags ¶
BlindingFlags returns the current blinding flags per I2CP specification 0.9.43+
func (*Session) BlindingParams ¶
BlindingParams returns a copy of the current blinding parameters per I2CP specification 0.9.43+ - returns nil if no parameters set
func (*Session) BlindingScheme ¶
BlindingScheme returns the current blinding cryptographic scheme per I2CP specification 0.9.43+ - returns 0 if blinding is disabled
func (*Session) ClearBlinding ¶
func (session *Session) ClearBlinding()
ClearBlinding clears all blinding parameters per I2CP specification 0.9.43+ - resets to non-blinded state
func (*Session) ClearPendingMessages ¶
ClearPendingMessages removes all pending messages per I2CP specification - called on session close or reset Returns the number of messages that were pending
func (*Session) Close ¶
Close gracefully closes the session and releases resources per I2CP specification - implements proper session lifecycle management with cleanup Sends DestroySession message to router and waits for cleanup completion
func (*Session) CompleteMessage ¶
func (session *Session) CompleteMessage(nonce uint32, status SessionMessageStatus) (*PendingMessage, bool)
CompleteMessage marks a message as completed with the given status per I2CP specification - called when MessageStatusMessage (type 22) is received Returns the pending message and true if found, nil and false otherwise
func (*Session) Config ¶
func (session *Session) Config() *SessionConfig
Config returns the session's configuration. Returns nil if the session was not properly initialized.
The returned SessionConfig contains tunnel settings, cryptographic options, and the destination identity for this session.
I2CP Spec: Session configuration is sent during CreateSessionMessage (type 1).
Example:
config := session.Config()
if config != nil {
fmt.Printf("Session destination: %s\n", config.destination.Base64())
}
func (*Session) CreateMetaLeaseSet ¶
func (s *Session) CreateMetaLeaseSet(config *MetaLeaseSetConfig) error
CreateMetaLeaseSet creates and sends a MetaLeaseSet for this session. This allows the session's destination to act as an aggregation point for multiple other destinations.
Parameters:
- config: MetaLeaseSetConfig containing the MetaLease entries
Returns an error if the session is not connected or if sending fails.
func (*Session) CreateMetaLeaseSetQueued ¶
func (s *Session) CreateMetaLeaseSetQueued(config *MetaLeaseSetConfig) error
CreateMetaLeaseSetQueued creates a MetaLeaseSet and queues it for sending. Use this when not yet connected to the router.
func (*Session) DeriveBlindingKeysForDestination ¶
func (s *Session) DeriveBlindingKeysForDestination(date string) (*BlindingKeyDerivation, error)
DeriveBlindingKeysForDestination derives blinding keys for this session's destination. This is used by services to create blinded versions of their destination for publication.
The secret is derived from the session's signing key pair seed.
Parameters:
- date: Date in "YYYY-MM-DD" format (or empty for today)
Returns:
- BlindingKeyDerivation with alpha and blinded keys
- Error if session has no destination or derivation fails
func (*Session) Destination ¶
func (session *Session) Destination() *Destination
Destination returns the session's destination per I2CP specification - provides access to session destination for addressing
func (*Session) GetPendingMessage ¶
func (session *Session) GetPendingMessage(nonce uint32) (*PendingMessage, bool)
GetPendingMessage returns a pending message by nonce without completing it per I2CP specification - used for status queries and debugging Returns the pending message and true if found, nil and false otherwise
func (*Session) GetPendingMessages ¶
func (session *Session) GetPendingMessages() map[uint32]*PendingMessage
GetPendingMessages returns a snapshot of all pending messages per I2CP specification - used for monitoring and cleanup Returns a copy of the pending messages map to prevent external modification
func (*Session) GetProperty ¶
func (session *Session) GetProperty(prop SessionConfigProperty) string
GetProperty returns the value of a specific session configuration property. Returns an empty string if the session is not properly initialized or the property is not set.
Available properties include tunnel configuration (quantity, length, variance), cryptographic options (tagsToSend, lowTagThreshold), and I2CP protocol settings (fastReceive, gzip, messageReliability).
See SessionConfigProperty constants for the full list of available properties.
I2CP Spec: Session properties are sent as a mapping in CreateSessionMessage (type 1).
Example:
fastReceive := session.GetProperty(SESSION_CONFIG_PROP_I2CP_FAST_RECEIVE)
if fastReceive == "true" {
fmt.Println("Fast receive mode enabled")
}
nickname := session.GetProperty(SESSION_CONFIG_PROP_INBOUND_NICKNAME)
fmt.Printf("Inbound tunnel nickname: %s\n", nickname)
func (*Session) GetTunnelLength ¶
GetTunnelLength returns the hop count (length) for tunnels in this session. The inbound parameter determines which direction: true for inbound, false for outbound. Returns 0 if the session is not properly initialized or the property is not set.
Tunnel length affects anonymity and latency:
- Higher values (3+): Stronger anonymity, higher latency
- Lower values (1-2): Lower latency, weaker anonymity
- Default (from client properties): 3 hops for strong anonymity
I2CP Spec: Tunnel configuration is part of session properties mapping.
Example:
inboundLength := session.GetTunnelLength(true)
outboundLength := session.GetTunnelLength(false)
fmt.Printf("Tunnel lengths: %d inbound hops, %d outbound hops\n",
inboundLength, outboundLength)
func (*Session) GetTunnelQuantity ¶
GetTunnelQuantity returns the number of tunnels configured for this session. The inbound parameter determines which direction: true for inbound, false for outbound. Returns 0 if the session is not properly initialized or the property is not set.
Tunnel quantity affects anonymity and performance:
- Higher values (3-5): Better anonymity and reliability, more overhead
- Lower values (1-2): Lower latency, less anonymity
- Default (from client properties): 3 tunnels for balanced anonymity/performance
I2CP Spec: Tunnel configuration is part of session properties mapping.
Example:
inboundCount := session.GetTunnelQuantity(true)
outboundCount := session.GetTunnelQuantity(false)
fmt.Printf("Tunnels: %d inbound, %d outbound\n", inboundCount, outboundCount)
func (*Session) ID ¶
ID returns the session ID assigned by the router per I2CP specification - unique identifier for session within I2CP connection
func (*Session) IsBlindingEnabled ¶
IsBlindingEnabled returns true if blinding is currently enabled per I2CP specification 0.9.43+ - checks if scheme is non-zero
func (*Session) IsOffline ¶ added in v0.1.1
IsOffline returns true if this session uses offline keys (LS2 offline signing). per I2CP specification § SessionConfig - Offline Signatures
Sessions with offline keys have a transient signing key that is time-limited, while the master signing key remains offline (not accessible to the I2CP client).
IMPORTANT: Datagram1 (protocol 17) does NOT support offline signatures. If this method returns true, applications should use Datagram2 (protocol 19) instead of Datagram1 for repliable authenticated datagrams.
The Java reference implementation (I2PDatagramMaker.java) throws IllegalArgumentException if session.isOffline() returns true when attempting to create Datagram1 messages.
Example usage:
if session.IsOffline() {
// Use Datagram2 for repliable authenticated datagrams
protocol = go_i2cp.ProtoDatagram2
} else {
// Use Datagram1 (traditional repliable datagram)
protocol = go_i2cp.ProtoDatagram
}
func (*Session) IsPrimary ¶
IsPrimary returns whether this is a primary session or subsession per I2CP specification 0.9.21+ - primary sessions own tunnel pools, subsessions share them
func (*Session) LookupDestination ¶
LookupDestination initiates an asynchronous destination lookup using HostLookupMessage per I2CP specification 0.9.11+ - implements destination and hostname resolution. The resolved destination is delivered via the OnDestination callback; this method only returns an error if the request itself cannot be sent.
func (*Session) LookupDestinationWithContext ¶
func (session *Session) LookupDestinationWithContext(ctx context.Context, address string, timeout time.Duration) error
LookupDestinationWithContext initiates an asynchronous destination lookup with context support per I2CP specification 0.9.11+ - implements context-aware destination resolution. The resolved destination is delivered via the OnDestination callback.
func (*Session) PendingMessageCount ¶
PendingMessageCount returns the number of messages awaiting status per I2CP specification - used for monitoring queue depth
func (*Session) PrimarySession ¶
PrimarySession returns the primary session for this subsession per I2CP specification 0.9.21+ - subsessions reference their primary for tunnel sharing
func (*Session) ReconfigureSession ¶
ReconfigureSession updates session configuration with new properties per I2CP specification section 7.1 - supports dynamic tunnel and crypto parameter updates Returns error if reconfiguration fails or properties are invalid
func (*Session) ReconfigureSessionWithContext ¶
func (session *Session) ReconfigureSessionWithContext(ctx context.Context, properties map[string]string) error
ReconfigureSessionWithContext updates session configuration with context support per I2CP specification section 7.1 - implements context-aware reconfiguration with timeout
func (*Session) SendBlindingInfo ¶
func (session *Session) SendBlindingInfo(info *BlindingInfo) error
SendBlindingInfo is a convenience method on Session to send blinding info for a destination. This is the primary API for applications to use when messaging blinded destinations.
Example usage:
info := &go_i2cp.BlindingInfo{
EndpointType: go_i2cp.BLINDING_ENDPOINT_HASH,
Endpoint: destHash[:],
BlindedSigType: 11, // Ed25519-SHA512
Expiration: uint32(time.Now().Add(24*time.Hour).Unix()),
LookupPassword: "optional-secret",
}
err := session.SendBlindingInfo(info)
func (*Session) SendBlindingInfoForHash ¶
func (s *Session) SendBlindingInfoForHash( hash []byte, blindedSigType uint16, expiration uint32, authConfig *PerClientAuthConfig, ) error
SendBlindingInfoForHash is a convenience method to send BlindingInfo for a hash endpoint.
func (*Session) SendBlindingInfoForHostname ¶
func (s *Session) SendBlindingInfoForHostname( hostname string, blindedSigType uint16, expiration uint32, authConfig *PerClientAuthConfig, ) error
SendBlindingInfoForHostname is a convenience method to send BlindingInfo for a hostname.
func (*Session) SendBlindingInfoWithAuth ¶
func (s *Session) SendBlindingInfoWithAuth( endpointType uint8, endpoint []byte, blindedSigType uint16, expiration uint32, authConfig *PerClientAuthConfig, ) error
SendBlindingInfoWithAuth is a convenience method to send BlindingInfo with per-client auth. It creates the BlindingInfo, configures auth, and sends it to the router.
Parameters:
- endpointType: BLINDING_ENDPOINT_HASH, BLINDING_ENDPOINT_HOSTNAME, etc.
- endpoint: The endpoint data (hash, hostname, destination bytes, or sigkey)
- blindedSigType: The signature type used for blinding
- expiration: Expiration time in seconds since epoch
- authConfig: Per-client authentication configuration (can be nil)
func (*Session) SendMessage ¶
func (session *Session) SendMessage(destination *Destination, protocol uint8, srcPort, destPort uint16, payload *Stream, nonce uint32) error
SendMessage sends a basic message without expiration control per I2CP specification - implements basic message delivery via SendMessageMessage (type 5)
func (*Session) SendMessageExpires ¶
func (session *Session) SendMessageExpires(dest *Destination, protocol uint8, srcPort, destPort uint16, payload *Stream, flags uint16, expirationSeconds uint64) error
SendMessageExpires sends a message with expiration time and flags for delivery options per I2CP specification 0.7.1+ - implements SendMessageExpiresMessage (type 36) for enhanced delivery control Supports per-message reliability override and tag management
func (*Session) SendMessageExpiresWithContext ¶
func (session *Session) SendMessageExpiresWithContext(ctx context.Context, dest *Destination, protocol uint8, srcPort, destPort uint16, payload *Stream, flags uint16, expirationSeconds uint64) error
SendMessageExpiresWithContext sends an expiring message with context support per I2CP specification 0.7.1+ - implements context-aware expiring message delivery
func (*Session) SendMessageWithContext ¶
func (session *Session) SendMessageWithContext(ctx context.Context, destination *Destination, protocol uint8, srcPort, destPort uint16, payload *Stream, nonce uint32) error
SendMessageWithContext sends a message with context support for timeout control per I2CP specification - implements context-aware message delivery with cancellation
func (*Session) SessionID ¶
SessionID returns the session ID assigned by the router per I2CP specification - unique identifier for session within I2CP connection This is an idiomatic alias for ID() following Go naming conventions
func (*Session) SetBlindingFlags ¶
SetBlindingFlags sets the blinding flags per I2CP specification 0.9.43+
func (*Session) SetBlindingParams ¶
SetBlindingParams sets the blinding parameters per I2CP specification 0.9.43+ - stores a copy of the provided data
func (*Session) SetBlindingScheme ¶
SetBlindingScheme sets the blinding cryptographic scheme per I2CP specification 0.9.43+ - use 0 to disable blinding
func (*Session) SetID ¶
SetID sets the session ID (internal use only) per I2CP specification - called by client when session is created by router
func (*Session) SetPrimary ¶
SetPrimary sets the primary session flag (internal use only) per I2CP specification 0.9.21+ - used for multi-session support
func (*Session) SetPrimarySession ¶
SetPrimarySession sets the primary session reference (internal use only) per I2CP specification 0.9.21+ - links subsession to primary for resource sharing
func (*Session) SigningKeyPair ¶
func (session *Session) SigningKeyPair() (*Ed25519KeyPair, error)
SigningKeyPair returns the Ed25519 key pair used for this session. Returns the key pair that corresponds to the session's destination. This key pair is used to sign I2P Streaming Protocol packets and other cryptographic operations requiring the session's signing key.
Returns:
- *Ed25519KeyPair: The signing key pair if available
- error: ErrSessionNotInitialized if session not properly initialized, or an error describing why the key pair is unavailable
Example usage for packet signing:
keyPair, err := session.SigningKeyPair()
if err != nil {
return err
}
signature, err := keyPair.Sign(packetData)
func (*Session) StoreBlindingInfo ¶
StoreBlindingInfo stores received blinding parameters in the session. This is called when the router sends BlindingInfoMessage to provide parameters for accessing an encrypted LeaseSet.
The stored parameters can be retrieved with BlindingParams() and used for key derivation with DeriveBlindingFactor.
func (*Session) TrackMessage ¶
func (session *Session) TrackMessage(nonce uint32, dest *Destination, protocol uint8, srcPort, destPort uint16, payloadSize uint32, flags uint16, expiration uint64) error
TrackMessage registers a message for delivery tracking per I2CP specification - tracks messages from send to status callback (type 22) Returns error if nonce is already being tracked
func (*Session) TransientSigningKeyPair ¶ added in v0.1.1
func (session *Session) TransientSigningKeyPair() (*Ed25519KeyPair, error)
TransientSigningKeyPair returns the transient Ed25519 signing key pair for offline sessions. This is used for signing Datagram2 payloads when the session uses offline keys.
Per I2P Proposal 163 (Datagram2), offline signature block construction requires:
- Authorization: Sign(expires||sigtype||transient_pubkey) with destination key
- Payload: Sign(target_hash||flags||options||offline_sig||payload) with transient key
This method returns the transient key pair needed for the payload signature. Use SigningKeyPair() to get the destination key for authorization signatures.
Returns:
- The transient Ed25519 key pair if offline signing is configured
- Error if session is not offline or no transient key pair is configured
Example usage for Datagram2 offline signature construction:
if session.IsOffline() {
transientKP, err := session.TransientSigningKeyPair()
if err != nil {
return err
}
payloadSig, err := transientKP.Sign(payloadData)
}
func (*Session) ValidateProtocol ¶ added in v0.1.1
ValidateProtocol checks if the given protocol is compatible with this session's configuration. Returns an error if the protocol cannot be used with this session.
Currently validates:
- ProtoDatagram (17) is not used with offline-signed sessions
This provides a clear error message instead of cryptographic failures when users attempt incompatible protocol/session combinations.
type SessionCallbacks ¶
type SessionCallbacks struct {
// OnMessage is called when a message is received from another I2P destination.
// Parameters:
// - session: The session that received the message
// - srcDest: Source I2P destination that sent the message
// - protocol: Protocol number (application-defined)
// - srcPort: Source port (application-defined)
// - destPort: Destination port (application-defined)
// - payload: Message payload as a Stream (can be read with ReadUint*/ReadBytes methods)
OnMessage func(session *Session, srcDest *Destination, protocol uint8, srcPort, destPort uint16, payload *Stream)
// OnStatus is called when the session status changes.
// Parameters:
// - session: The session whose status changed
// - status: New session status (e.g., SessionCreated, SessionDestroyed)
OnStatus func(session *Session, status SessionStatus)
// OnDestination is called when a destination lookup completes.
// Parameters:
// - session: The session that requested the lookup
// - requestId: Request identifier from the original lookup call
// - address: Destination address that was looked up (Base32 or Base64)
// - dest: Resolved destination, or nil if lookup failed
OnDestination func(session *Session, requestId uint32, address string, dest *Destination)
// OnMessageStatus is called when a sent message's delivery status is updated.
// Useful for tracking message delivery and implementing reliable messaging.
// Parameters:
// - session: The session that sent the message
// - messageId: Message nonce/identifier from SendMessage
// - status: Delivery status (e.g., SendSuccess, SendFailure)
// - size: Message size in bytes
// - nonce: Message nonce (same as messageId)
OnMessageStatus func(session *Session, messageId uint32, status SessionMessageStatus, size, nonce uint32)
// OnLeaseSet2 is called when the router requests LeaseSet publication via RequestVariableLeaseSetMessage.
// I2CP 0.9.38+ - The router provides lease information; the client creates and publishes the LeaseSet2.
// Note: This is NOT triggered when receiving a remote destination's LeaseSet - use DestLookup for that.
// Parameters:
// - session: The session that received the LeaseSet request
// - leaseSet: The LeaseSet2 structure with destination, leases, and signature to publish
//
// Example:
//
// OnLeaseSet2: func(sess *Session, ls *LeaseSet2) {
// log.Printf("LeaseSet2: type=%d, expires=%s", ls.Type(), ls.Expires())
// if ls.IsExpired() {
// log.Println("WARNING: LeaseSet expired")
// }
// }
OnLeaseSet2 func(session *Session, leaseSet *LeaseSet2)
// OnBlindingInfo is called when the router provides blinding information for encrypted LeaseSet access.
// I2CP 0.9.43+ - Used for password-protected or key-protected destinations.
// Parameters:
// - session: The session that received blinding info
// - blindingScheme: Authentication scheme (0=DH, 1=PSK)
// - blindingFlags: Flags indicating required authentication
// - blindingParams: Blinding parameters (store securely for future access)
//
// Important: Store blindingParams securely - they're required to access encrypted destinations.
//
// Example:
//
// OnBlindingInfo: func(sess *Session, scheme, flags uint16, params []byte) {
// log.Printf("Blinding enabled: scheme=%d, flags=%d", scheme, flags)
// // Store params securely for future connections
// if err := storeBlindingParams(params); err != nil {
// log.Printf("Failed to store blinding params: %v", err)
// }
// }
OnBlindingInfo func(session *Session, blindingScheme, blindingFlags uint16, blindingParams []byte)
// OnMetaLeaseSet is called when a send attempt fails because the destination uses a MetaLeaseSet.
// I2CP 0.9.41+ (MessageStatus code 22) - Indicates multi-homed destination requiring resolution.
// Parameters:
// - session: The session that attempted to send
// - originalDest: The MetaLeaseSet destination that was targeted
// - messageNonce: Nonce of the failed message (for retry tracking)
//
// Recovery procedure:
// 1. Call session.LookupDestination() with the originalDest hash to retrieve MetaLeaseSet contents
// 2. Parse the MetaLeaseSet to extract available destination hashes
// 3. Select one hash (application logic - e.g., random, round-robin, or preference-based)
// 4. Retry SendMessage using the selected destination hash
//
// Example:
//
// OnMetaLeaseSet: func(sess *Session, dest *Destination, nonce uint32) {
// log.Printf("Destination is MetaLeaseSet, resolving...")
// // Request MetaLeaseSet contents via HostLookup
// sess.LookupDestination(dest.Base64())
// // In OnDestination callback, parse meta and select actual destination
// }
OnMetaLeaseSet func(session *Session, originalDest *Destination, messageNonce uint32)
}
SessionCallbacks provides callback functions for session events. All callbacks are optional and can be set to nil if not needed. Callbacks may be invoked concurrently, so implementations should be thread-safe.
Example:
callbacks := SessionCallbacks{
OnMessage: func(sess *Session, proto uint8, src, dest uint16, payload *Stream) {
log.Printf("Received message: protocol=%d, ports=%d->%d", proto, src, dest)
},
OnMessageStatus: func(sess *Session, msgId uint32, status SessionMessageStatus, size, nonce uint32) {
log.Printf("Message %d status: %v", msgId, status)
},
}
session := NewSession(client, callbacks)
type SessionConfig ¶
type SessionConfig struct {
// contains filtered or unexported fields
}
func NewSessionConfig ¶
func NewSessionConfig() (*SessionConfig, error)
NewSessionConfig creates a new SessionConfig with auto-generated destination. This is the simplest way to create a session configuration without loading from a file. The destination is created using standard cryptography (currently Ed25519 by default).
Example:
config := NewSessionConfig() // config is ready to use with default settings
If you need to load a destination from a file, use NewSessionConfigFromDestinationFile instead.
func NewSessionConfigFromDestinationFile ¶
func NewSessionConfigFromDestinationFile(filename string, crypto *Crypto) (config SessionConfig)
func (*SessionConfig) GetOfflineSignatureBytes ¶
func (config *SessionConfig) GetOfflineSignatureBytes() []byte
GetOfflineSignatureBytes returns the offline signature bytes. Returns nil if offline signing is not configured or the signature is invalid.
func (*SessionConfig) GetOfflineSignatureExpiration ¶
func (config *SessionConfig) GetOfflineSignatureExpiration() uint32
GetOfflineSignatureExpiration returns the offline signature expiration timestamp. Returns 0 if offline signing is not configured.
func (*SessionConfig) GetOfflineSignatureTransientKey ¶
func (config *SessionConfig) GetOfflineSignatureTransientKey() []byte
GetOfflineSignatureTransientKey returns the transient public key for offline signing. Returns nil if offline signing is not configured or the key is invalid.
func (*SessionConfig) GetProperty ¶
func (config *SessionConfig) GetProperty(prop SessionConfigProperty) string
func (*SessionConfig) GetTransientKeyPair ¶ added in v0.1.1
func (config *SessionConfig) GetTransientKeyPair() *Ed25519KeyPair
GetTransientKeyPair returns the transient signing key pair for offline sessions. Returns nil if no transient key pair has been configured.
This method provides access to the transient private key needed for signing Datagram2 payloads when the session is offline (IsOffline() returns true).
func (*SessionConfig) HasOfflineSignature ¶
func (config *SessionConfig) HasOfflineSignature() bool
HasOfflineSignature returns true if the session is configured for offline-signed operation. Per I2CP § SessionConfig - Offline Signatures, all three properties must be set.
func (*SessionConfig) SetOfflineSignature ¶
func (config *SessionConfig) SetOfflineSignature(expiration uint32, transientPublicKey, signature []byte) error
SetOfflineSignature configures the session for offline-signed destination operation. Per I2CP § SessionConfig - Offline Signatures: "If the Destination is offline signed, the Mapping must contain:
- i2cp.leaseSetOfflineExpiration
- i2cp.leaseSetTransientPublicKey
- i2cp.leaseSetOfflineSignature"
Parameters:
- expiration: Unix timestamp in seconds when the offline signature expires
- transientPublicKey: The transient signing public key (raw bytes, will be base64 encoded)
- signature: The offline signature (raw bytes, will be base64 encoded)
The signature is generated by signing [signingKeyType||signingKey||expires||transientKeyType||transientKey] with the long-term signing private key. The session then uses the transient private key for all subsequent signatures (e.g., LeaseSet signing).
This enables enhanced security by keeping the long-term private key offline and only using a time-limited transient key for active operations.
func (*SessionConfig) SetProperty ¶
func (config *SessionConfig) SetProperty(prop SessionConfigProperty, value string)
func (*SessionConfig) SetTransientKeyPair ¶ added in v0.1.1
func (config *SessionConfig) SetTransientKeyPair(keyPair *Ed25519KeyPair) error
SetTransientKeyPair sets the transient signing key pair for offline-signed sessions. This key pair is used for Datagram2 payload signing when the session is offline.
The transient key pair should be generated separately and the public key should also be passed to SetOfflineSignature() along with the authorization signature.
Per I2P Proposal 163 (Datagram2), offline signature block construction requires:
- Authorization: Sign(expires||sigtype||transient_pubkey) with destination key
- Payload: Sign(target_hash||flags||options||offline_sig||payload) with transient key
This method stores the transient private key needed for the payload signature. Returns an error if the key pair is nil.
func (*SessionConfig) ValidateOfflineSignature ¶
func (config *SessionConfig) ValidateOfflineSignature() error
ValidateOfflineSignature validates the offline signature configuration. Per I2CP § SessionConfig - Offline Signatures, all three properties must be set together.
This function validates:
- All three properties are set (or none are set)
- The expiration timestamp is not in the past
- The transient public key and signature are valid base64
Returns nil if the configuration is valid or if offline signing is not configured.
func (*SessionConfig) ValidateTimestamp ¶
func (config *SessionConfig) ValidateTimestamp() error
ValidateTimestamp validates that the session config timestamp is within ±30 seconds of the current time, as required by the I2CP specification.
Per I2CP § SessionConfig Notes: "The creation date must be within +/- 30 seconds of the current time when processed by the router, or the config will be rejected."
This validation should be called before sending CreateSessionMessage to ensure early detection of clock synchronization issues.
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_LEASESET_ENC_TYPE SESSION_CONFIG_PROP_I2CP_MESSAGE_RELIABILITY SESSION_CONFIG_PROP_I2CP_PASSWORD SESSION_CONFIG_PROP_I2CP_USERNAME // Offline Signature Properties (I2CP § SessionConfig - Offline Signatures) // These three properties must ALL be set together if the Destination uses offline signing. // Per SPEC.md: "If the Destination is offline signed, the Mapping must contain: // - i2cp.leaseSetOfflineExpiration // - i2cp.leaseSetTransientPublicKey // - i2cp.leaseSetOfflineSignature" SESSION_CONFIG_PROP_I2CP_LEASESET_OFFLINE_EXPIRATION // Unix timestamp in seconds when offline signature expires SESSION_CONFIG_PROP_I2CP_LEASESET_TRANSIENT_PUBLIC_KEY // Base64-encoded transient signing public key SESSION_CONFIG_PROP_I2CP_LEASESET_OFFLINE_SIGNATURE // Base64-encoded offline signature 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 SessionError ¶
type SessionError struct {
SessionID uint16 // I2CP session ID (2-byte integer)
Operation string // What operation failed
Err error // Underlying error
}
SessionError represents an error related to session operations. It includes the session ID for debugging and tracing.
func (*SessionError) Error ¶
func (e *SessionError) Error() string
func (*SessionError) Unwrap ¶
func (e *SessionError) Unwrap() error
type SessionMessageStatus ¶
type SessionMessageStatus = uint8
Legacy type alias for backward compatibility DEPRECATED: Use uint8 MSG_STATUS_* constants directly
type SessionState ¶
type SessionState uint8
SessionState represents the lifecycle state of an I2CP session. This helps diagnose where in the protocol flow issues occur.
const ( // SessionStatePending - CreateSession sent, awaiting response SessionStatePending SessionState = iota // SessionStateCreated - SessionStatus received with CREATED status SessionStateCreated // SessionStateAwaitingLeaseSet - Waiting for RequestVariableLeaseSet from router SessionStateAwaitingLeaseSet // SessionStateLeaseSetRequested - Router requested LeaseSet (type 37 received) SessionStateLeaseSetRequested // SessionStateLeaseSetSent - CreateLeaseSet2 sent to router SessionStateLeaseSetSent // SessionStateActive - Session fully established and active SessionStateActive // SessionStateDestroying - DestroySession sent SessionStateDestroying // SessionStateDestroyed - Session destroyed SessionStateDestroyed // SessionStateRejected - Session was rejected by router SessionStateRejected // SessionStateDisconnected - Connection lost SessionStateDisconnected )
func (SessionState) String ¶
func (s SessionState) String() string
String returns a human-readable name for the session state.
type SessionStateTracker ¶
type SessionStateTracker struct {
// contains filtered or unexported fields
}
SessionStateTracker tracks the lifecycle state of I2CP sessions for debugging.
func NewSessionStateTracker ¶
func NewSessionStateTracker() *SessionStateTracker
NewSessionStateTracker creates a new session state tracker.
func (*SessionStateTracker) DiagnosticReport ¶
func (sst *SessionStateTracker) DiagnosticReport() string
DiagnosticReport generates a comprehensive session state report.
func (*SessionStateTracker) Disable ¶
func (sst *SessionStateTracker) Disable()
Disable disables session state tracking.
func (*SessionStateTracker) Enable ¶
func (sst *SessionStateTracker) Enable()
Enable enables session state tracking.
func (*SessionStateTracker) GetLeaseSetWaitDiagnostics ¶
func (sst *SessionStateTracker) GetLeaseSetWaitDiagnostics() string
GetLeaseSetWaitDiagnostics returns diagnostic info about LeaseSet waits.
func (*SessionStateTracker) GetState ¶
func (sst *SessionStateTracker) GetState(sessionID uint16) (SessionState, bool)
GetState returns the current state of a session.
func (*SessionStateTracker) IsEnabled ¶
func (sst *SessionStateTracker) IsEnabled() bool
IsEnabled returns whether state tracking is enabled.
func (*SessionStateTracker) RecordLeaseSetReceived ¶
func (sst *SessionStateTracker) RecordLeaseSetReceived(sessionID uint16, tunnelCount uint8)
RecordLeaseSetReceived records that RequestVariableLeaseSet was received.
func (*SessionStateTracker) SetState ¶
func (sst *SessionStateTracker) SetState(sessionID uint16, newState SessionState, reason string)
SetState sets the state for a session and records the transition.
func (*SessionStateTracker) StartLeaseSetWait ¶
func (sst *SessionStateTracker) StartLeaseSetWait(sessionID uint16, timeout time.Duration)
StartLeaseSetWait records that a session is waiting for RequestVariableLeaseSet.
type SessionStatus ¶
type SessionStatus int
Session Status Constants I2CP specification: SessionStatusMessage (type 20) status field values Per https://geti2p.net/spec/i2cp#sessionstatusmessage:
0 = Destroyed - The session with the given ID is terminated 1 = Created - In response to CreateSessionMessage, a new session is now active 2 = Updated - In response to ReconfigureSessionMessage 3 = Invalid - The configuration is invalid 4 = Refused - Router was unable to create the session (0.9.12+)
const ( I2CP_SESSION_STATUS_DESTROYED SessionStatus = 0 // 0 - Session destroyed I2CP_SESSION_STATUS_CREATED SessionStatus = 1 // 1 - Session created successfully I2CP_SESSION_STATUS_UPDATED SessionStatus = 2 // 2 - Session configuration updated I2CP_SESSION_STATUS_INVALID SessionStatus = 3 // 3 - Session invalid (see errors.go: ErrSessionInvalid) I2CP_SESSION_STATUS_REFUSED SessionStatus = 4 // 4 - Session creation refused (0.9.12+, see errors.go: ErrSessionRefused) )
type SignatureKeyPair ¶
type SignatureKeyPair struct {
// contains filtered or unexported fields
}
SignatureKeyPair represents an Ed25519 signature key pair. This struct is maintained for backward compatibility. New code should use Ed25519KeyPair directly.
type StateTransition ¶
type StateTransition struct {
From SessionState
To SessionState
Timestamp time.Time
Reason string
}
StateTransition records a state change for diagnostic purposes.
type Stream ¶
Stream provides I2CP-specific message serialization operations. It wraps bytes.Buffer and adds methods for reading/writing I2CP protocol data structures.
The Stream type focuses on I2CP protocol serialization including:
- Binary integer encoding (big-endian uint16/32/64)
- Length-prefixed strings
- I2CP property mappings (key=value; format)
For general binary operations outside I2CP, use encoding/binary directly.
func NewStream ¶
NewStream creates a new Stream from a byte slice. The Stream wraps a bytes.Buffer initialized with the provided data.
func NewStreamPooled ¶
NewStreamPooled creates a new Stream using a buffer from the pool. When the Stream is no longer needed, call ReleaseStream() to return the buffer. If buffer pooling is disabled, this behaves identically to NewStream().
func (*Stream) ReadMapping ¶
ReadMapping reads an I2CP property mapping from the stream. Format: [size:uint16][key1_len:1][key1][=][value1_len:1][value1][;]...[keyN_len:1][keyN][=][valueN_len:1][valueN][;]
Returns a map of key-value pairs. If the mapping is empty (size=0), returns an empty map. Returns an error if the mapping data is malformed or incomplete.
func (*Stream) ReadUint16 ¶
ReadUint16 reads a big-endian uint16 from the stream. This is commonly used for I2CP session IDs and length prefixes.
func (*Stream) ReadUint32 ¶
ReadUint32 reads a big-endian uint32 from the stream. This is commonly used for I2CP message IDs, sizes, and tunnel IDs.
func (*Stream) ReadUint64 ¶
ReadUint64 reads a big-endian uint64 from the stream. This is commonly used for I2CP timestamps.
func (*Stream) Seek ¶
Seek provides limited support for repositioning within the stream. Currently only supports Seek(0, 0) to reset to the beginning. This is used internally for I2CP message processing.
For full io.Seeker support, use bytes.Reader instead.
func (*Stream) WriteLenPrefixedString ¶
WriteLenPrefixedString writes a string prefixed by its length as a single byte. Format: [length:1 byte][string data] This limits strings to 255 bytes, which is sufficient for I2CP property keys/values.
func (*Stream) WriteMapping ¶
WriteMapping writes an I2CP property mapping to the stream. Format: [size:uint16][key1_len:1][key1][=][value1_len:1][value1][;]...[keyN_len:1][keyN][=][valueN_len:1][valueN][;]
The mapping is a collection of key=value pairs separated by semicolons. Keys are sorted alphabetically for deterministic serialization. Empty keys are skipped to avoid malformed output.
This format is used throughout I2CP for session configuration properties.
func (*Stream) WriteUint16 ¶
WriteUint16 writes a big-endian uint16 to the stream. This is commonly used for I2CP session IDs and length prefixes.
func (*Stream) WriteUint32 ¶
WriteUint32 writes a big-endian uint32 to the stream. This is commonly used for I2CP message IDs, sizes, and tunnel IDs.
func (*Stream) WriteUint64 ¶
WriteUint64 writes a big-endian uint64 to the stream. This is commonly used for I2CP timestamps.
type Tcp ¶
type Tcp struct {
// contains filtered or unexported fields
}
func (*Tcp) Connect ¶
Connect establishes a TCP or TLS connection to the I2P router. Initializes the connection address if needed, then establishes either a TLS connection (if configured) or plain TCP connection.
func (*Tcp) Disconnect ¶
func (tcp *Tcp) Disconnect()
func (*Tcp) GetProperty ¶
func (tcp *Tcp) GetProperty(property TcpProperty) string
func (*Tcp) IsConnected ¶
func (*Tcp) SetProperty ¶
func (tcp *Tcp) SetProperty(property TcpProperty, value string)
func (*Tcp) SetupTLS ¶
SetupTLS configures TLS for the TCP connection per I2CP 0.8.3+ specification. It loads client certificates, CA certificates, and configures TLS settings. The insecure parameter allows skipping certificate verification (development only).
Parameters:
- certFile: Path to client certificate file (PEM format)
- keyFile: Path to client private key file (PEM format)
- caFile: Path to CA certificate file (PEM format, optional)
- insecure: If true, skip certificate verification (NOT for production)
Returns error if certificate loading fails or TLS configuration is invalid.
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
}
type X25519KeyPair ¶
type X25519KeyPair struct {
// contains filtered or unexported fields
}
X25519KeyPair represents an X25519 key exchange key pair for modern I2P ECDH Wraps github.com/go-i2p/crypto/curve25519 types
func NewX25519KeyPair ¶
func NewX25519KeyPair() (*X25519KeyPair, error)
NewX25519KeyPair generates a new X25519 key pair for ECDH operations Delegates to github.com/go-i2p/crypto/curve25519.GenerateX25519KeyPair()
func X25519KeyPairFromPrivateKey ¶
func X25519KeyPairFromPrivateKey(privateKey [32]byte) (*X25519KeyPair, error)
X25519KeyPairFromPrivateKey creates an X25519KeyPair from just the private key. The public key is derived from the private key.
func X25519KeyPairFromStream ¶
func X25519KeyPairFromStream(stream *Stream) (*X25519KeyPair, error)
X25519KeyPairFromStream reads an X25519 key pair from a stream Uses go.step.sm/crypto/x25519 for key reconstruction and validation
func (*X25519KeyPair) AlgorithmType ¶
func (kp *X25519KeyPair) AlgorithmType() uint32
AlgorithmType returns the algorithm type constant
func (*X25519KeyPair) GenerateSharedSecret ¶
func (kp *X25519KeyPair) GenerateSharedSecret(peerPublicKey [32]byte) ([32]byte, error)
GenerateSharedSecret performs ECDH to generate a shared secret with the peer's public key Uses go.step.sm/crypto/x25519 PrivateKey.SharedKey() for ECDH
func (*X25519KeyPair) PrivateKey ¶
func (kp *X25519KeyPair) PrivateKey() [32]byte
PrivateKey returns a copy of the private key as [32]byte for backward compatibility
func (*X25519KeyPair) PublicKey ¶
func (kp *X25519KeyPair) PublicKey() [32]byte
PublicKey returns a copy of the public key as [32]byte for backward compatibility
func (*X25519KeyPair) WritePublicKeyToStream ¶
func (kp *X25519KeyPair) WritePublicKeyToStream(stream *Stream) error
WritePublicKeyToStream writes only the public key to a stream
func (*X25519KeyPair) WriteToStream ¶
func (kp *X25519KeyPair) WriteToStream(stream *Stream) error
WriteToStream writes the complete X25519 key pair to a stream
Source Files
¶
- bandwidth.go
- batching.go
- blinding_crypto.go
- buffer_pool.go
- certificate.go
- chacha20poly1305.go
- circuit_breaker.go
- client.go
- client_callbacks.go
- client_connect.go
- client_leaseset.go
- client_lookup.go
- client_messages.go
- constants.go
- create_session_sync.go
- crypto.go
- crypto_struct.go
- debug_diagnostics.go
- destination.go
- dh_psk_auth.go
- diagnostics.go
- ed25519.go
- errors.go
- i2pc.go
- lease.go
- leaseset2.go
- log.go
- logger.go
- lookup_entry.go
- message_names.go
- meta_leaseset.go
- metrics.go
- per_client_auth.go
- retry.go
- router_info.go
- send_message_flags.go
- session.go
- session_callbacks.go
- session_config.go
- session_struct.go
- signature_key_pair.go
- stream.go
- tcp.go
- utils.go
- version.go
- x25519.go
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
bandwidth-limits
command
|
|
|
context-usage
command
Package main demonstrates context-aware operations in go-i2cp
|
Package main demonstrates context-aware operations in go-i2cp |
|
debug_leaseset
command
|
|
|
diagnostics
command
Package main demonstrates go-i2cp diagnostic capabilities for troubleshooting I2CP protocol interactions, particularly useful for debugging session creation timeouts with Java I2P routers.
|
Package main demonstrates go-i2cp diagnostic capabilities for troubleshooting I2CP protocol interactions, particularly useful for debugging session creation timeouts with Java I2P routers. |
|
external-callbacks
command
|
|
|
metrics
command
|
|
|
modern-crypto
command
|
|
|
session-creation-fix
command
Package main demonstrates the CORRECT way to create I2CP sessions This example shows the fix for the "CreateSession hangs with Java I2P router" bug.
|
Package main demonstrates the CORRECT way to create I2CP sessions This example shows the fix for the "CreateSession hangs with Java I2P router" bug. |
|
signature-fix-test
command
Example program to test CreateSession signature fix This verifies that the signature is now valid according to I2CP specification
|
Example program to test CreateSession signature fix This verifies that the signature is now valid according to I2CP specification |
|
signing-keypair-usage
command
|
|
|
source-destination
command
|
|
|
tls-connection
command
|