-
Notifications
You must be signed in to change notification settings - Fork 257
LP registration #6142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
durch
wants to merge
16
commits into
develop
Choose a base branch
from
drazen/lp-reg
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
LP registration #6142
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
Implement LP (Lewes Protocol) registration flow testing in nym-gateway-probe to validate gateway LP registration capabilities alongside existing WireGuard and mixnet tests. Changes: - Add LpProbeResults struct to track LP registration test results (can_connect, can_handshake, can_register, error) - Add lp_registration_probe() function that tests full registration flow: * TCP connection to LP listener (port 41264) * Noise protocol handshake with PSK derivation * Registration request with bandwidth credentials * Registration response validation - Integrate LP test into main probe flow - runs automatically if gateway has LP address (derived from gateway IP + port 41264) - Export LpRegistrationClient from nym-registration-client for probe use - Add LP address field to TestedNodeDetails The probe tests only successful registration without additional traffic, keeping the implementation simple and focused.
* Add nymkkt with KKT convenience wrappers for nym-lp integration
Integrates nymkkt module from georgio/noise-psq branch to enable
post-quantum key distribution for nym-lp.
Changes:
- Add common/nymkkt from georgio/noise-psq (KKT protocol implementation)
- Add convenience wrapper layer (kkt.rs) with simplified API:
- request_kem_key() - Client requests gateway's KEM key
- validate_kem_response() - Client validates signed response
- handle_kem_request() - Gateway handles requests
- Add nymkkt to workspace members in root Cargo.toml
- Export kkt module in lib.rs
The KKT (Key Encapsulation Mechanism Transport) protocol enables efficient
distribution of post-quantum KEM public keys. Instead of storing large PQ
keys in the directory (1KB-500KB), we store 32-byte hashes and fetch actual
keys on-demand via this authenticated protocol.
Tests: All 5 unit tests passing (authenticated, anonymous, signature
verification, hash validation)
* feat(lp): add Ed25519 authentication to PSQ protocol
Replace basic PSQ v0 API with authenticated v1 API that includes
cryptographic authentication via Ed25519 signatures.
Changes:
- PSQ initiator now signs encapsulated keys with Ed25519 private key
- PSQ responder verifies Ed25519 signatures before deriving PSK
- Prevents MITM attacks through mutual authentication
- Fixed test helpers to use role-based Ed25519 keypair assignment
(initiator uses [1u8;32], responder uses [2u8;32])
Security: This adds a critical authentication layer to the post-quantum
PSK derivation protocol, ensuring both parties can verify each other's
identity during the handshake.
Tests: All 77 tests passing (was 11 failures, now 0)
* feat(lp): integrate PSQ post-quantum PSK derivation
Complete integration of Post-Quantum Secure (PSQ) protocol for PSK
derivation in the Lewes Protocol, replacing simple Blake3 derivation
with cryptographically secure DHKEM-based PSK establishment.
This commit encompasses three completed tasks:
- Add KKTRequest/KKTResponse message types to LpMessage enum
- Update codec to handle KKT message serialization/deserialization
- Add kkt_orchestrator.rs with high-level KKT API wrappers
- Enable key exchange orchestration for PSQ protocol
- Add set_psk() method to NoiseProtocol for dynamic PSK injection
- Integrate PSQ derivation into LpSession handshake flow
- PSQ payload embedded in first Noise message (ClientHello)
- Derive PSK using libcrux-psq before Noise handshake completion
- Add helper functions for X25519 to KEM conversions
- Add comprehensive PSQ integration tests in session_integration/
- Test PSQ handshake end-to-end flow
- Validate PSK derivation correctness between initiator/responder
- Test PSQ + Noise combined protocol operation
Dependencies:
- libcrux-psq: Post-quantum PSK protocol implementation
- libcrux-kem: Key Encapsulation Mechanism primitives
- nym-kkt: KKT key exchange protocol wrappers
- rand 0.9: Required for KKT compatibility
Security: This adds Harvest-Now-Decrypt-Later (HNDL) resistance by
combining classical ECDH with post-quantum KEM for PSK derivation.
Even if X25519 is broken by quantum computers, the PSK remains secure.
Tests: All 77 tests passing
* feat(lp): add PSQ error handling documentation and tests (nym-bbi)
Formalize the "always abort" error handling strategy for PSQ failures.
PSQ errors indicate attacks, misconfigurations, or protocol violations
that should not be silently ignored or worked around.
Changes:
- Add comprehensive error handling documentation to psk.rs module
- Add diagnostic logging with error categorization:
* CredError → warn about potential attack
* TimestampElapsed → warn about potential replay
* Other errors → log as errors
- Add 4 error scenario tests:
* test_psq_deserialization_failure
* test_handshake_abort_on_psq_failure
* test_psq_invalid_signature
* test_psq_state_unchanged_on_error
- Add log dependency to Cargo.toml
Error handling strategy: All PSQ failures abort the handshake cleanly
with no retry or fallback. This prevents silent security degradation
and ensures misconfigurations are detected early.
State guarantees: PSQ errors leave session in clean state - dummy PSK
remains, Noise HandshakeState unchanged, no partial data, no cleanup needed.
Tests: 81 tests passing (77 original + 4 new error tests)
Closes: nym-bbi
* feat(lp): add PSK injection tracking to prevent dummy PSK usage (nym-ep2)
Add safety mechanism to ensure real post-quantum PSK was injected before
allowing transport mode operations (encrypt/decrypt). This prevents
accidentally using the insecure dummy PSK [0u8; 32] if PSQ injection fails.
Changes:
- Add `psk_injected: AtomicBool` field to LpSession
- Initialize to `false` in LpSession::new()
- Set to `true` after successful PSK injection:
* Initiator: In prepare_handshake_message() after set_psk()
* Responder: In process_handshake_message() after set_psk()
- Add NoiseError::PskNotInjected error variant
- Add PSK injection checks in encrypt_data() and decrypt_data()
* Check happens before handshake completion check
* Returns PskNotInjected if flag is false
- Add comprehensive PSK injection lifecycle documentation to LpSession
- Add test_transport_fails_without_psk_injection test
- Update test_encrypt_decrypt_before_handshake to expect PskNotInjected
PSK Injection Lifecycle:
1. Session created with dummy PSK [0u8; 32] in Noise HandshakeState
2. During handshake, PSQ runs and derives real post-quantum PSK
3. Real PSK injected via set_psk() - psk_injected flag set to true
4. Handshake completes, transport mode available
5. Transport operations check psk_injected flag for safety
This is defensive programming - normal PSQ flow always injects the real PSK.
The safety check prevents transport mode if PSQ somehow fails silently or is
bypassed due to implementation bugs.
Tests: 82 tests passing (81 original + 1 new)
Closes: nym-ep2
* docs(lp): fix PSK state documentation inaccuracy
Correct error handling documentation to clarify that PSK slot 3
remains unmodified only on error, not in all cases.
Previous: "PSK slot 3 = dummy [0u8; 32] (never modified)"
Corrected: "PSK slot 3 = dummy [0u8; 32] (not modified on error)"
This is more accurate since:
- On error: PSK remains as dummy value (never injected)
- On success: PSK is replaced with real post-quantum PSK
Documentation-only change, no functional impact.
* feat(lp): add KKTExchange state to state machine for pre-handshake KEM key transfer (nym-4za)
Add KKTExchange state to LpStateMachine to properly orchestrate KKT (KEM Key Transfer)
protocol before Noise handshake begins. This enables dynamic KEM public key exchange,
allowing post-quantum KEM algorithms to be used without pre-published keys.
Changes:
- Add KKTExchange state and KKTComplete action to state machine
- Implement automatic KKT exchange on StartHandshake:
* Initiator: sends KKT request → waits for response → validates signature
* Responder: waits for request → validates → sends signed KEM key
- Update process_kkt_response() to accept Option<&[u8]> for hash validation:
* Some(hash): full KKT validation with directory hash (future)
* None: signature-only mode (current deployment)
- Add local_x25519_public() helper for responder KEM key derivation
- Update state flow: ReadyToHandshake → KKTExchange → Handshaking → Transport
- Add PSK handle storage (psk_handle) for future re-registration
- Export generate_fresh_salt() for session creation
- Update psq_responder_process_message() to return encrypted PSK handle (ctxt_B)
- Add comprehensive tests:
* test_kkt_exchange_initiator_flow
* test_kkt_exchange_responder_flow
* test_kkt_exchange_full_roundtrip
* test_kkt_exchange_close
* test_kkt_exchange_rejects_invalid_inputs
* Updated test_state_machine_simplified_flow for KKT phase
All tests passing. Ready for nym-8y5 (PSQ handshake KKT integration).
* docs(lp): add state machine and post-quantum security protocol documentation
Add comprehensive documentation of the Lewes Protocol state machine and
post-quantum security architecture to LP_PROTOCOL.md.
New sections:
- State Machine and Security Protocol overview
- Detailed state transition diagram (ReadyToHandshake → KKTExchange → Handshaking → Transport)
- Complete message sequence diagram showing KKT + PSQ + Noise flow
- KKT (KEM Key Transfer) protocol specification
- PSQ (Post-Quantum Secure PSK) protocol details
- Security guarantees and implementation status
- Algorithm choices (current X25519, future ML-KEM-768)
- Message type specifications for KKT
- Version 1.1 changelog entry documenting KKT/PSQ integration
Documentation includes:
- ASCII art state machine diagram
- Message sequence diagram with all protocol phases
- PSK derivation formulas
- Security properties checklist
- Migration path to post-quantum KEMs
- Integration details (PSQ embedded in Noise, no extra round-trips)
Related to nym-4za (KKTExchange state implementation).
* feat(lp): use KKT-authenticated KEM key in PSQ handshake (nym-8y5)
Replace direct X25519→KEM conversion with KKT-derived authenticated key
in PSQ initiator flow. This ensures PSQ uses the responder's authenticated
KEM public key obtained via KKT protocol instead of blindly converting
their X25519 key, properly completing the post-quantum security chain.
Changes:
- session.rs: Extract KEM key from KKTState::Completed in prepare_handshake_message()
- session.rs: Add set_kkt_completed_for_test() helper for test initialization
- session.rs: Update create_handshake_test_session() to initialize KKT state
- session.rs: Fix test_handshake_abort_on_psq_failure and test_psq_invalid_signature
- session_manager.rs: Add init_kkt_for_test() for integration test setup
- session_integration/mod.rs: Update tests for KKT-first flow (6 rounds total)
- session_integration/mod.rs: Fix state machine test expectations for KKTExchange state
All 87 tests passing. Unblocks nym-w8f (KKT tests) and nym-m15 (production integration).
* feat(lp): simplify API to Ed25519-only, derive X25519 internally
Refactored LP state machine to use Ed25519 keys exclusively in the public
API, with X25519 keys derived internally via RFC 7748. This simplifies the
API from 6 parameters to 4 while maintaining protocol security.
**Core API Changes:**
- LpStateMachine::new(): Removed explicit X25519 keypair parameters
- Old: new(is_initiator, local_keypair, local_ed25519_keypair,
remote_public_key, remote_ed25519_key, salt)
- New: new(is_initiator, local_ed25519_keypair, remote_ed25519_key, salt)
- X25519 keys now derived internally from Ed25519 using RFC 7748
- lp_id calculation moved inside state machine (uses derived X25519 keys)
**Protocol Changes:**
- ClientHello message extended from 65 to 97 bytes
- Now includes client_ed25519_public_key field (32 bytes)
- Required for PSQ authentication in KKT + PSQ handshake flow
- Breaking change: gateway must extract Ed25519 from ClientHello
**Gateway Updates:**
- receive_client_hello() now extracts Ed25519 public key
- LpGatewayHandshake::new_responder() accepts Ed25519 keys only
- Removed manual X25519 conversion (handled by state machine)
**Registration Client Updates:**
- LpRegistrationClient now uses Ed25519 keypairs
- Generate fresh ephemeral Ed25519 keys for LP registration
- ClientHello includes Ed25519 public key for gateway authentication
- Fixed 7 pre-existing build errors:
* mixnet_client_startup_timeout field removal
* IprClientConnect API change (async → sync)
* Error variant renames (use helper function)
* LP client key type mismatches (X25519 → Ed25519)
**Test Suite:**
- Updated 16+ test functions to use new 4-parameter constructor
- Fixed 5 integration test failures caused by lp_id mismatch
- Tests now derive X25519 from Ed25519 (matching production behavior)
- Added missing PublicKey imports in test modules
- All 87 tests passing (100% success rate)
**Implementation Details:**
- Added Ed25519RecoveryError variant to LpError enum
- Type conversion: nym_crypto X25519 → nym_lp keypair types
- Maintained backward compatibility for PSQ/KKT protocol flow
- Session manager updated to use new API signature
This change completes the Ed25519-only API migration, hiding X25519 as an
implementation detail while preserving all security properties of the
KKT-authenticated PSQ handshake protocol.
* chore: run cargo fmt
* chore: run cargo clippy --fix to resolve simple linter issues
* Basic handshake working
* Final tweaks
* Wrap PR comments, 2024
---------
Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This PR implements the Lewes Protocol (LP) registration path for direct TCP-based gateway connections, providing a more efficient alternative to mixnet-based registration while maintaining security through Noise protocol
handshake and credential verification.
What's Implemented
Server-Side (Gateway)
Client-Side (RegistrationClient)
Protocol Features
Configuration & Defaults
Architecture Changes
New Modules
Modified Components
What's Outstanding
Testing
Documentation
Future Enhancements (Not blocking)
Breaking Changes
None - LP is an additional registration path that doesn't affect existing WireGuard or Mixnet registration modes.
Performance Impact
LP registration provides:
Security Considerations
Migration Path
No migration required. Clients can opt-in to LP registration by:
This change is