From 5b3d7b515bf954c342005be91593f11547807d90 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 13 Jun 2026 15:27:57 -0400 Subject: [PATCH] inbound.randomKey and outbound.randomKey I2CP params --- libi2pd/Destination.cpp | 16 +++++++++++++++- libi2pd/Destination.h | 3 ++- libi2pd/IdentMetrics.cpp | 23 ++++++++++++++++------- libi2pd/IdentMetrics.h | 3 +++ libi2pd/TunnelPool.cpp | 10 ++++++++++ libi2pd/TunnelPool.h | 2 ++ libi2pd_client/ClientContext.cpp | 4 ++++ 7 files changed, 52 insertions(+), 9 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 6bd8acfe..635c70d0 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -41,7 +41,7 @@ namespace client int numTags = DEFAULT_TAGS_TO_SEND; bool isHighBandwidth = true; std::shared_ptr > explicitPeers; - std::string_view explicitPeersStr, trustedRoutersStr; + std::string_view explicitPeersStr, trustedRoutersStr, inboundRandomKeyStr, outboundRandomKeyStr; try { if (params) @@ -63,6 +63,8 @@ namespace client } explicitPeersStr = (*params)[I2CP_PARAM_EXPLICIT_PEERS]; trustedRoutersStr = (*params)[I2CP_PARAM_TRUSTED_ROUTERS]; + inboundRandomKeyStr = (*params)[I2CP_PARAM_INBOUND_RANDOM_KEY]; + outboundRandomKeyStr = (*params)[I2CP_PARAM_OUTBOUND_RANDOM_KEY]; m_Nickname = (*params)[I2CP_PARAM_INBOUND_NICKNAME]; if (m_Nickname.empty ()) // try outbound m_Nickname = (*params)[I2CP_PARAM_OUTBOUND_NICKNAME]; @@ -108,6 +110,18 @@ namespace client m_Pool->SetExplicitPeers (i2p::data::ExtractIdentHashes (explicitPeersStr)); if (!trustedRoutersStr.empty ()) m_Pool->SetTrustedRouters (i2p::data::ExtractIdentHashes (trustedRoutersStr)); + if (!inboundRandomKeyStr.empty ()) + { + uint8_t key[32]; // might be 32 bytes, but only first 16 bytes are used + if (i2p::data::Base64ToByteStream (inboundRandomKeyStr, key, 32) >= 16) + m_Pool->SetInboundPeerOrderingKey (key); + } + if (!outboundRandomKeyStr.empty ()) + { + uint8_t key[32]; // might be 32 bytes, but only first 16 bytes are used + if (i2p::data::Base64ToByteStream (outboundRandomKeyStr, key, 32) >= 16) + m_Pool->SetOutboundPeerOrderingKey (key); + } if(params) { int maxLatency = 0; diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index e4f2968d..579ba7d4 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -65,7 +65,8 @@ namespace client const int DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE = 0; const char I2CP_PARAM_EXPLICIT_PEERS[] = "explicitPeers"; const char I2CP_PARAM_TRUSTED_ROUTERS[] = "trustedRouters"; - const int STREAM_REQUEST_TIMEOUT = 60; //in seconds + const char I2CP_PARAM_INBOUND_RANDOM_KEY[] = "inbound.randomKey"; + const char I2CP_PARAM_OUTBOUND_RANDOM_KEY[] = "outbound.randomKey"; const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend"; const int DEFAULT_TAGS_TO_SEND = 40; const char I2CP_PARAM_RATCHET_INBOUND_TAGS[] = "crypto.ratchet.inboundTags"; diff --git a/libi2pd/IdentMetrics.cpp b/libi2pd/IdentMetrics.cpp index c90cd981..671cc1ec 100644 --- a/libi2pd/IdentMetrics.cpp +++ b/libi2pd/IdentMetrics.cpp @@ -45,13 +45,7 @@ namespace data PeerOrdering::PeerOrdering () { - RAND_bytes (m_PeerOrderingKey, 16); -#if OPENSSL_SIPHASH - EVP_PKEY * sipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, m_PeerOrderingKey, 16); - m_MDCtx = EVP_MD_CTX_create (); - EVP_DigestSignInit (m_MDCtx, nullptr, nullptr, nullptr, sipKey); - EVP_PKEY_free (sipKey); -#endif + SetKey (nullptr); } PeerOrdering::~PeerOrdering () @@ -61,6 +55,21 @@ namespace data #endif } + void PeerOrdering::SetKey (const uint8_t * key) + { + if (key) + memcpy (m_PeerOrderingKey, key, 16); + else + RAND_bytes (m_PeerOrderingKey, 16); +#if OPENSSL_SIPHASH + if (m_MDCtx) EVP_MD_CTX_destroy (m_MDCtx); // delete previous + EVP_PKEY * sipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, m_PeerOrderingKey, 16); + m_MDCtx = EVP_MD_CTX_create (); + EVP_DigestSignInit (m_MDCtx, nullptr, nullptr, nullptr, sipKey); + EVP_PKEY_free (sipKey); +#endif + } + int PeerOrdering::CalculatePeerOrderingGroup (const IdentHash& routerIdent) { uint8_t hash[16]; diff --git a/libi2pd/IdentMetrics.h b/libi2pd/IdentMetrics.h index d69735bb..ec4f38a1 100644 --- a/libi2pd/IdentMetrics.h +++ b/libi2pd/IdentMetrics.h @@ -47,6 +47,9 @@ namespace data ~PeerOrdering (); void CleanUp (uint64_t ts); + void SetKey (const uint8_t * key); + const Tag<16>& GetKey () const { return m_PeerOrderingKey; } + int GetPeerOrderingGroup (const IdentHash& routerIdent); bool IsFirstHop (const IdentHash& routerIdent) { return !GetPeerOrderingGroup (routerIdent); }; bool IsLastHop (const IdentHash& routerIdent) { return GetPeerOrderingGroup (routerIdent) & 0x02; }; // IBGW or OBEP diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 9f376435..2115ae24 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -89,6 +89,16 @@ namespace tunnel m_TrustedRouters.swap (routers); } + void TunnelPool::SetInboundPeerOrderingKey (const uint8_t * key) + { + m_InboundPeerOrdering.SetKey (key); + } + + void TunnelPool::SetOutboundPeerOrderingKey (const uint8_t * key) + { + m_OutboundPeerOrdering.SetKey (key); + } + void TunnelPool::DetachTunnels () { { diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index bf797be2..bb1d44b5 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -70,6 +70,8 @@ namespace tunnel void SetLocalDestination (std::shared_ptr destination) { m_LocalDestination = destination; }; void SetExplicitPeers (std::vector explicitPeers); void SetTrustedRouters (std::vector routers); + void SetInboundPeerOrderingKey (const uint8_t * key); + void SetOutboundPeerOrderingKey (const uint8_t * key); void CreateTunnels (); void TunnelCreated (std::shared_ptr createdTunnel); diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index a4da26c9..9cabe30a 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -521,6 +521,10 @@ namespace client if (trustedRouters.length () > 0) options.Insert (I2CP_PARAM_TRUSTED_ROUTERS, trustedRouters); std::string ratchetInboundTags = GetI2CPStringOption(section, I2CP_PARAM_RATCHET_INBOUND_TAGS, ""); if (ratchetInboundTags.length () > 0) options.Insert (I2CP_PARAM_RATCHET_INBOUND_TAGS, ratchetInboundTags); + std::string inboundRandomKey = GetI2CPStringOption(section, I2CP_PARAM_INBOUND_RANDOM_KEY, ""); + if (inboundRandomKey.length () > 0) options.Insert (I2CP_PARAM_INBOUND_RANDOM_KEY, inboundRandomKey); + std::string outboundRandomKey = GetI2CPStringOption(section, I2CP_PARAM_OUTBOUND_RANDOM_KEY, ""); + if (outboundRandomKey.length () > 0) options.Insert (I2CP_PARAM_OUTBOUND_RANDOM_KEY, outboundRandomKey); } void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, i2p::util::Mapping& options) const