Sample CodeiOS, iPadOS, Mac Catalyst, macOSReviewed 2026-07-21View on Apple Developer

Storing CryptoKit Keys in the Keychain

At a glance

Item Summary
Purpose Convert between strongly typed cryptographic keys and native keychain types.
App architecture A Swift sample bundle with entry-bearing project variants CryptoKitKeychain, CryptoKitKeychainMac, each leading to CryptoKit APIs.
Main patterns Protocol-oriented abstraction, Delegate or data-source callbacks, Central store, SwiftUI environment injection
Project style 18 scanned source file(s) across Swift, organized around ranked entry, type, and file boundaries.
Execution model No structured execution marker indexed; callback threading requires source review.
State/event model Source-visible mechanisms: ObservableObject, @Published, SwiftUI state property wrapper.
Key frameworks/packages Foundation, CryptoKit, SwiftUI, Security, UIKit; these are source dependencies, not architecture labels.

Project structure

Source bundle/
├── CryptoKitKeychain/
│   ├── AppDelegate.swift
│   └── SceneDelegate.swift
├── CryptoKitKeychainMac/
│   └── AppDelegate.swift
├── Testing/
│   └── KeyTest.swift
├── Views/
│   ├── ContentView.swift
│   ├── CurveView.swift
│   ├── NISTView.swift
│   ├── SymmetricView.swift
│   └── ExecutionView.swift
└── Storage/
    ├── GenericPasswordStore.swift
    ├── SecKeyStore.swift
    └── GenericPasswordConvertible.swift

Structure observations

  • Architecturally prominent files are ranked from entry points and role-named declarations; resource-only paths are omitted.
  • Primary languages: Swift.
  • The verified tree contains 8 project/configuration file(s) and 19 source declaration(s).

Overall architecture

Reference code

CryptoKitKeychain/AppDelegate.swift:10 — architecture anchor

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { }

Interpretation

The branches represent separate entry-bearing project variants in the downloaded bundle, not runtime calls between those variants. Each branch is intentionally collapsed at the documented framework boundary; the detailed target-local flow remains in the cited files. Ownership is claimed only where the next section cites a stored property or assignment.

Ownership and state

Ownership evidence

CryptoKitKeychainMac/AppDelegate.swift:14 — stored dependency or nearest verified ownership anchor

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    // ...
    var window: NSWindow!
    // ...
}
Owner Object or state Relationship Mutation authority
AppDelegate NSWindow (window) stores or receives App/module collaborators
ContentView KeyTest (tester) receives environment-provided state The environment provider is authoritative
CurveView KeyTest (tester) receives environment-provided state The environment provider is authoritative
NISTView KeyTest (tester) receives environment-provided state The environment provider is authoritative

Composition arrows indicate a source-visible construction expression or locally owned value state; aggregation means the owner stores or receives a dependency without proving exclusive lifetime ownership.

Concurrency, scheduling, and thread safety

Evidence limit: actor isolation, async/await, or Task creation does not by itself prove background-thread execution; Sendable conformance alone does not prove thread-safe mutation.

No source-visible execution, scheduling, or synchronization boundary was found in the indexed source.

@MainActor/MainActor.run, DispatchQueue.main, and RunLoop.main are reported as distinct isolation, queue, and event-loop mechanisms. A plain Task is kept separate from Task.detached; neither is labeled as a background thread.

State propagation, frameworks, and dependencies

Evidence limit: an import proves a source-level compilation dependency at the cited line; it does not prove runtime use, architectural adoption, or whether a Swift package is a direct application dependency.

Category Mechanism or module Verified role Evidence
State propagation ObservableObject ObservableObject supplies an observation contract. Testing/KeyTest.swift:13
State propagation @Published A published property can emit owner-controlled changes. Testing/KeyTest.swift:64
State propagation SwiftUI state property wrapper A SwiftUI property wrapper supplies or observes UI state. Views/ContentView.swift:11
Source import Foundation The cited file imports this module; runtime use and architectural role are not inferred. Storage/GenericPasswordConvertible.swift:8
Source import CryptoKit The cited file imports this module; runtime use and architectural role are not inferred. Storage/GenericPasswordConvertible.swift:9
Source import SwiftUI The cited file imports this module; runtime use and architectural role are not inferred. CryptoKitKeychain/SceneDelegate.swift:9
Source import Security The cited file imports this module; runtime use and architectural role are not inferred. Storage/GenericPasswordStore.swift:10
Source import UIKit The cited file imports this module; runtime use and architectural role are not inferred. CryptoKitKeychain/AppDelegate.swift:8

receive(on:) describes downstream delivery scheduling, while subscribe(on:) describes upstream subscription/request/cancel scheduling. An import Combine alone establishes neither behavior nor a Store, reducer, Redux, or other application architecture.

Class and protocol design

Storage/GenericPasswordConvertible.swift:12 — representative type boundary

protocol GenericPasswordConvertible: CustomStringConvertible {
    /// Creates a key from a generic key representation.
    init<D>(genericKeyRepresentation data: D) throws where D: ContiguousBytes

