Cryptography in Swift (iOS/macOS): Encryption and Hashing
In modern iOS and macOS development, data security is one of the key priorities. Apple provides powerful built-in tools for cryptographic protection: from simple hashing to asymmetric encryption. In this article, we will look at how to use CryptoKit (recommended framework starting from iOS 13 / macOS 10.15) and the classic CommonCrypto to solve typical tasks: encryption, hashing, and data authentication.
Basic Concepts
Before moving to code, let's understand the terms:
- Symmetric encryption — one key is used for both encryption and decryption (e.g., AES).
- Asymmetric encryption — a pair of keys: public (for encryption) and private (for decryption).
- Hashing — irreversible transformation of data into a fixed-length string (SHA-256).
- HMAC — hash-based message authentication code using a key.
1. Hashing with CryptoKit
CryptoKit is a modern Swift framework that makes cryptography simple and secure. The SHA256 structure is used for hashing.
import CryptoKit
func hashString(_ input: String) -> String { let inputData = Data(input.utf8) let hashed = SHA256.hash(data: inputData) return hashed.compactMap { String(format: "%02x", $0) }.joined()}
// Example usagelet password = "MySecurePass123"let hash = hashString(password)print("SHA-256 hash: \\(hash)")SHA384, SHA512, and SHA1 (the latter only for compatibility) are also available.
2. HMAC (Message Authentication)
HMAC adds a key to the hash, protecting against forgery. In CryptoKit, this is implemented via HMAC with the algorithm specified:
import CryptoKit
func hmacSHA256(key: SymmetricKey, message: String) -> String { let messageData = Data(message.utf8) let code = HMAC<SHA256>.authenticationCode(for: messageData, using: key) return code.compactMap { String(format: "%02x", $0) }.joined()}
// Key generationlet key = SymmetricKey(size: .bits256)let hmac = hmacSHA256(key: key, message: "Important message")print("HMAC: \\(hmac)")3. Symmetric Encryption (AES-GCM)
AES-GCM is a modern encryption mode that provides both confidentiality and authentication (prevents data tampering). CryptoKit supports it out of the box.
import CryptoKit
func encryptAESGCM(plainText: String, key: SymmetricKey) throws -> Data { let plainData = Data(plainText.utf8) let sealedBox = try AES.GCM.seal(plainData, using: key) return sealedBox.combined! // combined = nonce + ciphertext + tag}
func decryptAESGCM(encryptedData: Data, key: SymmetricKey) throws -> String { let sealedBox = try AES.GCM.SealedBox(combined: encryptedData) let decryptedData = try AES.GCM.open(sealedBox, using: key) return String(data: decryptedData, encoding: .utf8)!}
// Examplelet key = SymmetricKey(size: .bits256)let originalText = "Secret data"
do { let encrypted = try encryptAESGCM(plainText: originalText, key: key) let decrypted = try decryptAESGCM(encryptedData: encrypted, key: key) print("Decrypted: \\(decrypted)")} catch { print("Error: \\(error)")}Important: combined includes everything needed for decryption (nonce, ciphertext, tag). Store it together with the encrypted data.
4. Asymmetric Encryption (RSA) via CommonCrypto
For RSA, CryptoKit does not provide a direct API, but you can use Security.framework and CommonCrypto
Also in library
Task Queues for TypeScript: Bull, Bee-Queue, and Asynchronous Processing
Winston for JavaScript (Node.js): Complete Guide with Examples
Creating CLI Applications in Node.js: Commander and Yargs Frameworks
C++ Task Scheduler: Creating and Managing Tasks
Working with Excel in PHP: PhpSpreadsheet and OpenSpout Libraries