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. |
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
flowchart LR
Bundle["Sample bundle"]
V1["CryptoKitKeychain"]
V2["CryptoKitKeychainMac"]
Boundary["CryptoKit APIs"]
Bundle --> V1
V1 --> Boundary
Bundle --> V2
V2 --> Boundary
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
classDiagram
AppDelegate o-- NSWindow : window
ContentView o-- KeyTest : tester
CurveView o-- KeyTest : tester
NISTView o-- KeyTest : tester
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.
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.PrivateKey → GenericPasswordConvertible, Curve25519.Signing.PrivateKey → GenericPasswordConvertible, SymmetricKey → GenericPasswordConvertible, SecureEnclave.P256.KeyAgreement.PrivateKey → GenericPasswordConvertible, SecureEnclave.P256.Signing.PrivateKey → GenericPasswordConvertible, P256.Signing.PrivateKey → SecKeyConvertible.
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
AppDelegateis 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 |
AppDelegate |
CryptoKitKeychainMac/AppDelegate.swift |
AppDelegate |
Testing/KeyTest.swift |
KeyTest, TestStatus, Category, Purpose, NISTSize, SymmetricSize |
Views/ContentView.swift |
ContentView, ContentViewPreviews |
Views/CurveView.swift |
CurveView, CurveViewPreviews |
Views/NISTView.swift |
NISTView, NISTViewPreviews |
Views/SymmetricView.swift |
SymmetricView, SymmetricViewPreviews |
CryptoKitKeychain/SceneDelegate.swift |
SceneDelegate |
Storage/GenericPasswordStore.swift |
GenericPasswordStore |
Storage/SecKeyStore.swift |
SecKeyStore |