Clone this repository
For self-hosted knots, clone URLs may differ based on your setup.
Download tar.gz
- Replace branching GF(2^8) reduction with branchless mask:
(a as i8 >> 7) as u8 selects 0x1b without branching on secret bits
- Add upper-bound index check (> 3) in combine_shares; silent wrong
reconstruction on out-of-range indices was not caught before
- Switch fill_bytes -> try_fill_bytes so RNG failure returns
CryptoError::SecretSharing instead of panicking
- Remove #[derive(Clone)] from ShamirShare — no call site uses it and
Clone on a secret-bearing type is inconsistent with P256Keypair
- Expand combine_with_index_zero_fails to test both argument positions
- Add combine_with_index_out_of_range_fails test (index: 4)
- Expand gf_mul_is_commutative to exhaustive 256×256 check
- Update gf_mul/gf_inv doc comments: describe branchless reduction,
fix "repeated squaring" -> "binary exponentiation (square-and-multiply)",
add standard -> GF(2^8) Lagrange derivation step
Adds split_secret and combine_shares to crates/crypto using GF(2^8)
arithmetic (AES irreducible polynomial 0x11b). Any 2 of the 3 returned
shares reconstruct the original 32-byte secret; a single share reveals
nothing (information-theoretic security). Share data is zeroized on drop.
Closes MM-93
- Fix 1: Replace wrong sqlx error source for corrupt migration version. Use
Protocol(format!(...)) instead of RowNotFound to accurately describe the
i64-to-u32 conversion failure.
- Fix 2: Remove InvalidKeyId from CryptoError variants list in CLAUDE.md (never
implemented).
- Fix 3: Rename three test functions to match their assertions:
unsupported_algorithm_returns_422, empty_algorithm_returns_422,
missing_algorithm_field_returns_422.
- Fix 4: Add test for null algorithm field. Null deserialization returns 400
(Bad Request) from Axum's default JSON rejection, distinct from missing/invalid
enum variants (422).
- Fix 5: Add key_id context to DB insert error log for better debugging when
signing key persistence fails.
- Fix 6: Add comment explaining why Sensitive<T> has pub T field — deliberate
design choice to make raw value access visible in source for code review.
- Fix #5: Config.signing_key_master_key leaks via Debug and clone
- Wrap signing_key_master_key in Sensitive<Zeroizing<[u8; 32]>>
- Adds Sensitive newtype that redacts Debug output to "***"
- Zeroizing ensures key bytes are securely zeroized on drop
- Never copies key into non-zeroizing allocation
- Fix #6: CreateSigningKeyRequest.algorithm should be one-variant enum
- Replace Option<String> with Algorithm enum (single P256 variant)
- Serde validates at deserialization time, not runtime
- Remove dead runtime algorithm matching code
- Updated tests to expect 422 (Unprocessable Entity) for invalid enum
- Fix #7: Remove dead CryptoError::InvalidKeyId variant
- Variant was never constructed in this PR
- Fix #8: Wrap raw_bytes in Zeroizing in keys.rs
- Ensures intermediate GenericArray from secret_key.to_bytes() is zeroized
- Guards against future changes to p256 library behavior
- Fix #9: Add PRAGMA table_info test for V003 relay_signing_keys columns
- Validates exact column order and names: id, algorithm, public_key,
private_key_encrypted, created_at
- Fix #10: Add V003 PRIMARY KEY uniqueness constraint test
- Verifies duplicate id inserts fail with constraint violation
- Fix #11: Introduce DidKeyUri newtype for P256Keypair.key_id
- Prevents silent positional swap bugs in SQL binds and API responses
- Type-safe distinction between key_id (did:key:z...) and public_key (z...)
- Converts to string for DB inserts and JSON responses
Changes:
- crates/common: Add zeroize dependency, Sensitive<T> wrapper, export it
- crates/crypto: Add DidKeyUri newtype, remove InvalidKeyId CryptoError variant
- crates/relay: Add zeroize dependency, update handler to use new types, add V003 tests
- Issue #1 (Critical): Replace non-constant-time Bearer token comparison with subtle::ConstantTimeEq to prevent timing attacks in create_signing_key.rs:57
- Issue #2 (Critical): Move zeroize and subtle dependencies to [workspace.dependencies] in root Cargo.toml; update crates to use { workspace = true } per project conventions
- Issue #3 (High): Fix migration infrastructure to return DbError instead of silently mapping corrupt schema_migrations version numbers to 0; now propagates parse errors with ? operator in mod.rs:99-107
- Issue #4 (High): Add sentinel field signing_key_master_key_toml_sentinel to RawConfig to detect and reject misconfigured operators who set the security-sensitive field in relay.toml instead of env var EZPDS_SIGNING_KEY_MASTER_KEY; includes validation check and regression test in config.rs