From 9330c0c452af791988b55392e9c09a0bb446fd03 Mon Sep 17 00:00:00 2001 From: null Date: Wed, 8 Jul 2026 23:29:37 -0500 Subject: [PATCH] =?UTF-8?q?docs(manual):=20batch=209=20review=20=E2=80=94?= =?UTF-8?q?=20Tink=20template=20name=20was=20SHA128=20(typo),=20should=20b?= =?UTF-8?q?e=20SHA256?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The iOS CryptoKit guidance paragraph said: 'Tink's ECIES_P256_HKDF_HMAC_SHA128_GCM is not bit-compatible with raw CryptoKit...' But the actual Tink template is ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM (SHA-256, not SHA-128). Verified in app/src/main/java/app/closer/crypto/UserKeyManager.kt: HybridKeyTemplates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM The iOS->Android sealed-answer bridge section above the typo already had the correct SHA256 name. Fixed the CryptoKit guidance to match. Other Batch 9 claims verified clean: - CloserApp.swift @main is CloserApp, with @StateObject AppState. - AppState is @MainActor final ObservableObject with @Published authState / currentUser / currentCouple / currentPartner / isPremium. - iOS deployment target: 17.0 (iphone/project.yml). - NavigationStack + .navigationDestination, no DI framework, .shared singletons (AuthService.shared, FirestoreService.shared, BillingService.shared) - matches. - CloserTheme.swift color tokens: closerPrimary light=B98AF4 /dark=CFA7FF, closerSecondary light=E7A2D1 /dark=FFAFD9, closerBackground light=FFFBFE /dark=18111E - matches the brand primary/secondary stated in MEMORY.md. - docs/brand/visual-identity.md and docs/copy-guide.md both exist. - XcodeGen project name = Closer (iphone/project.yml). - Project.yml deploymentTarget iOS: 17.0. - All PARTNER_ANSWERED / REVEAL_READY / gameRouteForType / wheelComplete / thisOrThatReplay / PARTNER_JOINED_GAME / PARTNER_COMPLETED_PART / fromRemoteType branches exist in PartnerNotificationManager.kt and match the manual's deep-link routing table. --- docs/Engineering_Reference_Manual.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Engineering_Reference_Manual.md b/docs/Engineering_Reference_Manual.md index b2526d5c..c3d436f6 100644 --- a/docs/Engineering_Reference_Manual.md +++ b/docs/Engineering_Reference_Manual.md @@ -1094,7 +1094,7 @@ The iOS port now implements the strict-E2EE pairing path: The iOS CryptoKit implementation follows these rules of parity with Android: - Use CryptoKit's `AES.GCM` for symmetric encryption. AAD binding must match Android exactly. -- Use `P256.KeyAgreement` + `HKDF` + `AES.GCM` for the iOS-native Path A ECIES envelope. Tink's `ECIES_P256_HKDF_HMAC_SHA128_GCM` is not bit-compatible with raw CryptoKit, so iOS→Android sealed-answer key release goes through the server-side `wrapReleaseKeyCallable` (see [iOS → Android sealed-answer bridge](#ios-android-sealed-answer-bridge-wrapreleasekeycallable)). iOS↔iOS releases use the native Path A envelope. +- Use `P256.KeyAgreement` + `HKDF` + `AES.GCM` for the iOS-native Path A ECIES envelope. Tink's `ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM` is not bit-compatible with raw CryptoKit, so iOS→Android sealed-answer key release goes through the server-side `wrapReleaseKeyCallable` (see [iOS → Android sealed-answer bridge](#ios-android-sealed-answer-bridge-wrapreleasekeycallable)). iOS↔iOS releases use the native Path A envelope. - Use `SecItemAdd` / `SecItemCopyMatching` for keychain storage. Store the couple key as a generic password item with `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` and `kSecAttrSynchronizable=false` so it is device-bound and not included in iCloud backup. - For Argon2id, use `swift-sodium` (libsodium) rather than an unaudited pure-Swift implementation. Verify byte output against the Android BouncyCastle reference before shipping.