Loading...
Loading...
Perform cryptographic operations using Apple CryptoKit. Use when hashing data with SHA256/SHA384/SHA512, generating HMAC authentication codes, encrypting with AES-GCM or ChaChaPoly, signing with P256/P384/P521/Curve25519 keys, performing ECDH key agreement, storing keys in the Secure Enclave, or migrating from CommonCrypto to CryptoKit.
npx skill4agent add dpearson2699/swift-ios-skills cryptokitHashFunctionimport CryptoKit
let data = Data("Hello, world!".utf8)
let digest = SHA256.hash(data: data)
let hex = digest.compactMap { String(format: "%02x", $0) }.joined()var hasher = SHA256()
hasher.update(data: chunk1)
hasher.update(data: chunk2)
let digest = hasher.finalize()==let expected = SHA256.hash(data: reference)
let actual = SHA256.hash(data: received)
if expected == actual {
// Data integrity verified
}let key = SymmetricKey(size: .bits256)
let data = Data("message".utf8)
let mac = HMAC<SHA256>.authenticationCode(for: data, using: key)let isValid = HMAC<SHA256>.isValidAuthenticationCode(
mac, authenticating: data, using: key
)var hmac = HMAC<SHA256>(key: key)
hmac.update(data: chunk1)
hmac.update(data: chunk2)
let mac = hmac.finalize()let key = SymmetricKey(size: .bits256)
let plaintext = Data("Secret message".utf8)
// Encrypt
let sealedBox = try AES.GCM.seal(plaintext, using: key)
let ciphertext = sealedBox.combined! // nonce + ciphertext + tag
// Decrypt
let box = try AES.GCM.SealedBox(combined: ciphertext)
let decrypted = try AES.GCM.open(box, using: key)let sealedBox = try ChaChaPoly.seal(plaintext, using: key)
let combined = sealedBox.combined // Always non-optional for ChaChaPoly
let box = try ChaChaPoly.SealedBox(combined: combined)
let decrypted = try ChaChaPoly.open(box, using: key)let header = Data("v1".utf8)
let sealedBox = try AES.GCM.seal(
plaintext, using: key, authenticating: header
)
let decrypted = try AES.GCM.open(
sealedBox, using: key, authenticating: header
)| Size | Use |
|---|---|
| AES-128-GCM; adequate for most uses |
| AES-192-GCM; uncommon |
| AES-256-GCM or ChaChaPoly; recommended default |
let key = SymmetricKey(size: .bits256)let key = SymmetricKey(data: existingKeyData)let signingKey = P256.Signing.PrivateKey()
let publicKey = signingKey.publicKey
// Sign
let signature = try signingKey.signature(for: data)
// Verify
let isValid = publicKey.isValidSignature(signature, for: data)// Export
let der = signingKey.derRepresentation
let pem = signingKey.pemRepresentation
let x963 = signingKey.x963Representation
let raw = signingKey.rawRepresentation
// Import
let restored = try P256.Signing.PrivateKey(derRepresentation: der)let signingKey = Curve25519.Signing.PrivateKey()
let publicKey = signingKey.publicKey
// Sign
let signature = try signingKey.signature(for: data)
// Verify
let isValid = publicKey.isValidSignature(signature, for: data)rawRepresentation| Curve | Signature Scheme | Key Size | Typical Use |
|---|---|---|---|
| P256 | ECDSA | 256-bit | General purpose; Secure Enclave support |
| P384 | ECDSA | 384-bit | Higher security requirements |
| P521 | ECDSA | 521-bit | Maximum NIST security level |
| Curve25519 | Ed25519 | 256-bit | Fast; simple API; no Secure Enclave |
// Alice
let aliceKey = P256.KeyAgreement.PrivateKey()
// Bob
let bobKey = P256.KeyAgreement.PrivateKey()
// Alice computes shared secret
let sharedSecret = try aliceKey.sharedSecretFromKeyAgreement(
with: bobKey.publicKey
)
// Derive a symmetric key using HKDF
let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(
using: SHA256.self,
salt: Data("salt".utf8),
sharedInfo: Data("my-app-v1".utf8),
outputByteCount: 32
)sharedSecretsymmetricKeylet aliceKey = Curve25519.KeyAgreement.PrivateKey()
let bobKey = Curve25519.KeyAgreement.PrivateKey()
let sharedSecret = try aliceKey.sharedSecretFromKeyAgreement(
with: bobKey.publicKey
)
let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(
using: SHA256.self,
salt: Data(),
sharedInfo: Data("context".utf8),
outputByteCount: 32
)SharedSecretSymmetricKey| Method | Standard | Use |
|---|---|---|
| HKDF (RFC 5869) | Recommended default |
| ANSI X9.63 | Interop with X9.63 systems |
sharedInfoguard SecureEnclave.isAvailable else {
// Fall back to software keys
return
}let privateKey = try SecureEnclave.P256.Signing.PrivateKey()
let publicKey = privateKey.publicKey // Standard P256.Signing.PublicKey
let signature = try privateKey.signature(for: data)
let isValid = publicKey.isValidSignature(signature, for: data)let accessControl = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
[.privateKeyUsage, .biometryCurrentSet],
nil
)!
let privateKey = try SecureEnclave.P256.Signing.PrivateKey(
accessControl: accessControl
)dataRepresentation// Export
let blob = privateKey.dataRepresentation
// Restore
let restored = try SecureEnclave.P256.Signing.PrivateKey(
dataRepresentation: blob
)let seKey = try SecureEnclave.P256.KeyAgreement.PrivateKey()
let peerPublicKey: P256.KeyAgreement.PublicKey = // from peer
let sharedSecret = try seKey.sharedSecretFromKeyAgreement(
with: peerPublicKey
)// DON'T
let badKey = SymmetricKey(data: sharedSecret)
// DO -- derive with HKDF
let goodKey = sharedSecret.hkdfDerivedSymmetricKey(
using: SHA256.self,
salt: salt,
sharedInfo: info,
outputByteCount: 32
)// DON'T -- hardcoded nonce
let nonce = try AES.GCM.Nonce(data: Data(repeating: 0, count: 12))
let box = try AES.GCM.seal(data, using: key, nonce: nonce)
// DO -- let CryptoKit generate a random nonce (default behavior)
let box = try AES.GCM.seal(data, using: key)// DON'T -- manually strip tag and decrypt
// DO -- always use AES.GCM.open() or ChaChaPoly.open()
// which verifies the tag automatically// DON'T -- MD5/SHA1 for integrity or security
import CryptoKit
let bad = Insecure.MD5.hash(data: data)
// DO -- use SHA256 or stronger
let good = SHA256.hash(data: data)Insecure.MD5Insecure.SHA1// DON'T
UserDefaults.standard.set(key.rawBytes, forKey: "encryptionKey")
// DO -- store in Keychain
// See references/cryptokit-patterns.md for Keychain storage patterns// DON'T -- crash on simulator or unsupported hardware
let key = try SecureEnclave.P256.Signing.PrivateKey()
// DO
guard SecureEnclave.isAvailable else { /* fallback */ }
let key = try SecureEnclave.P256.Signing.PrivateKey()isValidAuthenticationCodedataRepresentationITSAppUsesNonExemptEncryption