mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
R3-8: bind liveness envelope to WebAuthn credential + challenge
A stolen attestation (within its 2-minute validity window) could be replayed against a different WebAuthn enrollment because the envelope only attested (userID, score, timestamp) — it said nothing about WHICH public key the user was actually enrolling. Fix: extend LivenessAttestation with two optional binding fields: credentialHash = sha256(publicKey) [base64-std] challengeId = the WebAuthn challenge being enrolled [base64url] handleBiometricEnroll computes both values from the real enrollment data (consumed challenge bytes + submitted public key) and passes them as ExpectedCredentialHash / ExpectedChallengeID to VerifyLiveness. Mismatches are always fatal. A missing binding is fatal in STRICT mode (the default) and warns-and-accepts in LAX. BindingMode is server-configured via MPC_LIVENESS_BINDING=strict|lax. Production mainnet runs STRICT — must ship the extended envelope as a deployment blocker. LAX exists solely for the rollout window; every permissive accept emits an `mpc.biometric.binding_warn` log line so operators can see rollout progress. Tests added in pkg/webauthn/liveness_test.go: - R38_AcceptsMatchingCredentialHash - R38_RejectsMismatchedCredentialHash - R38_RejectsMissingBindingStrict - R38_LaxWarnsOnMissing - R38_AcceptsMatchingChallengeID - R38_RejectsMismatchedChallengeID Full ./pkg/api/ suite green; the existing pre-R3-8 LAX-style liveness tests still pass (they supply no Expected* values → the binding path is a no-op for them).
This commit is contained in:
@@ -471,7 +471,11 @@ make e2e-test
|
||||
|
||||
31. **R2-2 CAS under Postgres**: Session consume + operation approve now use `orm.GetForUpdate` (SELECT ... FOR UPDATE) inside READ COMMITTED tx via `orm.RunInTransactionWith(IsolationReadCommitted)`. Requires `hanzoai/orm@v0.4.0`. Postgres-backed regression tests in `cas_postgres_test.go` — skipped when no Postgres available, `TEST_PG_DSN` overrides DSN. `pkg/db.New` now accepts `postgres://...` DSNs alongside SQLite.
|
||||
|
||||
32. **R2-3 Tightened API-key gate**: `requireRoleOrAPIPermission([]string{"owner","admin","signer"}, "mpc:sign")` replaces `requireRole("owner","admin","signer","api")` on `/v1/mpc/sign` and `/v1/mpc/settlement/sign`. Role `api` passes only if the key holds the named permission (or `*`). A bare API key with permissions=[] is rejected.
|
||||
32. **R2-3 Tightened API-key gate**: `requireRoleOrAPIPermission([]string{"owner","admin","signer"}, "mpc:sign")` replaces `requireRole("owner","admin","signer","api")` on `/v1/mpc/sign` and `/v1/mpc/settlement/sign`. Role `api` passes only if the key holds the named permission. A bare API key with permissions=[] is rejected.
|
||||
|
||||
33. **R3-2 No `*` wildcard in API-key permissions**: `hasPermission` no longer honors `*`. Every API key must enumerate explicit permissions. Tests `TestRequireRoleOrAPIPermission_WildcardRejectedOnSensitive` + `TestRequirePermission_WildcardRejected` assert `permissions=["*"]` is REJECTED for every sensitive name (`mpc:sign`, `mpc:settlement:sign`, `mpc:operations:approve`, `mpc:wallet:sweep`, `mpc:policy:write`, plus `trade:submit`). Breaking change: re-issue keys with explicit permissions; bump to v1.7.0.
|
||||
|
||||
34. **R3-8 Liveness envelope bound to enrollment**: `LivenessAttestation` now carries `credentialHash = sha256(pubKey)` and/or `challengeId`. `handleBiometricEnroll` passes expected values to `VerifyLiveness` so a stolen envelope cannot be replayed against a different WebAuthn public key. Mode toggle via `MPC_LIVENESS_BINDING=strict|lax` (default `strict`). **Blocker for mainnet biometric enroll**: must ship the extended envelope; while in LAX the server emits a `mpc.biometric.binding_warn` log on every permissive accept. Tests in `pkg/webauthn/liveness_test.go` — matching-hash accept, mismatch-rejects, strict-rejects-missing, lax-warns-missing, challengeId accept/reject.
|
||||
|
||||
### Consensus-Embedded Transport (Jan 2026)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user