Cryptography in Swift (iOS/macOS): Encryption and Hashing
Data security is a key aspect of iOS and macOS development. Swift provides powerful tools for cryptographic protection: from the built-in CryptoKit framework (starting with iOS 13 / macOS 10.15) to the low-level CommonCrypto (C library). In this article, we will cover the main operations: symmetric encryption (AES), asymmetric encryption (RSA), hashing (SHA-256), and message authentication (HMAC).
1. Project Setup
Using CryptoKit requires no additional configuration — it is part of the Foundation standard library. If you are working with CommonCrypto, add it to the Bridging-Header (for Swift + ObjC) or import the module directly:
// For CommonCrypto in Swift 5+ you can use:import CommonCrypto// Or configure a module map (modulemap)2. Symmetric Encryption (AES-GCM) with CryptoKit
CryptoKit provides a high-level API for AES in GCM mode (Galois/Counter Mode) — a secure and simple way to encrypt.
import CryptoKitimport Foundation
// Function to encrypt a stringfunc encryptString(_ plaintext: String, using key: SymmetricKey) throws -> Data { let plaintextData = plaintext.data(using: .utf8)! let sealedBox = try AES.GCM.seal(plaintextData, using: key) return sealedBox.combined! // combined = nonce + ciphertext + tag}
// Function to decryptfunc decryptData(_ combinedData: Data, using key: SymmetricKey) throws -> String { let sealedBox = try AES.GCM.SealedBox(combined: combinedData) let decryptedData = try AES.GCM.open(sealedBox, using: key) return String(data: decryptedData, encoding: .utf8)!}
// Usage examplelet key = SymmetricKey(size: .bits256) // 256-bit keylet original = "Secret message for iOS"let encrypted = try encryptString(original, using: key)print("Encrypted: \\(encrypted.base64EncodedString())")
let decrypted = try decryptData(encrypted, using: key)print("Decrypted: \\(decrypted)")Important: SymmetricKey is generated randomly. For a real application, the key should be stored in Keychain or use Secure Enclave.
3. Hashing (SHA-256) and HMAC
Hashing is a one-way function, essential for data integrity verification and password storage. CryptoKit supports SHA-256, SHA-384, SHA-512.
import CryptoKit
func sha256Hash(of data: Data) -> String { let digest = SHA256.hash(data: data) return digest.compactMap { String(format: "%02x", $0) }.joined()}
// Example for a stringlet message = "Hello, Swift Crypto!"let hash = sha256Hash(of: message.data(using: .utf8)!)print("SHA-256: \\(hash)")For message authentication (HMAC), use HMAC with a key:
func hmacSHA256(key: SymmetricKey, data: Data) -> Data { let authenticationCode = HMAC<SHA256>.authenticationCode(for: data, using: key) return Data(authenticationCode)}
let hmacKey = SymmetricKey(size: .bits256)let hmacResult = hmacSHA256(key: hmacKey, data: "Important data".data(using: .utf8)!)print("HMAC: \\(hmacResult.base64EncodedString())")4. Asymmetric Encryption (RSA) via Security framework
For RSA, use the Security framework (SecKey). CryptoKit does not directly support RSA, but you can combine approaches.
import Security
// Generate RSA key pair (2048 bits)func generateRSAKeyPair() -> (privateKey: SecKey, publicKey: SecKey)? { let attributes: [String: Any] = [ kSecAttrKeyType as String: kSecAttrKeyTypeRSA, kSecAttrKeySizeInBits as String: 2048, kS