Add StorageKeys, ExternalKeyMaterialKey, Value

This commit is contained in:
Matt Bruce 2026-01-14 10:07:05 -06:00
parent 3efb77bc32
commit e7115693a1
3 changed files with 32 additions and 19 deletions

View File

@ -13,7 +13,7 @@ struct SecureStorgageSampleApp: App {
init() { init() {
_ = WatchConnectivityService.shared _ = WatchConnectivityService.shared
Task { Task {
await EncryptionHelper.shared.registerKeyMaterialProvider( await StorageRouter.shared.registerKeyMaterialProvider(
ExternalKeyMaterialProvider(), ExternalKeyMaterialProvider(),
for: SampleKeyMaterialSources.external for: SampleKeyMaterialSources.external
) )

View File

@ -1,37 +1,26 @@
import CryptoKit
import Foundation import Foundation
import LocalData import LocalData
import Security
nonisolated nonisolated
struct ExternalKeyMaterialProvider: KeyMaterialProviding { struct ExternalKeyMaterialProvider: KeyMaterialProviding {
private enum Constants { private enum Constants {
static let service = "com.example.securestorage.externalkey"
static let keyLength = 32 static let keyLength = 32
} }
func keyMaterial(for keyName: String) async throws -> Data { func keyMaterial(for keyName: String) async throws -> Data {
if let existing = try await KeychainHelper.shared.get( let key = StorageKeys.ExternalKeyMaterialKey(keyName: keyName)
service: Constants.service, if let existing = try await StorageRouter.shared.get(key) as Data? {
key: keyName
) {
return existing return existing
} }
var bytes = [UInt8](repeating: 0, count: Constants.keyLength) let symmetricKey = SymmetricKey(size: .bits256)
let status = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) let material = symmetricKey.withUnsafeBytes { Data($0) }
guard status == errSecSuccess else { guard material.count == Constants.keyLength else {
throw StorageError.securityApplicationFailed throw StorageError.securityApplicationFailed
} }
let material = Data(bytes) try await StorageRouter.shared.set(material, for: key)
try await KeychainHelper.shared.set(
material,
service: Constants.service,
key: keyName,
accessibility: .afterFirstUnlock,
accessControl: nil
)
return material return material
} }
} }

View File

@ -0,0 +1,24 @@
import Foundation
import LocalData
extension StorageKeys {
/// Stores external key material used for encryption policies.
struct ExternalKeyMaterialKey: StorageKey {
typealias Value = Data
let name: String
let domain: StorageDomain = .keychain(service: "com.example.securestorage.externalkey")
let security: SecurityPolicy = .keychain(
accessibility: .afterFirstUnlock,
accessControl: nil
)
let serializer: Serializer<Data> = .data
let owner = "SampleApp"
let availability: PlatformAvailability = .phoneOnly
let syncPolicy: SyncPolicy = .never
init(keyName: String) {
self.name = keyName
}
}
}