You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
DONE
NOTE: Not in use but can be selected via a parameter
Issue 2: Static Key Storage for IK Pattern
Issue Location
File:libp2p/security/noise/transport.py:35 Class:Transport TODO Comment:# TODO: A storage of seen noise static keys for pattern IK?
Current Status Analysis
Current Implementation
The Transport class currently doesn't implement noise pipes or IK pattern support:
classTransport(ISecureTransport):
libp2p_privkey: PrivateKeynoise_privkey: PrivateKeylocal_peer: IDearly_data: bytes|Nonewith_noise_pipes: bool# NOTE: Implementations that support Noise Pipes must decide whether to use# an XX or IK handshake based on whether they possess a cached static# Noise key for the remote peer.# TODO: A storage of seen noise static keys for pattern IK?def__init__(
self,
libp2p_keypair: KeyPair,
noise_privkey: PrivateKey,
early_data: bytes|None=None,
with_noise_pipes: bool=False,
) ->None:
self.libp2p_privkey=libp2p_keypair.private_keyself.noise_privkey=noise_privkeyself.local_peer=ID.from_pubkey(libp2p_keypair.public_key)
self.early_data=early_dataself.with_noise_pipes=with_noise_pipesifself.with_noise_pipes:
raiseNotImplementedErrordefget_pattern(self) ->IPattern:
ifself.with_noise_pipes:
raiseNotImplementedErrorelse:
returnPatternXX(
self.local_peer,
self.libp2p_privkey,
self.noise_privkey,
self.early_data,
)
The Problem
Noise Pipes Not Implemented: The feature is disabled with NotImplementedError
Missing IK Pattern: No implementation of the IK handshake pattern
No Key Caching: No storage mechanism for static keys
Performance Impact: Can't optimize handshakes with known peers
What Must Be Done
Required Changes
Static Key Storage: Implement a cache for remote peer static keys
IK Pattern Implementation: Create PatternIK class
Pattern Selection Logic: Choose between XX and IK based on cached keys
Key Management: Handle key storage, retrieval, and expiration
Implementation Options
Option A: Simple In-Memory Key Cache
importtimefromtypingimportDict, OptionalclassTransport(ISecureTransport):
libp2p_privkey: PrivateKeynoise_privkey: PrivateKeylocal_peer: IDearly_data: bytes|Nonewith_noise_pipes: bool_static_key_cache: Dict[ID, tuple[PublicKey, float]] # peer_id -> (key, timestamp)def__init__(
self,
libp2p_keypair: KeyPair,
noise_privkey: PrivateKey,
early_data: bytes|None=None,
with_noise_pipes: bool=False,
cache_ttl: int=3600, # 1 hour default
) ->None:
self.libp2p_privkey=libp2p_keypair.private_keyself.noise_privkey=noise_privkeyself.local_peer=ID.from_pubkey(libp2p_keypair.public_key)
self.early_data=early_dataself.with_noise_pipes=with_noise_pipesself.cache_ttl=cache_ttlself._static_key_cache= {}
def_get_cached_static_key(self, peer_id: ID) ->Optional[PublicKey]:
"""Get cached static key for a peer if available and not expired."""ifpeer_idnotinself._static_key_cache:
returnNonekey, timestamp=self._static_key_cache[peer_id]
iftime.time() -timestamp>self.cache_ttl:
delself._static_key_cache[peer_id]
returnNonereturnkeydef_cache_static_key(self, peer_id: ID, static_key: PublicKey) ->None:
"""Cache a static key for a peer."""self._static_key_cache[peer_id] = (static_key, time.time())
defget_pattern(self, remote_peer: ID|None=None) ->IPattern:
ifnotself.with_noise_pipes:
returnPatternXX(
self.local_peer,
self.libp2p_privkey,
self.noise_privkey,
self.early_data,
)
# Check if we have a cached static key for IK patternifremote_peerandself._get_cached_static_key(remote_peer):
returnPatternIK(
self.local_peer,
self.libp2p_privkey,
self.noise_privkey,
self.early_data,
remote_peer,
self._get_cached_static_key(remote_peer),
)
else:
returnPatternXX(
self.local_peer,
self.libp2p_privkey,
self.noise_privkey,
self.early_data,
)
asyncdefsecure_outbound(self, conn: IRawConnection, peer_id: ID) ->ISecureConn:
pattern=self.get_pattern(peer_id)
secure_conn=awaitpattern.handshake_outbound(conn, peer_id)
# Cache the static key if using XX pattern (we learned it)ifisinstance(pattern, PatternXX):
# Extract static key from the handshakestatic_key=self._extract_static_key_from_handshake(pattern)
ifstatic_key:
self._cache_static_key(peer_id, static_key)
returnsecure_conn
Option B: Persistent Key Storage
importsqlite3importjsonfromtypingimportOptionalclassStaticKeyStorage:
def__init__(self, db_path: str="noise_static_keys.db"):
self.db_path=db_pathself._init_db()
def_init_db(self) ->None:
"""Initialize the database schema."""withsqlite3.connect(self.db_path) asconn:
conn.execute(""" CREATE TABLE IF NOT EXISTS static_keys ( peer_id TEXT PRIMARY KEY, static_key BLOB, created_at INTEGER, last_used INTEGER, use_count INTEGER DEFAULT 0 ) """)
defget_static_key(self, peer_id: ID) ->Optional[PublicKey]:
"""Get cached static key for a peer."""withsqlite3.connect(self.db_path) asconn:
cursor=conn.execute(""" SELECT static_key, created_at FROM static_keys WHERE peer_id = ? """, (str(peer_id),))
row=cursor.fetchone()
ifrow:
static_key_bytes, created_at=row# Check if key is not too old (e.g., 24 hours)iftime.time() -created_at<86400:
# Update usage statisticsconn.execute(""" UPDATE static_keys SET last_used = ?, use_count = use_count + 1 WHERE peer_id = ? """, (int(time.time()), str(peer_id)))
returnself._deserialize_public_key(static_key_bytes)
returnNonedefstore_static_key(self, peer_id: ID, static_key: PublicKey) ->None:
"""Store a static key for a peer."""withsqlite3.connect(self.db_path) asconn:
conn.execute(""" INSERT OR REPLACE INTO static_keys (peer_id, static_key, created_at, last_used) VALUES (?, ?, ?, ?) """, (
str(peer_id),
static_key.to_bytes(),
int(time.time()),
int(time.time())
))
defcleanup_expired_keys(self, max_age: int=86400) ->None:
"""Remove expired keys from storage."""withsqlite3.connect(self.db_path) asconn:
conn.execute(""" DELETE FROM static_keys WHERE ? - created_at > ? """, (int(time.time()), max_age))
classTransport(ISecureTransport):
def__init__(
self,
libp2p_keypair: KeyPair,
noise_privkey: PrivateKey,
early_data: bytes|None=None,
with_noise_pipes: bool=False,
key_storage: StaticKeyStorage|None=None,
) ->None:
# ... existing initialization ...self.key_storage=key_storageorStaticKeyStorage()
self.with_noise_pipes=with_noise_pipesdefget_pattern(self, remote_peer: ID|None=None) ->IPattern:
ifnotself.with_noise_pipes:
returnPatternXX(...)
# Check persistent storage for static keyifremote_peer:
cached_key=self.key_storage.get_static_key(remote_peer)
ifcached_key:
returnPatternIK(
self.local_peer,
self.libp2p_privkey,
self.noise_privkey,
self.early_data,
remote_peer,
cached_key,
)
returnPatternXX(...)
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
TODO Analysis: Noise Security Issues
Last review: August 2025
Overview
This document analyzes two TODO/FIXME issues in the noise security module:
Message prefix behavior in Go -DONElibp2p/security/noise/io.py:44
Static key storage for IK pattern -DEPRECATED in specs https://github.com/libp2p/specs/tree/master/noise#handshake-patternlibp2p/security/noise/transport.py:35
Issue 1: Message Prefix Behavior in Go
DONE
NOTE: Not in use but can be selected via a parameter
Issue 2: Static Key Storage for IK Pattern
Issue Location
File:
libp2p/security/noise/transport.py:35
Class:
Transport
TODO Comment:
# TODO: A storage of seen noise static keys for pattern IK?
Current Status Analysis
Current Implementation
The
Transport
class currently doesn't implement noise pipes or IK pattern support:The Problem
NotImplementedError
What Must Be Done
Required Changes
PatternIK
classImplementation Options
Option A: Simple In-Memory Key Cache
Option B: Persistent Key Storage
Option C: Advanced PatternIK Implementation
Impact Analysis
Summary and Recommendations
Priority Order
Implementation Strategy
Testing Requirements
Documentation Needs
Beta Was this translation helpful? Give feedback.
All reactions