Skip to content
macOSDeep Dive Published Updated 3 min readViews unavailable

Secure Enclave Keys on macOS: Keychain Access Control Without Exportable Private Material

How Secure Enclave-backed macOS keys combine Keychain references, access-control policy, signatures, device binding, error handling, and recovery design.

On supported Macs, an application can ask Security.framework to generate a private key whose operations are performed by the Secure Enclave. The app receives a Keychain reference and can request signing or key agreement when access-control conditions are satisfied. It does not receive exportable private-key bytes. That protects extraction, but it also changes backup, migration, and account-recovery design.

Generation binds capability to policy

A typical creation dictionary selects an elliptic-curve key type, permanent Keychain storage, the Secure Enclave token, an application tag, and a SecAccessControl object. The access-control flags can require user presence, current biometric enrollment, a device passcode, or application password depending on the supported platform policy.

let access = SecAccessControlCreateWithFlags(
    nil,
    kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
    [.privateKeyUsage, .userPresence],
    nil)!

let attributes: [String: Any] = [
    kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
    kSecAttrKeySizeInBits as String: 256,
    kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
    kSecPrivateKeyAttrs as String: [
        kSecAttrIsPermanent as String: true,
        kSecAttrApplicationTag as String: Data("com.example.signing".utf8),
        kSecAttrAccessControl as String: access
    ]
]

Check SecKeyCreateRandomKey errors and query algorithm support before use. The exact flags must match the product’s authentication promise. .userPresence and .biometryCurrentSet are not synonyms: tying use to the current biometric set can invalidate access after enrollment changes, while a broader presence policy may permit another device-unlock method.

The Keychain item is a reference, not the secret

Store and retrieve the key by a stable application tag and access group. Restrict Keychain sharing to components that genuinely need the operation. Access groups and entitlements are authorization configuration; an accidental broad group expands who can ask for signatures even though nobody can export the scalar.

Export the public key with SecKeyCopyExternalRepresentation, encode it in the protocol’s required format, and bind it to an account through an authenticated enrollment ceremony. Never assume that a raw platform public-key representation already matches a server’s DER, X.509, COSE, or JWK encoding.

For each operation, use SecKeyIsAlgorithmSupported and sign the right input form. Some algorithms hash internally and others expect a digest. Signing a digest with a “message” algorithm double-hashes it; signing arbitrary message bytes with a “digest” algorithm misstates the security contract.

Authentication UI is also part of the operation. Supply an LAContext and localized reason through the documented Security framework parameters when the policy can prompt, perform the call from a context that can present UI, and distinguish user cancellation from key invalidation or an unsupported algorithm. Never loop immediately on cancellation: repeated biometric/passcode prompts can lock out or train users to approve an unexplained request. Bind each prompt to a visible, user-initiated action and a precise server challenge.

Sign fresh nonces and include protocol context—account, relying service, operation, and version—in the data that the server verifies. A valid signature over an ambiguous byte string can be replayed for a different action if the surrounding protocol never domain-separates its messages.

Recovery is an application protocol

A ThisDeviceOnly Secure Enclave private key is intentionally not restored to another Mac through ordinary backup. Hardware failure, erase, account migration, or access-control invalidation can make the key unavailable. The application therefore needs another authenticated device, a recovery credential, administrator escrow of a separate key, or a server-mediated re-enrollment flow.

Do not weaken the primary key to make migration easy. Treat loss as key revocation: enroll a replacement public key, invalidate the old credential server-side, and retain an audit trail. For data encryption, avoid making irreplaceable user data decryptable only by one nonexportable key unless a deliberate wrapped-key or recovery architecture exists.

Test cancellation, lock state, changed biometrics, no passcode, unsupported hardware, duplicate tags, app reinstall, access-group changes, OS update, and device migration. A Secure Enclave key is strongest when its nonexportability is paired with precise access control and a recovery protocol designed before the first customer loses a device.

Related:

Sources:

Comments