---
title: Chỉ dùng thuật toán mã hóa an toàn (CryptoKit)
impact: CRITICAL
impactDescription: Thuật toán MD5, SHA1, DES đã bị bẻ gãy và không đảm bảo bảo mật. Dữ liệu mã hóa bằng thuật toán yếu có thể bị giải mã bởi attacker.
tags: swift, ios, cryptography, cryptokit, security, hashing, encryption
---

## Chỉ dùng thuật toán mã hóa an toàn (CryptoKit)

Dùng Apple **CryptoKit** (iOS 13+) thay vì CommonCrypto cho mã hóa mới. Tránh hoàn toàn MD5, SHA1, DES, và chế độ ECB. Dùng AES-GCM hoặc ChaChaPoly cho encryption, SHA-256+ cho hashing.

**Incorrect (thuật toán yếu):**

```swift
import CommonCrypto

// !! MD5 - đã bị bẻ gãy, tìm collision dễ dàng
func md5Hash(_ string: String) -> String {
    let data = string.data(using: .utf8)!
    var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
    CC_MD5(data.bytes, CC_LONG(data.count), &digest)
    return digest.map { String(format: "%02x", $0) }.joined()
}

// !! SHA1 - không đủ bảo mật
func sha1Hash(_ data: Data) -> Data {
    var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
    data.withUnsafeBytes { CC_SHA1($0.baseAddress, CC_LONG(data.count), &digest) }
    return Data(digest)
}

// !! DES - key chỉ 56 bit, có thể brute force
func desEncrypt(_ data: Data, key: Data) -> Data? {
    return symmetric(data: data, key: key, algorithm: kCCAlgorithmDES, operation: kCCEncrypt)
}
```

**Correct (CryptoKit với thuật toán an toàn):**

```swift
import CryptoKit

// SHA-256 cho hashing dữ liệu (không phải password)
func sha256Hash(_ data: Data) -> String {
    let digest = SHA256.hash(data: data)
    return digest.map { String(format: "%02x", $0) }.joined()
}

// AES-GCM cho symmetric encryption (authenticated + encrypted)
func encryptData(_ data: Data, using key: SymmetricKey) throws -> Data {
    let sealedBox = try AES.GCM.seal(data, using: key)
    return sealedBox.combined!
}

func decryptData(_ encryptedData: Data, using key: SymmetricKey) throws -> Data {
    let sealedBox = try AES.GCM.SealedBox(combined: encryptedData)
    return try AES.GCM.open(sealedBox, using: key)
}

// Tạo key an toàn
func generateEncryptionKey() -> SymmetricKey {
    return SymmetricKey(size: .bits256)  // 256-bit AES key
}

// Cho password hashing - dùng bên server, trên iOS verify
// Dùng PBKDF2 nếu cần derive key từ password
func deriveKey(from password: String, salt: Data) -> SymmetricKey {
    let keyData = PKCS5.PBKDF2(password: Array(password.utf8),
                                salt: Array(salt),
                                iterations: 100_000,
                                keyLength: 32,
                                variant: .sha2(.sha256)).calculate()
    return SymmetricKey(data: Data(keyData))
}
```

**Approved vs Prohibited:**

| Mục đích | Nên dùng | Không dùng |
|---------|----------|------------|
| Hash | SHA-256, SHA-3, BLAKE2 | MD5, SHA-1 |
| Mã hóa | AES-GCM (256-bit), ChaChaPoly | DES, 3DES, AES-ECB |
| Chữ ký | P-256, P-384, Curve25519 | RSA < 2048-bit |

**Tools:** CryptoKit, Code Review, MobSF

