Криптография в Swift (iOS/macOS): шифрование и хеширование
В современной разработке под iOS и macOS безопасность данных — один из ключевых приоритетов. Apple предоставляет мощные встроенные инструменты для криптографической защиты: от простого хеширования до асимметричного шифрования. В этой статье мы рассмотрим, как использовать CryptoKit (рекомендованный фреймворк начиная с iOS 13 / macOS 10.15) и классический CommonCrypto для решения типовых задач: шифрование, хеширование и аутентификация данных.
Основные понятия
Прежде чем перейти к коду, разберёмся с терминами:
- Симметричное шифрование — один ключ используется и для шифрования, и для расшифровки (например, AES).
- Асимметричное шифрование — пара ключей: публичный (для шифрования) и приватный (для расшифровки).
- Хеширование — необратимое преобразование данных в строку фиксированной длины (SHA-256).
- HMAC — код аутентификации сообщения на основе хеша с использованием ключа.
1. Хеширование с помощью CryptoKit
CryptoKit — современный Swift-фреймворк, который делает криптографию простой и безопасной. Для хеширования используется структура SHA256.
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()
}
// Пример использования
let password = "MySecurePass123"
let hash = hashString(password)
print("SHA-256 хеш: \(hash)")
Также доступны SHA384, SHA512 и SHA1 (последний — только для совместимости).
2. HMAC (аутентификация сообщения)
HMAC добавляет ключ к хешу, что защищает от подделки. В CryptoKit это реализовано через HMAC с указанием алгоритма:
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()
}
// Генерация ключа
let key = SymmetricKey(size: .bits256)
let hmac = hmacSHA256(key: key, message: "Важное сообщение")
print("HMAC: \(hmac)")
3. Симметричное шифрование (AES-GCM)
AES-GCM — современный режим шифрования, который обеспечивает как конфиденциальность, так и аутентификацию (предотвращает подмену данных). CryptoKit поддерживает его из коробки.
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)!
}
// Пример
let key = SymmetricKey(size: .bits256)
let originalText = "Секретные данные"
do {
let encrypted = try encryptAESGCM(plainText: originalText, key: key)
let decrypted = try decryptAESGCM(encryptedData: encrypted, key: key)
print("Расшифровано: \(decrypted)")
} catch {
print("Ошибка: \(error)")
}
Важно: combined включает всё необходимое для расшифровки (nonce, ciphertext, tag). Храните его вместе с зашифрованными данными.
4. Асимметричное шифрование (RSA) через CommonCrypto
Для RSA CryptoKit не предоставляет прямого API, но можно использовать Security.framework и CommonCrypto. Ниже — пример шифрования публичным ключом.
import Security
func encryptRSA(plainText: String, publicKey: SecKey) -> Data? {
guard let plainData = plainText.data(using: .utf8) else { return nil }
var error: Unmanaged<CFError>?
guard let cipherData = SecKeyCreateEncryptedData(
publicKey,
.rsaEncryptionPKCS1,
plainData as CFData,
&error
) as Data? else {
print("О