Что такое CryptoKit и зачем она нужна?
CryptoKit — это фреймворк для криптографических операций, разработанный компанией Apple и встроенный непосредственно в экосистему Swift. Он доступен начиная с iOS 13, macOS 10.15, watchOS 6 и tvOS 13. В отличие от сторонних библиотек, CryptoKit является нативным решением, что гарантирует высокую производительность, безопасность и полную интеграцию с системой управления ключами Secure Enclave.
Зачем нужна CryptoKit? В современной разработке приложений безопасность данных выходит на первый план. CryptoKit предоставляет разработчикам простой, но мощный интерфейс для:
- Хеширования данных (SHA-256, SHA-384, SHA-512)
- Симметричного шифрования (AES-GCM, ChaCha20-Poly1305)
- Асимметричного шифрования (Curve25519, P-256, P-384, P-521)
- Цифровых подписей (EdDSA, ECDSA)
- Генерации криптостойких случайных чисел
- Обмена ключами (Diffie-Hellman на эллиптических кривых)
Библиотека спроектирована так, чтобы минимизировать ошибки разработчика: она использует безопасные реализации по умолчанию, автоматически управляет памятью и не позволяет использовать устаревшие или небезопасные алгоритмы (например, MD5 или SHA-1 для подписей).
Установка CryptoKit
Так как CryptoKit является частью стандартной библиотеки Apple, не требуется установка через менеджеры пакетов (CocoaPods, Swift Package Manager или Carthage). Всё, что нужно — это проект с минимальной целью развертывания iOS 13+ или macOS 10.15+.
Важно: Если вы разрабатываете под более старые версии ОС, CryptoKit недоступен. В таком случае используйте CommonCrypto (C-уровень) или сторонние библиотеки (например, CryptoSwift).
Для проверки доступности CryptoKit в коде используйте:
import CryptoKit
if #available(iOS 13.0, macOS 10.15, *) {
// Ваш код с CryptoKit
} else {
// Fallback на CommonCrypto
}
Быстрый старт с примером кода
Рассмотрим простейший пример: хеширование строки и симметричное шифрование.
import CryptoKit
import Foundation
// 1. Хеширование
let inputString = "Hello, CryptoKit!"
let inputData = Data(inputString.utf8)
let hash = SHA256.hash(data: inputData)
print("SHA256 хеш: \(hash.compactMap { String(format: "%02x", $0) }.joined())")
// 2. Симметричное шифрование (AES-GCM)
let key = SymmetricKey(size: .bits256) // Генерация 256-битного ключа
let plaintext = "Секретное сообщение".data(using: .utf8)!
do {
let sealedBox = try AES.GCM.seal(plaintext, using: key)
print("Зашифрованные данные: \(sealedBox.ciphertext.base64EncodedString())")
// Расшифровка
let openedBox = try AES.GCM.open(sealedBox, using: key)
let decryptedString = String(data: openedBox, encoding: .utf8)!
print("Расшифрованное сообщение: \(decryptedString)")
} catch {
print("Ошибка шифрования: \(error)")
}
Основные методы и функции CryptoKit
Ниже представлены 10 ключевых функций CryptoKit с подробным описанием, параметрами и примерами.
1. SHA256.hash(data:)
Описание: Вычисляет SHA-256 хеш от переданных данных. Возвращает объект SHA256Digest.
Параметры:
data: Data— исходные данные для хеширования.
Пример:
let data = "Пример данных".data(using: .utf8)!
let digest = SHA256.hash(data: data)
print(digest.description) // Вывод: SHA256 digest: 8f4343... (64 символа)
2. SHA384.hash(data:)
Описание: Аналогично SHA256, но использует 384-битный дайджест. Более безопасен, но медленнее.
Параметры: те же, что и SHA256.
Пример:
let digest384 = SHA384.hash(data: data)
print("SHA384: \(digest384)")
3. SHA512.hash(data:)
Описание: 512-битный хеш. Максимальная безопасность среди SHA-2 семейства.
Пример:
let digest512 = SHA512.hash(data: data)
print("SHA512: \(digest512)")
4. AES.GCM.seal(_:using:nonce:)
Описание: Шифрует данные с использованием алгоритма AES в режиме GCM (Galois/Counter Mode). Обеспечивает аутентификацию данных.
Параметры:
plaintext: Data— открытый текст.using: SymmetricKey— симметричный ключ (128, 192 или 256 бит).nonce: AES.GCM.Nonce?— опциональный nonce (12 байт). Если не указан, генерируется автоматически.
Возвращает: AES.GCM.SealedBox — содержит зашифрованный текст, тег аутентификации и nonce.
Пример:
let key = SymmetricKey(size: .bits256)
let plaintext = Data("Конфиденциально".utf8)
let sealedBox = try AES.GCM.seal(plaintext, using: key)
// sealedBox.ciphertext, sealedBox.tag, sealedBox.nonce
5. AES.GCM.open(_:using:)
Описание: Расшифровывает данные, проверяя аутентификацию. Если данные были изменены, выбрасывает ошибку.
Параметры:
sealedBox: AES.GCM.SealedBox— зашифрованный контейнер.using: SymmetricKey— тот же ключ, что использовался при шифровании.
Пример:
let decryptedData = try AES.GCM.open(sealedBox, using: key)
print(String(data: decryptedData, encoding: .utf8)!)
6. ChaChaPoly.seal(_:using:nonce:)
Описание: Шифрование с использованием алгоритма ChaCha20-Poly1305. Альтернатива AES-GCM, часто быстрее на мобильных устройствах.
Параметры: аналогичны AES.GCM.seal.
Пример:
let chachaKey = SymmetricKey(size: .bits256)
let chachaBox = try ChaChaPoly.seal(plaintext, using: chachaKey)
7. Curve25519.KeyAgreement.privateKey
Описание: Генерирует закрытый ключ для обмена ключами по протоколу X25519 (Diffie-Hellman на Curve25519).
Параметры: нет (инициализатор).
Пример:
let alicePrivateKey = Curve25519.KeyAgreement.PrivateKey()
let alicePublicKey = alicePrivateKey.publicKey
// Отправляем alicePublicKey Бобу
8. Curve25519.KeyAgreement.sharedSecretFromKeyAgreement(with:)
Описание: Вычисляет общий секрет на основе своего закрытого ключа и публичного ключа другой стороны.
Параметры:
publicKeyShare: Curve25519.KeyAgreement.PublicKey— публичный ключ собеседника.
Пример:
let bobPrivateKey = Curve25519.KeyAgreement.PrivateKey()
let sharedSecret = try alicePrivateKey.sharedSecretFromKeyAgreement(with: bobPrivateKey.publicKey)
// sharedSecret — это SharedSecret, из которого можно получить симметричный ключ
9. P256.Signing.PrivateKey() и signature(for:)
Описание: Создание цифровой подписи с использованием эллиптической кривой P-256 (ECDSA).
Параметры:
for: Data— данные для подписи (обычно хеш).
Пример:
let signingKey = P256.Signing.PrivateKey()
let message = Data("Важный документ".utf8)
let signature = try signingKey.signature(for: message)
// signature — объект P256.Signing.ECDSASignature
10. P256.Signing.PublicKey. isValidSignature(_:for:)
Описание: Проверяет подпись для переданных данных.
Параметры:
signature: P256.Signing.ECDSASignature— подпись для проверки.for: Data— исходные данные.
Пример:
let publicKey = signingKey.publicKey
let isValid = publicKey.isValidSignature(signature, for: message)
print("Подпись валидна: \(isValid)")
Реальный практический пример использования
Рассмотрим сценарий: приложение для обмена зашифрованными сообщениями между двумя пользователями (Алисой и Бобом). Используем асимметричное шифрование для обмена ключами и симметричное — для самих сообщений.
import CryptoKit
import Foundation
// Шаг 1: Алиса генерирует свою пару ключей
let alicePrivateKey = Curve25519.KeyAgreement.PrivateKey()
let alicePublicKeyData = alicePrivateKey.publicKey.rawRepresentation
// Шаг 2: Боб генерирует свою пару ключей
let bobPrivateKey = Curve25519.KeyAgreement.PrivateKey()
let bobPublicKeyData = bobPrivateKey.publicKey.rawRepresentation
// Шаг 3: Обмен публичными ключами (в реальности через сеть)
// Алиса получает публичный ключ Боба
let bobPublicKey = try Curve25519.KeyAgreement.PublicKey(rawRepresentation: bobPublicKeyData)
// Шаг 4: Вычисление общего секрета
let sharedSecret = try alicePrivateKey.sharedSecretFromKeyAgreement(with: bobPublicKey)
// Шаг 5: Получение симметричного ключа из общего секрета
let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(
using: SHA256.self,
salt: Data(),
sharedInfo: Data(),
outputByteCount: 32
)
// Шаг 6: Шифрование сообщения
let message = "Привет, Боб! Это секретное сообщение."
let messageData = Data(message.utf8)
let sealedBox = try AES.GCM.seal(messageData, using: symmetricKey)
// Передача sealedBox (ciphertext + nonce + tag) Бобу
// Шаг 7: Боб расшифровывает
let bobSymmetricKey = sharedSecret.hkdfDerivedSymmetricKey(
using: SHA256.self,
salt: Data(),
sharedInfo: Data(),
outputByteCount: 32
)
let decryptedData = try AES.GCM.open(sealedBox, using: bobSymmetricKey)
let decryptedMessage = String(data: decryptedData, encoding: .utf8)!
print("Боб получил: \(decryptedMessage)")
Советы и типичные ошибки
Советы
- Всегда используйте аутентифицированное шифрование: AES-GCM и ChaCha20-Poly1305 проверяют целостность данных. Никогда не используйте режимы типа ECB или CBC, если не уверены в необходимости.
- Храните ключи в Keychain: Никогда не храните криптографи
Также в библиотеке
Конфигурация приложений Swift (iOS/macOS): лучшие практики и инструменты
Работа с XML в Java: DOM, SAX, StAX и JAXB
Jsoup для Java: полное руководство с примерами
WebSocket библиотеки Rust: Tokio-tungstenite и async-tungstenite для реального времени