CryptoKit is Apple's modern cryptography framework. It exposes the primitives you need to protect data — symmetric and authenticated encryption, cryptographic hashing, message authentication, key derivation, digital signatures, and key agreement — through a small, strongly typed Swift API designed to make misuse hard. Keys are value types rather than raw byte buffers, ciphertext and its authentication tag travel together in a sealed box, and digests are distinct types so you cannot accidentally compare a SHA-256 hash with a SHA-512 one.
You work with a handful of building blocks. A `SymmetricKey` is the secret shared by both sides of an encrypted exchange; `AES.GCM` and `ChaChaPoly` use it to seal a message into ciphertext plus an authentication tag, and refuse to open anything that has been tampered with. The SHA-2 and SHA-3 families produce typed digests like `SHA256Digest`; `HMAC` authenticates a message under a key, and `HKDF` expands a shared secret into one or more keys. For public-key work, elliptic curves such as `Curve25519`, `P256`, `P384`, and `P521` provide signing and Diffie-Hellman key agreement, the latter yielding a `SharedSecret` you convert into a `SymmetricKey`.
Beyond the classics, CryptoKit keeps pace with the state of the art. The SHA-3 family, Hybrid Public Key Encryption (`HPKE`), and key-encapsulation mechanisms (`KEM`) sit alongside post-quantum primitives — `MLDSA65`/`MLDSA87` for signatures, `MLKEM768`/`MLKEM1024` for key encapsulation, and the `XWingMLKEM768X25519` hybrid. Private keys can be generated and held inside the Secure Enclave so the raw key material never leaves hardware, and anything cryptographically obsolete is quarantined under the `Insecure` namespace so you have to opt in by name.
Get started
Encrypt and authenticate a message with AES-GCM
import CryptoKit
import Foundation
// Generate a fresh 256-bit symmetric key (share it securely with the recipient).
let key = SymmetricKey(size: .bits256)
// Seal: encrypt the plaintext AND attach an authentication tag.
let plaintext = Data("Meet me at the docks at midnight.".utf8)
let sealedBox = try AES.GCM.seal(plaintext, using: key)
// `combined` is nonce ‖ ciphertext ‖ tag — safe to store or transmit.
let wire = sealedBox.combined!
// Open: decrypt and verify. Throws if the data or tag was modified.
let box = try AES.GCM.SealedBox(combined: wire)
let decrypted = try AES.GCM.open(box, using: key)
assert(decrypted == plaintext)Key concepts
Keys are values, not bytes
`SymmetricKey` and the private-key types are first-class values you create, copy, and pass around — never loose `[UInt8]` arrays. CryptoKit manages the underlying memory and zeroes it when the key is released, which keeps secrets from lingering and removes a whole class of handling mistakes.
Authenticated encryption (AEAD)
`AES.GCM` and `ChaChaPoly` don't just encrypt — they authenticate. `seal(_:using:)` returns a `SealedBox` containing the ciphertext, a nonce, and a tag; `open(_:using:)` decrypts only if the tag verifies, so any tampering is rejected before you ever see the plaintext.
Digests are distinct types
Each hash function produces its own digest type — `SHA256Digest`, `SHA512Digest`, and so on. Because they are different types, the compiler stops you from comparing hashes computed with different algorithms, and digests are `Hashable` and contiguous-byte iterable for easy storage and comparison.
Agreement → shared secret → key
Public-key exchange follows a fixed shape: each party performs key agreement (ECDH over `Curve25519` or a NIST curve) to derive a common `SharedSecret`, then turns that secret into a `SymmetricKey` with HKDF via `hkdfDerivedSymmetricKey(...)`. You never use the raw shared secret directly as a key.
Post-quantum and hardware-backed keys
For long-term security, `MLKEM768`/`MLKEM1024` and `MLDSA65`/`MLDSA87` provide post-quantum key encapsulation and signatures, and `XWingMLKEM768X25519` hybridises a PQ KEM with X25519. The `SecureEnclave` namespace generates keys whose private material is created and used entirely inside the device's secure hardware.
Symmetric Keys and Shared Secrets 3
The secrets that drive symmetric cryptography. Create a `SymmetricKey` of a given `SymmetricKeySize`, or derive one from the `SharedSecret` produced by a key-agreement exchange.
- StSymmetricKeyiOS 13.0+A symmetric cryptographic key — the shared secret used by authenticated ciphers, HMAC, and HKDF. Generate a random key of a chosen size, or import existing key material as `Data`; CryptoKit owns the storage and zeroes it on release.init(size:)init(data:)bitCountwithUnsafeBytes(_:)
let key = SymmetricKey(size: .bits256) // random let imported = SymmetricKey(data: keyBytes) // from Data - StSymmetricKeySizeiOS 13.0+The bit length of a symmetric key. Use the standard `.bits128`, `.bits192`, or `.bits256` sizes, or construct a custom size in bits..bits128.bits192.bits256init(bitCount:)
SymmetricKey(size: .bits256) - StSharedSecretiOS 13.0+The secret bytes produced by a Diffie-Hellman key agreement. Never used as a key directly — derive a `SymmetricKey` from it with HKDF before encrypting.hkdfDerivedSymmetricKey(using:salt:sharedInfo:outputByteCount:)x963DerivedSymmetricKey(using:sharedInfo:outputByteCount:)
let secret = try myKey.sharedSecretFromKeyAgreement(with: theirPublicKey) let key = secret.hkdfDerivedSymmetricKey( using: SHA256.self, salt: salt, sharedInfo: Data(), outputByteCount: 32)
Authenticated Encryption 2
Ciphers that encrypt and authenticate in one step. Both `AES.GCM` and `ChaChaPoly` seal plaintext into a box of ciphertext-plus-tag and refuse to open tampered data.
- EnAESiOS 13.0+The Advanced Encryption Standard cipher. Its `GCM` mode provides authenticated encryption: `seal(_:using:)` returns a `SealedBox` of ciphertext, nonce, and tag, and `open(_:using:)` decrypts only if the tag verifies.AES.GCM.seal(_:using:)AES.GCM.open(_:using:)AES.GCM.NonceAES.GCM.SealedBox
let box = try AES.GCM.seal(data, using: key) let clear = try AES.GCM.open(box, using: key) - EnChaChaPolyiOS 13.0+The ChaCha20-Poly1305 authenticated cipher — a fast, constant-time alternative to AES-GCM that excels on hardware without AES acceleration. Same `seal`/`open` shape as `AES.GCM`.seal(_:using:)open(_:using:)ChaChaPoly.SealedBoxChaChaPoly.Nonce
let box = try ChaChaPoly.seal(data, using: key) let clear = try ChaChaPoly.open(box, using: key)
Hashing 12
One-way hash functions and the typed digests they produce. Prefer the SHA-2 (`SHA256`/`SHA384`/`SHA512`) or SHA-3 families; each `hash(data:)` returns a strongly typed `…Digest`.
- StSHA256iOS 13.0+The SHA-2 256-bit hash function. Hash a buffer in one call, or feed it incrementally and finalize, producing a typed `SHA256Digest`.hash(data:)update(data:)finalize()
let digest = SHA256.hash(data: message) print(digest.compactMap { String(format: "%02x", $0) }.joined()) - StSHA256DigestiOS 13.0+The output of a Secure Hashing Algorithm 2 (SHA-2) hash with a 256-bit digest.
- StSHA384iOS 13.0+An implementation of Secure Hashing Algorithm 2 (SHA-2) hashing with a
- StSHA384DigestiOS 13.0+The output of a Secure Hashing Algorithm 2 (SHA-2) hash with a 384-bit digest.
- StSHA512iOS 13.0+An implementation of Secure Hashing Algorithm 2 (SHA-2) hashing with a
- StSHA512DigestiOS 13.0+The output of a Secure Hashing Algorithm 2 (SHA-2) hash with a 512-bit digest.
- StSHA3_256iOS 26.0+An implementation of Secure Hashing Algorithm 3 (SHA-3) hashing with a 256-bit digest.
- StSHA3_256DigestiOS 26.0+The output of a Secure Hashing Algorithm 3 (SHA-2) hash with a 256-bit digest.
- StSHA3_384iOS 26.0+An implementation of Secure Hashing Algorithm 3 (SHA-3) hashing with a 384-bit digest.
- StSHA3_384DigestiOS 26.0+The output of a Secure Hashing Algorithm 3 (SHA-2) hash with a 384-bit digest.
- StSHA3_512iOS 26.0+An implementation of Secure Hashing Algorithm 3 (SHA-3) hashing with a 512-bit digest.
- StSHA3_512DigestiOS 26.0+The output of a Secure Hashing Algorithm 3 (SHA-2) hash with a 512-bit digest.
Message Authentication and Key Derivation 3
Keyed integrity and key expansion. `HMAC` proves a message came from someone holding the key, and `HKDF` stretches a high-entropy secret into one or more derived keys.
- StHMACiOS 13.0+A hash-based message authentication code, generic over a hash function. Produces and verifies a keyed tag that proves a message's integrity and origin to anyone holding the key.authenticationCode(for:using:)isValidAuthenticationCode(_:authenticating:using:)
let mac = HMAC<SHA256>.authenticationCode(for: data, using: key) let ok = HMAC<SHA256>.isValidAuthenticationCode(mac, authenticating: data, using: key) - StHKDFiOS 14.0+The HMAC-based key derivation function. Expands a high-entropy input — typically a `SharedSecret` — into one or more cryptographically independent `SymmetricKey`s, optionally bound to a salt and context info.deriveKey(inputKeyMaterial:salt:info:outputByteCount:)expand(pseudoRandomKey:info:outputByteCount:)
let key = HKDF<SHA256>.deriveKey( inputKeyMaterial: ikm, salt: salt, info: info, outputByteCount: 32) - StHashedAuthenticationCodeiOS 13.0+A hash-based message authentication code.
Elliptic-Curve Cryptography 5
Public-key signing and Diffie-Hellman key agreement over modern curves. `Curve25519` is the default choice; `P256`/`P384`/`P521` cover NIST-curve interoperability.
- EnCurve25519iOS 13.0+The Curve25519 elliptic curve, namespacing `Signing` (Ed25519) and `KeyAgreement` (X25519) key pairs. The recommended default for new signing and Diffie-Hellman code.Curve25519.Signing.PrivateKeyCurve25519.KeyAgreement.PrivateKeypublicKeysignature(for:)
let sk = Curve25519.Signing.PrivateKey() let sig = try sk.signature(for: message) let ok = sk.publicKey.isValidSignature(sig, for: message) - EnP256iOS 13.0+An elliptic curve that enables NIST P-256 signatures and key agreement.
- EnP384iOS 13.0+An elliptic curve that enables NIST P-384 signatures and key agreement.
- EnP521iOS 13.0+An elliptic curve that enables NIST P-521 signatures and key agreement.
- StCorecryptoCurveTypeiOS 18.0+A type that identifies the underlying corecrypto elliptic curve backing a key.
Post-Quantum Cryptography 6
Primitives that resist attacks from quantum computers. ML-DSA signs, ML-KEM encapsulates keys, and X-Wing combines a PQ KEM with X25519 for hybrid security during the transition.
- EnMLKEM768iOS 26.0+A post-quantum key-encapsulation mechanism at the ML-KEM-768 (FIPS 203) security level. The recipient publishes a public key; the sender encapsulates a fresh shared secret to it, and the recipient decapsulates the same secret.MLKEM768.PrivateKeyMLKEM768.PublicKeyencapsulate()decapsulate(_:)
let sk = MLKEM768.PrivateKey() let result = try sk.publicKey.encapsulate() // sender let secret = try sk.decapsulate(result.encapsulated) // recipient - EnMLDSA65iOS 26.0+The MLDSA65 Digital Signature Algorithm
- EnMLDSA87iOS 26.0+The MLDSA87 Digital Signature Algorithm
- EnMLKEM1024iOS 26.0+The Module-Lattice key encapsulation mechanism (KEM).
- EnXWingMLKEM768X25519iOS 26.0+The X-Wing (ML-KEM768 with X25519) Key Encapsulation Mechanism, defined in
- EnKEMiOS 17.0+A key encapsulation mechanism.
Hybrid Public Key Encryption 1
`HPKE` packages key encapsulation, a key-derivation step, and an AEAD cipher into a single standardized scheme for encrypting to a recipient's public key.
- EnHPKEiOS 17.0+Hybrid Public Key Encryption (RFC 9180): a standardized scheme that combines key encapsulation, a KDF, and an AEAD cipher so you can encrypt directly to a recipient's public key. Configure it with a `Ciphersuite`.HPKE.SenderHPKE.RecipientHPKE.Ciphersuiteseal(_:authenticating:)
var sender = try HPKE.Sender( recipientKey: recipientPublic, ciphersuite: .Curve25519_SHA256_AES_GCM_256, info: info) let ct = try sender.seal(message)
Hardware-Backed Keys 1
Keys whose private half is generated and used inside the Secure Enclave, so the raw key material is never exposed to your app or the operating system.
- EnSecureEnclaveiOS 13.0+Generates and uses private keys inside the device's Secure Enclave, so the raw private key material is never exposed to your app, the OS, or memory. Available on devices with the dedicated security hardware.SecureEnclave.P256.Signing.PrivateKeySecureEnclave.P256.KeyAgreement.PrivateKeyisAvailabledataRepresentation
guard SecureEnclave.isAvailable else { return } let sk = try SecureEnclave.P256.Signing.PrivateKey()
Legacy Algorithms 1
Obsolete primitives (MD5, SHA-1, insecure RSA padding) kept only for interoperability, namespaced under `Insecure` so you must opt in deliberately.
- EnInsecureiOS 13.0+A container for older, cryptographically insecure algorithms.
Errors 2
The error types CryptoKit throws when an operation fails — for example authentication-tag verification failures or malformed ASN.1 key encodings.
- EnCryptoKitErroriOS 13.0+General cryptography errors used by CryptoKit.
- EnCryptoKitASN1ErroriOS 14.0+Errors from decoding ASN.1 content.
Protocols 14
- PrDiffieHellmanKeyAgreementiOS 17.0+A Diffie-Hellman Key Agreement Key
- PrDigestiOS 13.0+A type that represents the output of a hash.
- PrHPKEDiffieHellmanPrivateKeyiOS 17.0+A type that represents the private key in a Diffie-Hellman key exchange.
- PrHPKEDiffieHellmanPrivateKeyGenerationiOS 17.0+A type that represents the generation of private keys in a Diffie-Hellman key exchange.
- PrHPKEDiffieHellmanPublicKeyiOS 17.0+A type that represents the public key in a Diffie-Hellman key exchange.
- PrHPKEKEMPrivateKeyiOS 26.0+A type that represents the private key in HPKE.
- PrHPKEKEMPrivateKeyGenerationiOS 26.0+A type that represents the generation of private keys in HPKE
- PrHPKEKEMPublicKeyiOS 26.0+A type that represents the public key in HPKE
- PrHPKEPublicKeySerializationiOS 17.0+A type that ``HPKE`` uses to encode the public key.
- PrHashFunctioniOS 13.0+A type that performs cryptographically secure hashing.
- PrKEMOneTimePrivateKeyiOS 27.0+A one-time private key for a key encapsulation mechanism, which can only decapsulate once but it does so faster.
- PrKEMPrivateKeyiOS 17.0+The private key for a key encapsulation mechanism.
- PrKEMPublicKeyiOS 17.0+The public key for a key encapsulation mechanism.
- PrMessageAuthenticationCodeiOS 13.0+A type that represents a message authentication code.
Type Aliases 4
- TyCryptoKitMetaError
- TySHA2_256An implementation of Secure Hashing Algorithm 2 (SHA-2) hashing with a
- TySHA2_384An implementation of Secure Hashing Algorithm 2 (SHA-2) hashing with a
- TySHA2_512An implementation of Secure Hashing Algorithm 2 (SHA-2) hashing with a