# Shade V3.5 — Android Parity & Cross-Platform CI **Status:** Done (kryptografisk lag + CI-gate). Android-KeystoreStorage og scrypt/argon2id-paritet er post-GA-arbeid sporet i `android/shade-android/ROADMAP-ANDROID.md` — ikke en 4.0 GA-blocker. **Effort:** XL (2–4 måneder, parallelliserbar) **Forrige:** V3.1 **Adresserer:** V2.1 §3 --- ## Mål Gjør Kotlin-implementasjonen **byte-kompatibel** med TS-implementasjonen, og forsegle paritet via **CI-gate** som kjører delte test-vectors i begge språk. Ingen "production"-label på Android før ratchet + proto + streams 0x11 er grønne. --- ## Scope ### Inn — paritet-sjekkpunkter (eksplisitt) 1. **KDF-chain** — root key + chain key derivasjoner. Vector: `test-vectors/kdf-chain.json`. 2. **HKDF** — labels for `info`-felt. Vector: `test-vectors/hkdf.json`. 3. **X3DH** — full agreement med samme bundles. Vector: `test-vectors/x3dh.json`. 4. **Ratchet message** — encrypt/decrypt roundtrip (legg til vector). 5. **Fingerprint** — 60-digit safety number. Vector: `test-vectors/fingerprint.json`. 6. **Wire format 0x02** — encode/decode. Vector: `test-vectors/wire-format.json`. 7. **Streams 0x11** — multi-lane chunk encryption (M-Cross 3, ikke i M-Cross 1). 8. **Backup-format** — passphrase-basert KDF + AES-GCM payload. ### Inn — milestoner - **M-Cross 1 ✅** — keys + HKDF + X3DH + fingerprint. - **M-Cross 2 ✅** — ratchet step (encrypt + decrypt roundtrip) + wire 0x02 (RatchetMessage + PreKeyMessage med/uten OTPK). Vector-versjon `2`. - **M-Cross 3 ✅** — streams 0x11 (KDF, deterministic chunk nonce/AAD, wire 0x11 encode/decode). End-to-end socket interop pending; ikke gating-blokker. - **M-Cross 4 ✅** — backup-format HKDF + AEAD, gruppe sender-keys (kdfChainKey + Ed25519 sign(aad ‖ ct)), storage-HKDF (storageKey, fieldKey, rowNonce). Gjenstående: scrypt master-key (Bouncy Castle), argon2id-bytte, Android-KeystoreStorage som søsken-modul. ### Inn — CI - Gitea Actions matrix-job: - Bun-runner kjører `bun test:vectors` mot `test-vectors/*.json`. - Gradle-runner kjører `./gradlew vectorTests` mot samme filer. - PR-gate: begge må passere. - Vector-genereringsskript (`scripts/generate-vectors.ts`) finnes — utvid til 7 + 8. ### Ut - iOS — egen Swift-port er framtidig roadmap, ikke V3.5. - Native bindings i `shade-android` (vi bruker Tink i JVM-kode). --- ## Leveranser ### Kotlin - Full ratchet-implementasjon (M-Cross 2). - Wire 0x02 encode/decode. - Streams 0x11 (M-Cross 3). - Tink-storage-adapter med Keystore. ### Test-vectors - Utvid `scripts/generate-vectors.ts` med ratchet-step + streams + backup. - Versjons-tag på vector-filer (`{ "version": 2, ... }`). ### CI - `.gitea/workflows/cross-vectors.yml` — Bun + Gradle matrise. - Fail-policy: hvis vector-fil endres, **begge** runners må publisere passing før merge. ### Dokumentasjon - `android/shade-android/ROADMAP-ANDROID.md` — eksplisitte milestoner + status per sjekkpunkt. - `docs/cross-platform.md` — hvordan legge til en ny vector + hvordan kjøre lokalt. --- ## Akseptansekriterier - [ ] M-Cross 2: TS-encrypted melding kan dekrypteres av Kotlin-klient og omvendt, end-to-end-test. - [ ] CI-jobben feiler innen 60 s ved bevisst byte-divergens. - [ ] M-Cross 3: 1 MiB streams-fil over 4 lanes mellom TS-server og Kotlin-klient verifisert. - [ ] Ingen public release med "production"-label før M-Cross 2 er grønn. --- ## Avhengigheter - V3.1 — `cross-platform.md` lever der. --- ## Risiko - **Tink-mismatch.** Tink HKDF-info-encoding kan avvike fra `@noble/hashes`. Mitiger med tidlig vector-test (M-Cross 1 dekker dette). - **Endian / encoding.** Wire 0x02 bruker big-endian — Kotlin `ByteBuffer` default er big-endian, men streams-nonce-konstruksjon må gjennomgås. - **Maintainer-kapasitet.** Kotlin-port + TS-port må holdes i sync. Vector-CI er primær mitigasjon. --- ## Migrasjon Eksisterende M-Cross 1 scaffold beholdes; alt nytt bygges på den.