Cryptography in Swift (iOS/macOS): Encryption and Hashing
In modern iOS and macOS development, data security is a critical aspect. Swift provides powerful built-in tools for cryptography, ranging from the low-level CommonCrypto (C-API) to the modern framework CryptoKit (iOS 13+/macOS 10.15+). In this article, we will cover the main encryption and hashing methods available to a Swift developer.
1. Hashing
Hashing is a one-way transformation of data into a fixed-length string. It is used for data integrity verification and password storage (with salt).
Example with CryptoKit (SHA-256)
import CryptoKit
func hashSHA256(_ input: String) -> String { let inputData = Data(input.utf8) let hashed = SHA256.hash(data: inputData) return hashed.compactMap { String(format: "%02x", $0) }.joined()}
// Usagelet hash = hashSHA256("Hello, Swift!")print("SHA-256: \\(hash)")// Output: 8e3a... (64 characters)Example with CommonCrypto (MD5, deprecated)
Note: MD5 is not recommended for security but can be used for integrity checks.
import CommonCrypto
func md5Hash(_ input: String) -> String { let data = Data(input.utf8) var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH)) data.withUnsafeBytes { bytes in _ = CC_MD5(bytes.baseAddress, CC_LONG(data.count), &digest) } return digest.map { String(format: "%02x", $0) }.joined()}2. Symmetric Encryption (AES-GCM)
Symmetric encryption uses a single key for both encryption and decryption. CryptoKit provides a secure implementation of AES-GCM (Galois/Counter Mode).
Example of encryption and decryption with CryptoKit
import CryptoKit
func encryptAESGCM(plaintext: String, key: SymmetricKey) throws -> Data { let plaintextData = Data(plaintext.utf8) let sealedBox = try AES.GCM.seal(plaintextData, using: key) return sealedBox.combined! // combined = nonce + ciphertext + tag}
func decryptAESGCM(ciphertext: Data, key: SymmetricKey) throws -> String { let sealedBox = try AES.GCM.SealedBox(combined: ciphertext) let decryptedData = try AES.GCM.open(sealedBox, using: key) return String(data: decryptedData, encoding: .utf8)!}
// Usagelet key = SymmetricKey(size: .bits256) // 256-bit keylet encrypted = try encryptAESGCM(plaintext: "Secret message", key: key)let decrypted = try decryptAESGCM(ciphertext: encrypted, key: key)print("Decrypted: \\(decrypted)")3. Asymmetric Encryption (RSA)
Asymmetric encryption uses a key pair: a public key (for encryption) and a private key (for decryption). In iOS/macOS, Security.framework and SecKey are used for working with RSA.
Example of RSA key generation and encryption
import Security
func generateRSAKeyPair() -> (privateKey: SecKey, publicKey: SecKey)? { let attributes: [String: Any] = [ kSecAttrKeyType as String: kSecAttrKeyTypeRSA, kSecAttrKeySizeInBits as String: 2048, kSecPrivateKeyAttrs as String: [kSecAttrIsPermanent as String: false], kSecPublicKeyAttrs as String: [kSecAttrIsPermanent as String: false] ] guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, nil) else { return nil } let publicKey = SecKeyCopyPublicKey(privateKey)! return (privateKey, publicKey)}
func encryptRSA(plaintext: String, publicKey: SecKey) -> Data? { let plaintextData = Data(plaintext.utf8) var error: Unmanaged<CFError>? guard let ciphertext = SecKeyCreateEncryptedData( publicKey, .rsaEncryptionPKCS1, plaintextData as CFData, Also in library
ORM for Java: Comparison of Hibernate, MyBatis and JPA with Examples
Elasticsearch Client for Swift (iOS/macOS): Integration and Examples
ORM for TypeScript: comparison of TypeORM, Prisma and MikroORM
Vitest for TypeScript: Complete Guide with Examples