How does a Secure Enclave key behave in code: what is stored, what can be restored, and what can you not do with it?

14.7.4 · L3 · Interview

Predict first

Can you restore an enclave key from its blob, and is it the raw key? (needs a Mac with a Secure Enclave)

import Foundation
import CryptoKit

print("secure enclave available:", SecureEnclave.isAvailable)
let key = try SecureEnclave.P256.Signing.PrivateKey()
let msg = Data("challenge".utf8)
let sig = try key.signature(for: msg)
print("signature verifies with public key:", key.publicKey.isValidSignature(sig, for: msg))
let blob = key.dataRepresentation
let restored = try SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: blob)
print("blob is not the raw key (more than 32 bytes):", blob.count > 32)
print("restored key has the same public key:", restored.publicKey.rawRepresentation == key.publicKey.rawRepresentation)
print("software key has rawRepresentation, enclave key does not expose it:", P256.Signing.PrivateKey().rawRepresentation.count)
  • secure enclave available: true / signature verifies with public key: true / blob is not the raw key (more than 32 bytes): true / restored key has the same public key: true / software key has rawRepresentation, enclave key does not expose it: 32
  • secure enclave available: false
  • restored key has the same public key: false

Mental model. The blob is a claim ticket for a coat that is kept in a vault: you can show the ticket to get the coat worn for you, but you can never take the coat out of the building or reuse the ticket at another building.

A Secure Enclave key is created inside the coprocessor and its private part never leaves it, so what your app keeps is a dataRepresentation: an opaque blob that is only usable on the same device. The check on a Mac with a Secure Enclave shows the lifecycle: SecureEnclave.isAvailable is true, a signature made by the key verifies with its exported publicKey, the blob is larger than a 32-byte raw key (it is not the key), and restoring a key from the blob gives the same public key. Store the blob in the Keychain or a file; losing it loses the key, and it cannot be restored on another device or after a restore from backup to a new phone, so design a re-enrolment path (a new key, registered with the server again). A software P256.Signing.PrivateKey by contrast has a 32-byte rawRepresentation you can copy and export, which is exactly the property you give up for hardware protection.

Limits to say aloud: it supports only P-256 signing and key agreement (not bulk encryption: use it to sign challenges or unwrap a symmetric key), and an access control (biometry or passcode, Q343) can be attached when the key is created. The simulator has none, so isAvailable is false there and the creation call throws; code needs a fallback and tests need a protocol seam. The enclave protects the key from extraction, not from use: malware running as your app on an unlocked device can still ask it to sign, which is why access control and server-side risk checks matter. Not run here: the biometric access-control flags (need a device and a person) and use of the key through the Keychain APIs.

The blob restores the same key on the same device; only a software key exposes its raw bytes.

Common traps

  • Treating dataRepresentation as the key. It is a device-bound handle; back it up and it is useless elsewhere.
  • Assuming the simulator behaves like a device. There is no enclave, so code paths must handle unavailability.
  • Assuming hardware keys stop a compromised app from signing. They stop copying, not use.

They might follow up with

  • How do you migrate users to a new phone? Create a new enclave key on the new device and re-register its public key after another proof of identity.
  • What can you encrypt with it? Not bulk data directly; derive or wrap a symmetric key with agreement.

Related questions

  • 14.7.3 What does a code signature actually protect, what does it not say about the signer, and what happens when a…
  • 14.6.3 How do P-256 and Ed25519 signatures differ in CryptoKit: sizes, encodings, determinism, and interoperating…
  • 14.2.1 How do Face ID and Touch ID with LocalAuthentication work, and what does the Secure Enclave add?
  • 14.2.2 What do App Attest and DeviceCheck prove, when do they help, and what are their limits?

← What does a code signature actually protect, what does it not say…