# shade-android Kotlin implementation of the Shade E2EE protocol for Android apps. Byte-for-byte compatible with `@shade/core` (TypeScript), so messages encrypted on a TS backend can be decrypted on Android and vice versa. ## Status **M-Cross 1 ✅** — keys + HKDF + X3DH + fingerprint. **M-Cross 2 ✅** — full ratchet step (encrypt + decrypt roundtrip) + wire 0x02 (RatchetMessage and PreKeyMessage with/without OTPK). **M-Cross 3 ✅** — streams 0x11 (KDF labels with embedded NULs, deterministic chunk nonce/AAD, wire 0x11 encode/decode). **M-Cross 4 ✅** — backup-key HKDF + AES-GCM, group sender-key step (`kdfChainKey` + Ed25519 sign over `aad ‖ ct`), storage HKDF (storageKey/fieldKey/rowNonce). Pending: scrypt master-key, argon2id swap, Android KeystoreStorage (sibling module). Cross-platform test vectors in `/test-vectors/` are loaded by both the TS and Kotlin test suites; any byte-divergence fails CI within 60 s. See `ROADMAP-ANDROID.md` for the parity-checkpoint matrix and `/docs/cross-platform.md` for how to add a new vector. ## Usage (target API) ```kotlin import no.zyon.shade.ShadeSessionManager import no.zyon.shade.crypto.TinkProvider import no.zyon.shade.storage.KeystoreStorage val crypto = TinkProvider() val storage = KeystoreStorage(context) val manager = ShadeSessionManager(crypto, storage) manager.initialize() // Establish a session with a peer val bundle = fetchBundleFromServer("bob@example.com") manager.initSessionFromBundle("bob@example.com", bundle) // Encrypt val envelope = manager.encrypt("bob@example.com", "hello") // Decrypt val plaintext = manager.decrypt("alice@example.com", incomingEnvelope) ``` ## Crypto primitives Backed by Google Tink: - X25519 for Diffie-Hellman (via `X25519.generatePrivateKey()` / `computeSharedSecret`) - Ed25519 for signing (via `Ed25519Sign` / `Ed25519Verify`) - AES-256-GCM (via `AesGcmJce`) - HKDF-SHA256 (via `Hkdf.computeHkdf`) - HMAC-SHA256 (via `MacFactory`) ## Building Requires JDK 17. The module compiles as a pure-JVM Kotlin library so the parity gate runs without an Android SDK install. The Android-specific storage adapter (Keystore + EncryptedSharedPreferences) will land as a sibling Gradle module in M-Cross 4. ```bash cd android ./gradlew :shade-android:test ``` The Gradle wrapper downloads Gradle 8.10.2 on first run. ## Compatibility The Kotlin implementation must produce byte-identical output to `@shade/core` for: - KDF chain derivations (root key ratchet, chain key ratchet) - X3DH shared secrets - Ratchet message keys and ciphertext (given the same keys) - Fingerprints (safety numbers) - Binary wire format (`@shade/proto`) Shared test vectors in `test-vectors/` are loaded by both the TS and Kotlin test suites. Any divergence fails the CI immediately.