diff --git a/Config/App.xcconfig b/Config/App.xcconfig index cc576f1..f732775 100644 --- a/Config/App.xcconfig +++ b/Config/App.xcconfig @@ -6,5 +6,6 @@ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES INFOPLIST_KEY_BaseBundleID = $(BASE_BUNDLE_ID) INFOPLIST_KEY_TeamID = $(TEAM_ID) INFOPLIST_KEY_AppGroupID = $(APP_GROUP_ID) +INFOPLIST_KEY_NSFaceIDUsageDescription = SecureStorage uses Face ID to unlock protected Keychain items. CODE_SIGN_ENTITLEMENTS = SecureStorageSample/SecureStorageSample.entitlements diff --git a/README.md b/README.md index b025a29..74ade31 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ SharedPackage/ └── Models/ └── UserProfile.swift SecureStorageSample/ -├── ContentView.swift # Tabbed navigation +├── ContentView.swift # List-based navigation ├── Models/ │ ├── Credential.swift │ └── SampleLocationData.swift @@ -112,6 +112,7 @@ The app demonstrates various storage configurations: ### Encrypted Storage - AES-256-GCM or ChaCha20-Poly1305 encryption - PBKDF2 or HKDF key derivation +- PBKDF2 iteration count must remain consistent or existing data will not decrypt - Complete file protection - External key material example via `KeyMaterialProviding` - Global encryption configuration (Keychain service/account) in app `init` diff --git a/SecureStorageSample/StorageKeys/EncryptedFileSystem/SessionLogsKey.swift b/SecureStorageSample/StorageKeys/EncryptedFileSystem/SessionLogsKey.swift index e59cd63..53d7b6c 100644 --- a/SecureStorageSample/StorageKeys/EncryptedFileSystem/SessionLogsKey.swift +++ b/SecureStorageSample/StorageKeys/EncryptedFileSystem/SessionLogsKey.swift @@ -17,6 +17,7 @@ extension StorageKeys { let syncPolicy: SyncPolicy = .never init(iterations: Int = 10_000) { + // NOTE: PBKDF2 iterations must remain stable for existing data; changing this breaks decryption. self.security = .encrypted(.aes256(keyDerivation: .pbkdf2(iterations: iterations))) } } diff --git a/SecureStorageSample/Views/EncryptedStorageDemo.swift b/SecureStorageSample/Views/EncryptedStorageDemo.swift index 5fe530d..7a30208 100644 --- a/SecureStorageSample/Views/EncryptedStorageDemo.swift +++ b/SecureStorageSample/Views/EncryptedStorageDemo.swift @@ -37,6 +37,9 @@ struct EncryptedStorageDemo: View { Stepper("PBKDF2 Iterations: \(iterations)", value: $iterations, in: 1000...100000, step: 1000) .font(.caption) + IterationWarningView() + .padding(.top, Design.Spacing.xSmall) + Text("Higher iterations = more secure but slower") .font(.caption2) .foregroundStyle(.secondary) @@ -211,3 +214,11 @@ struct EncryptedStorageDemo: View { EncryptedStorageDemo() } } + +private struct IterationWarningView: View { + var body: some View { + Text("PBKDF2 iterations must match the value used during encryption. Changing this after saving will prevent decryption.") + .font(.caption2) + .foregroundStyle(Color.Status.warning) + } +}