Commit 6dfedb9
F-A1 Phase 1: derive_key_argon2id_with_salt (Rust crypto + FFI)
Adds the cryptographic primitive and the FFI entry point that Mode B
sign-up will rely on. See issue #14 for the full design context.
The existing `derive_key_argon2id(context, input)` uses the `context`
bytes as the Argon2 salt — which is a constant string for FxFiles
(`"fula-files-v1"`). Every input component (`provider:sub:email`) is
a public identity attribute, so anyone who obtains a single artifact
carrying all three computes the master key in one Argon2id invocation
— that is the F-A1 finding. The fix is to add a Mode B opt-in that
introduces a per-user random salt and a user-entered seed.
This commit lands the crypto + FFI side only:
- `fula_crypto::hashing::derive_key_argon2id_with_salt(context, input, salt)`:
new function taking an explicit salt. Internally it BLAKE3-hashes
`(context || 0x00 || salt)` to produce a 16-byte effective salt for
Argon2, preserving both domain separation (context is consumed) and
cross-platform consistency (effective salt is always 16 bytes
regardless of caller-salt length).
- `derive_key_argon2id_with_salt_checked` is the non-panicking variant
returning `Result<[u8; 32], &'static str>` for short-salt rejection.
- 7 unit tests cover: basic shape, distinct salts → distinct keys,
distinct contexts → distinct keys, determinism, short-salt rejection,
panic-on-short-salt convenience variant, and the explicit
non-equivalence to the legacy function (so Mode A and Mode B never
share a derived key even given byte-equivalent inputs — Mode B
users go through the rotation).
- `fula_flutter::api::encrypted::derive_key_with_salt(context, input, salt)`:
additive FFI surface that delegates to the new crypto function and
surfaces the short-salt error as a `Result<Vec<u8>, String>`.
Mode A users are not affected — the legacy `derive_key_argon2id` and
the legacy `derive_key` FFI are kept in place and unchanged. A Mode A
user's derivation continues to produce the same bytes as before.
What this commit does NOT do (Phase 1.5 follow-up):
- Regenerate the `packages/fula_client/lib/src` Dart bindings — the
dev environment needs LLVM / libclang for `flutter_rust_bridge_codegen`
to complete (ffigen step). The Rust FFI is in place; once codegen is
run on an LLVM-equipped dev environment, the Dart binding
`deriveKeyWithSalt` will appear in `encrypted.dart` and the
FxFiles app can call it.
- FxFiles `auth_service.dart` Mode B service-layer wiring — gated on
the Dart binding being available. The audit-findings doc records
the call-site changes; once the binding is generated, applying them
is mechanical.
- Server-side derivation-profile API for cross-device — Phase 2,
to be sequenced after the client-side Mode B opt-in is functional.
- UI screens (tier-action layout per Gemini advisor's UX review,
partial mnemonic verification, less-secure / recommended labels) —
Phase 2.
What ships in this commit IS safe in isolation: the new function is
additive, has no callers in production paths yet, and is exercised
only by unit tests. Mode A users see no behavior change.
Refs:
- Audit finding F-A1 in fula-client-audit-findings.md
- Issue #14 (the design + phasing)
- Gemini advisor UX review (2026-05-18) — informs Phase 2 UI
- Codex advisor correctness review (2026-05-18) — confirmed
`derive_key_with_salt` as the right FFI shape (over encoding salt
in input) and the staged-migration pattern for the eventual A→B
rotation
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>1 parent 45cf90c commit 6dfedb9
2 files changed
Lines changed: 207 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
257 | 257 | | |
258 | 258 | | |
259 | 259 | | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
260 | 347 | | |
261 | 348 | | |
262 | 349 | | |
| |||
387 | 474 | | |
388 | 475 | | |
389 | 476 | | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
390 | 560 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
275 | 275 | | |
276 | 276 | | |
277 | 277 | | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
278 | 315 | | |
279 | 316 | | |
280 | 317 | | |
| |||
0 commit comments