    /// A generic representation of the key.
    var genericKeyRepresentation: SymmetricKey { get }
}
Type Responsibility Depends on or conforms to
AppDelegate Receives callback-driven events UIResponder, UIApplicationDelegate
AppDelegate Receives callback-driven events NSObject, NSApplicationDelegate
ContentView User-interface presentation and input forwarding View
CurveView User-interface presentation and input forwarding View
NISTView User-interface presentation and input forwarding View
SymmetricView User-interface presentation and input forwarding View
SceneDelegate Receives callback-driven events UIResponder, UIWindowSceneDelegate
GenericPasswordStore Centralized state or persistence access Concrete collaborators/imported frameworks
SecKeyStore Centralized state or persistence access Concrete collaborators/imported frameworks
ExecutionView User-interface presentation and input forwarding View

The source explicitly defines local protocol relationships: Curve25519.KeyAgreement.PrivateKeyGenericPasswordConvertible, Curve25519.Signing.PrivateKeyGenericPasswordConvertible, SymmetricKeyGenericPasswordConvertible, SecureEnclave.P256.KeyAgreement.PrivateKeyGenericPasswordConvertible, SecureEnclave.P256.Signing.PrivateKeyGenericPasswordConvertible, P256.Signing.PrivateKeySecKeyConvertible.

Access control

Symbol Access Verified effect Likely rationale
description (Storage/GenericPasswordConvertible.swift:23) public The symbol is visible to importing modules. Inference: make the declaration available across a module or target boundary.
description (Storage/KeyStoreError.swift:18) public The symbol is visible to importing modules. Inference: make the declaration available across a module or target boundary.
description (Storage/SecKeyConvertible.swift:23) public The symbol is visible to importing modules. Inference: make the declaration available across a module or target boundary.
testCurve (Testing/KeyTest+Curve.swift:13) internal No explicit modifier means the Swift declaration is internal to the module. Inference: the language’s file or module boundary is sufficient for this sample collaboration.

Reference code

Storage/GenericPasswordConvertible.swift:23 — representative boundary

    public var description: String {
        return self.genericKeyRepresentation.withUnsafeBytes { bytes in
            return "Key representation contains \(bytes.count) bytes."
        }
    }

Swift declarations without a modifier are internal; explicit private, fileprivate, private(set), public, or open entries above are interpreted by language semantics. Objective-C/C samples instead rely on header and implementation boundaries, which are not equivalent to Swift lexical privacy.

Logic ownership and placement

Logic Owning type or file Placement rationale
Receives callback-driven events AppDelegate, SceneDelegate The source’s Delegate suffix makes this role explicit.
Centralized state or persistence access GenericPasswordStore, SecKeyStore The source’s Store suffix makes this role explicit.
User-interface presentation and input forwarding ContentView, CurveView, ExecutionView, NISTView The source’s View suffix makes this role explicit.

Design patterns

Pattern Source evidence Purpose or tradeoff
Protocol-oriented abstraction Storage/GenericPasswordConvertible.swift:31 A local protocol and concrete conformance create an explicit capability boundary.
Delegate or data-source callbacks CryptoKitKeychain/AppDelegate.swift:11 Callback protocols invert event delivery back into the sample’s owner.
Central store Storage/GenericPasswordStore.swift:12 A store-named type centralizes feature state or persistence.
SwiftUI environment injection Views/ContentView.swift:11 The environment supplies state or a capability without threading it through every initializer.

Naming conventions

  • Types: Delegate: AppDelegate, SceneDelegate; Store: GenericPasswordStore, SecKeyStore; View: ContentView, CurveView, ExecutionView, NISTView, SymmetricView.
  • Protocols: GenericPasswordConvertible, SecKeyConvertible.
  • Methods: applicationDidFinishLaunching, reset, run, scene.
  • Files: CryptoKitKeychain/AppDelegate.swift, CryptoKitKeychainMac/AppDelegate.swift, Testing/KeyTest.swift, Views/ContentView.swift, Views/CurveView.swift, Views/NISTView.swift.

Architecture takeaways

  • AppDelegate is the main source-visible entry or composition anchor for this sample.
  • Framework work reaches CryptoKit, SwiftUI, Security, UIKit through a deliberately small high-level chain; the detailed API graph remains inside the cited implementation files.
  • Stored-property evidence identifies lifecycle collaboration; it does not by itself prove exclusive object ownership.
  • Access-control conclusions separate verified language visibility from the likely design rationale.
  • Local protocol relationships provide an explicit substitution boundary.

Source map

Source file Relevant symbols
CryptoKitKeychain/AppDelegate.swift Cited implementation, UIKit, AppDelegate
CryptoKitKeychainMac/AppDelegate.swift Cited implementation, AppDelegate
Storage/GenericPasswordConvertible.swift GenericPasswordConvertible, Cited implementation, Foundation, CryptoKit
Storage/KeyStoreError.swift Cited implementation, KeyStoreError
Storage/SecKeyConvertible.swift Cited implementation, SecKeyConvertible
Testing/KeyTest+Curve.swift Cited implementation, Feature implementation
Storage/GenericPasswordStore.swift GenericPasswordStore, Security
Views/ContentView.swift Cited implementation, SwiftUI state property wrapper, ContentView, ContentViewPreviews
Testing/KeyTest.swift ObservableObject, @Published, KeyTest, TestStatus, Category, Purpose, NISTSize, SymmetricSize
CryptoKitKeychain/SceneDelegate.swift SwiftUI, SceneDelegate
Views/CurveView.swift CurveView, CurveViewPreviews
Views/NISTView.swift NISTView, NISTViewPreviews
Views/SymmetricView.swift SymmetricView, SymmetricViewPreviews
Storage/SecKeyStore.swift SecKeyStore
Views/ExecutionView.swift ExecutionView
Testing/KeyTest+NIST.swift Feature implementation