Криптография в Swift (iOS/macOS): шифрование и хеширование
Безопасность данных — ключевой аспект разработки под iOS и macOS. Swift предоставляет мощные инструменты для криптографической защиты: от встроенного фреймворка CryptoKit (начиная с iOS 13 / macOS 10.15) до низкоуровневого CommonCrypto (C-библиотека). В этой статье мы разберём основные операции: симметричное шифрование (AES), асимметричное (RSA), хеширование (SHA-256) и аутентификацию сообщений (HMAC).
1. Настройка проекта
Для использования CryptoKit дополнительных настроек не требуется — он входит в стандартную библиотеку Foundation. Если вы работаете с CommonCrypto, добавьте в Bridging-Header (для Swift + ObjC) или импортируйте модуль напрямую:
// Для CommonCrypto в Swift 5+ можно использовать:
import CommonCrypto
// Или настроить модульный мост (modulemap)
2. Симметричное шифрование (AES-GCM) с CryptoKit
CryptoKit предоставляет высокоуровневый API для AES в режиме GCM (Galois/Counter Mode) — безопасный и простой способ шифрования.
import CryptoKit
import Foundation
// Функция шифрования строки
func 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
}
// Функция дешифрования
func 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)!
}
// Пример использования
let key = SymmetricKey(size: .bits256) // 256-битный ключ
let original = "Секретное сообщение для iOS"
let encrypted = try encryptString(original, using: key)
print("Зашифровано: \(encrypted.base64EncodedString())")
let decrypted = try decryptData(encrypted, using: key)
print("Расшифровано: \(decrypted)")
Важно: SymmetricKey генерируется случайным образом. Для реального приложения ключ нужно хранить в Keychain или использовать Secure Enclave.
3. Хеширование (SHA-256) и HMAC
Хеширование — односторонняя функция, незаменимая для проверки целостности данных и хранения паролей. CryptoKit поддерживает 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()
}
// Пример для строки
let message = "Hello, Swift Crypto!"
let hash = sha256Hash(of: message.data(using: .utf8)!)
print("SHA-256: \(hash)")
Для аутентификации сообщений (HMAC) используйте HMAC с ключом:
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: "Важные данные".data(using: .utf8)!)
print("HMAC: \(hmacResult.base64EncodedString())")
4. Асимметричное шифрование (RSA) через Security framework
Для RSA используйте фреймворк Security (SecKey). CryptoKit не поддерживает RSA напрямую, но вы можете комбинировать подходы.
import Security
// Генерация пары ключей RSA (2048 бит)
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]
]
var error: Unmanaged<CFError>?
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
print("Ошибка генерации: \(error!.takeRetainedValue())")
return nil
}
let publicKey = SecKeyCopyPublicKey(privateKey)!
return