[swift] Swift에서의 암호화 관련 코딩 패턴

Swift는 iOS 및 macOS 애플리케이션 개발을 위한 강력한 프로그래밍 언어입니다. 이 언어는 데이터 보안과 암호화 기능을 구현하는 데 있어서도 매우 효과적이며, 개발자들은 사용자 데이터를 안전하게 보호하기 위해 암호화를 구현할 수 있습니다.

이번 블로그 포스트에서는 Swift에서 많이 사용되는 암호화 관련 코딩 패턴을 알아보겠습니다. 아래는 일반적으로 사용되는 패턴의 몇 가지 예시입니다.

1. 해시 함수 사용하기

해시 함수는 주어진 입력값으로부터 고정된 크기의 출력값을 생성하는 알고리즘입니다. Swift에서는 다양한 해시 함수를 사용할 수 있으며, 이를 활용하여 개인정보를 안전하게 저장하거나 검증할 수 있습니다.

import CryptoKit

func hashString(_ string: String) -> String {
    let inputData = Data(string.utf8)
    let hashedData = SHA256.hash(data: inputData)
    let hashedString = hashedData.compactMap { String(format: "%02x", $0) }.joined()
    return hashedString
}

let password = "MySecretPassword"
let hashedPassword = hashString(password)
print("Hashed Password: \(hashedPassword)")

위의 예시에서는 CryptoKit 프레임워크의 SHA256.hash(data:) 메서드를 사용하여 입력 문자열을 해시값으로 변환합니다. 이후 hashedData를 16진수 문자열로 변환하고, hashedString에 저장하여 출력합니다.

2. 대칭키 암호화 사용하기

대칭키 암호화는 동일한 키를 암호화 및 복호화에 사용하는 암호화 방식입니다. Swift에서는 CryptoKit 프레임워크를 사용하여 대칭키 암호화를 구현할 수 있습니다.

import CryptoKit

func encryptWithSymmetricKey(_ plainText: String, symmetricKey: SymmetricKey) throws -> Data {
    let data = plainText.data(using: .utf8)!
    let sealedBox = try AES.GCM.seal(data, using: symmetricKey)
    return sealedBox.combined!
}

func decryptWithSymmetricKey(_ encryptedData: Data, symmetricKey: SymmetricKey) throws -> String {
    let sealedBox = try AES.GCM.SealedBox(combined: encryptedData)
    let decryptedData = try AES.GCM.open(sealedBox, using: symmetricKey)
    return String(data: decryptedData, encoding: .utf8)!
}

let plainText = "My Secret Message"
let symmetricKey = SymmetricKey(size: .bits256)
let encryptedData = try encryptWithSymmetricKey(plainText, symmetricKey: symmetricKey)
let decryptedText = try decryptWithSymmetricKey(encryptedData, symmetricKey: symmetricKey)

print("Encrypted Data: \(encryptedData)")
print("Decrypted Text: \(decryptedText)")

위의 코드에서는 SymmetricKey를 사용하여 AES.GCM 알고리즘을 기반으로한 대칭키 암호화를 수행합니다. encryptWithSymmetricKey 함수는 주어진 평문을 암호화하고 decryptWithSymmetricKey 함수는 암호문을 복호화합니다.

3. 공개키/비밀키 암호화 사용하기

공개키/비밀키 암호화는 서로 다른 키를 사용하여 암호화 및 복호화를 수행하는 암호화 방식입니다. Swift에서는 Security 프레임워크를 사용하여 공개키/비밀키 암호화를 구현할 수 있습니다.

import Security

func encryptWithPublicKey(_ plainText: String, publicKeyTag: String) throws -> Data {
    let plainTextData = Data(plainText.utf8)
    let publicKey = try getPublicKey(withTag: publicKeyTag)
    let encryptedData = try publicKey.encrypt(plainTextData, padding: .OAEP)
    return encryptedData
}

func decryptWithPrivateKey(_ encryptedData: Data, privateKeyTag: String) throws -> String {
    let privateKey = try getPrivateKey(withTag: privateKeyTag)
    let decryptedData = try privateKey.decrypt(encryptedData, padding: .OAEP)
    return String(data: decryptedData, encoding: .utf8)!
}

func getPublicKey(withTag tag: String) throws -> SecKey {
    let query: [String: Any] = [
        kSecClass as String: kSecClassKey,
        kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
        kSecAttrApplicationTag as String: tag.data(using: .utf8)!,
        kSecReturnRef as String: true
    ]
    
    var publicKey: CFTypeRef?
    let status = SecItemCopyMatching(query as CFDictionary, &publicKey)
    guard status == errSecSuccess else {
        throw NSError(domain: "com.example.crypto", code: Int(status), userInfo: nil)
    }
    return publicKey as! SecKey
}

func getPrivateKey(withTag tag: String) throws -> SecKey {
    let query: [String: Any] = [
        kSecClass as String: kSecClassKey,
        kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
        kSecAttrApplicationTag as String: tag.data(using: .utf8)!,
        kSecReturnRef as String: true
    ]
    
    var privateKey: CFTypeRef?
    let status = SecItemCopyMatching(query as CFDictionary, &privateKey)
    guard status == errSecSuccess else {
        throw NSError(domain: "com.example.crypto", code: Int(status), userInfo: nil)
    }
    return privateKey as! SecKey
}

// 공개키/비밀키 생성 및 사용 예시
let plainText = "My Secret Message"
let publicKeyTag = "com.example.crypto.publicKey"
let privateKeyTag = "com.example.crypto.privateKey"

// 공개키/비밀키 생성
let publicKey = try generatePublicKey(withTag: publicKeyTag)
let privateKey = try generatePrivateKey(withTag: privateKeyTag)

// 공개키/비밀키 저장
try saveKey(publicKey, withTag: publicKeyTag)
try saveKey(privateKey, withTag: privateKeyTag)

// 공개키/비밀키 사용
let encryptedData = try encryptWithPublicKey(plainText, publicKeyTag: publicKeyTag)
let decryptedText = try decryptWithPrivateKey(encryptedData, privateKeyTag: privateKeyTag)

print("Encrypted Data: \(encryptedData)")
print("Decrypted Text: \(decryptedText)")

위의 코드에서는 SecKey를 사용하여 Security 프레임워크를 통해 공개키/비밀키 암호화를 수행합니다. encryptWithPublicKey 함수는 주어진 평문을 암호화하고 decryptWithPrivateKey 함수는 암호문을 복호화합니다.

결론

Swift에서 암호화 기능을 활용하는 것은 사용자 데이터의 보안을 강화하고 개인정보를 안전하게 보호하는 데 큰 도움이 됩니다. 이 블로그 포스트에서는 Swift에서 암호화 관련 코딩 패턴 몇 가지를 살펴보았는데, 이러한 패턴을 사용하여 개인정보를 암호화하고 안전하게 저장하고 전송할 수 있습니다.

더 많은 암호화 기능 및 패턴을 배우고 싶다면 Swift CryptoKit documentation을 확인해 보세요.