Add IterationWarningView

This commit is contained in:
Matt Bruce 2026-01-16 14:09:19 -06:00
parent 542d847ee6
commit a881eaa145
4 changed files with 15 additions and 1 deletions

View File

@ -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

View File

@ -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`

View File

@ -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)))
}
}

View File

@ -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)
}
}