A Python port of the Invisible Internet Project (I2P)

Crypto Implementation Audit Checklist#

Last audited: 2026-03-23 Auditor: Claude (automated) + manual review


1. Constant-Time Comparisons#

Target files: i2p_crypto/chacha20.py, i2p_crypto/aes_cbc.py, i2p_crypto/hmac_generator.py, i2p_crypto/eddsa.py, i2p_crypto/dsa.py, i2p_crypto/noise.py, i2p_crypto/garlic_crypto.py, i2p_data/i2np_codec.py

Check: Every MAC/tag/signature/hash verification uses hmac.compare_digest().

Location Pattern Status
hmac_generator.py:63 hmac.compare_digest() PASS
password.py:31 secrets.compare_digest() PASS
console/auth.py:28 secrets.compare_digest() PASS
garlic_crypto.py:257 hmac.compare_digest() on SHA-256 hash PASS (fixed 2026-03-23)
i2np_codec.py:80 hmac.compare_digest() on checksum byte PASS (fixed 2026-03-23)
dsa.py, eddsa.py Delegated to cryptography library verify() PASS
noise.py CipherState Delegated to ChaCha20Poly1305.decrypt() PASS

Result: PASS -- All comparisons on security-sensitive data use constant-time functions.


2. Key Zeroization#

Target files: i2p_crypto/x25519.py, i2p_crypto/noise.py, i2p_crypto/hkdf.py, i2p_data/session_key_manager.py

Check: Ephemeral keys stored in bytearray, explicitly zeroed after use.

Location Key Type Storage Zeroed? Status
noise.py:32 CipherState key bytes (immutable) No KNOWN LIMITATION
noise.py:162 Ephemeral private key bytes tuple No KNOWN LIMITATION
noise.py:360 _x25519_private bytes No KNOWN LIMITATION
hkdf.py:20-21 Output buffers bytearray No explicit zeroing ADVISORY
session_key_manager.py:103 Session keys bytes No KNOWN LIMITATION

Result: ADVISORY -- Python's immutable bytes type makes key zeroization impossible without switching to bytearray. This is a language-level limitation. The cryptography library handles its own key zeroization in C. For pure-Python key material, use bytearray with explicit zeroing in finally blocks.

Note: Key zeroization in Python is best-effort. The garbage collector may retain copies, and bytearray zeroing can be optimized away. For production deployments, rely on the cryptography library's C-level key handling.


3. CSPRNG Usage#

Target files: i2p_crypto/, i2p_transport/

Check: All randomness sourced from os.urandom() or secrets.*.

Location Function Source Status
elgamal.py:38-41 Key generation os.urandom() PASS
garlic_crypto.py:19-20 Padding/tags os.urandom() PASS
ssu2_handshake.py Connection IDs os.urandom(8) PASS
ssu2_server.py Nonces os.urandom(4) PASS
ntcp2_real_handshake.py Padding os.urandom() PASS
ssu2_connection.py:194 Challenge data os.urandom(8) PASS

Result: PASS -- Zero uses of random.* in crypto or transport modules.


4. No Secrets in Logs#

Target: All files in i2p_crypto/, i2p_transport/, i2p_data/

Check: No logging.*, print(), repr() calls that include key material.

Location Log Content Status
ssu2_server.py Addresses, packet sizes PASS
manager.py Peer hash prefix (first 8 bytes only) PASS
upnp.py URLs only PASS

Result: PASS -- No key material found in any logging statements.


5. Nonce Management#

Target files: NTCP2 and SSU2 frame encryption in i2p_transport/

Check: Nonce counters increment monotonically, overflow detection, separate nonce spaces.

Check Location Status
Monotonic increment (Noise) noise.py:51,60 PASS -- _n += 1 after each op
Overflow detection (Noise) noise.py:48,57 PASS (fixed 2026-03-23) -- checks _n >= MAX_NONCE
Overflow detection (SSU2) ssu2_connection.py:119 PASS (fixed 2026-03-23) -- checks >= 0xFFFFFFFF
Separate nonce spaces ssu2_connection.py:65-67 PASS -- send/recv use separate CipherState
Nonce construction (SSU2) ssu2_connection.py:105-107 PASS -- 12-byte nonce from packet number

Result: PASS -- All nonce management issues addressed.


6. AEAD Correctness#

Target files: i2p_crypto/chacha20.py, NTCP2/SSU2 frame processing

Check: AD parameter includes header bytes; decryption returns no partial plaintext on auth failure.

Check Location Status
AD binding (SSU2) ssu2_connection.py:127,170 PASS -- header bound as AD
AD binding (NTCP2) ntcp2_real_connection.py:81,103 PASS -- empty AD (per NTCP2 data phase spec)
Atomic decryption failure cryptography library PASS -- InvalidTag raised, no partial plaintext
Nonce increment on failure noise.py:60 PASS -- _n += 1 only reached after successful decrypt

Result: PASS -- AEAD semantics correct.


7. HKDF Usage#

Target: i2p_crypto/hkdf.py, i2p_crypto/noise.py

Check: Two-phase (Extract + Expand) usage; info parameters are protocol-specific strings.

Check Location Status
Extract + Expand hkdf.py PASS -- separate extract() and expand() functions
Protocol-specific info noise.py MixKey/MixHash PASS -- chaining key derived per Noise spec
Output length check hkdf.py PASS -- expand() output <= 255 * HashLen

Result: PASS


8. Integer Overflow Masking#

Target: i2p_crypto/siphash.py, nonce counters

Check: All arithmetic ported from Java applies explicit masks.

Check Location Status
64-bit mask in SipHash siphash.py:9,14,66,75,79 PASS -- & MASK64 on all operations
IV masking siphash.py:98 PASS -- iv & MASK64 on init
SipHash return siphash.py:61 PASS -- (v0 ^ v1 ^ v2 ^ v3) & MASK64

Result: PASS -- All Java overflow semantics correctly ported with explicit masks.


9. String Encoding#

Target: RouterInfo properties, address book, SU3 metadata

Check: All string-to-bytes conversions use explicit .encode('utf-8').

Check Status
RouterInfo encoding PASS -- explicit UTF-8 in data serialization
Password hashing PASS -- password.encode("utf-8")
Console auth PASS -- explicit UTF-8 encoding

Result: PASS


Summary#

Section Result Fixes Applied
1. Constant-time comparisons PASS 2 fixes (garlic_crypto, i2np_codec)
2. Key zeroization ADVISORY Language limitation documented
3. CSPRNG usage PASS None needed
4. No secrets in logs PASS None needed
5. Nonce management PASS 2 fixes (noise overflow, SSU2 overflow)
6. AEAD correctness PASS None needed
7. HKDF usage PASS None needed
8. Integer overflow masking PASS None needed
9. String encoding PASS None needed

Overall: 8/9 PASS, 1 ADVISORY (key zeroization -- Python language limitation) Fixes applied: 4 security hardening changes in this audit cycle