[Swift] CryptoSwift 암호화 라이브러리 사용방법
- 오픈소스/Swift
- 2023. 6. 15.
CryptoSwift
크립토스위프트는 스위프트로 작성된 오픈 소스 암호화 라이브러리입니다. 이 강력한 라이브러리는 다양한 암호화 알고리즘을 제공하여 데이터 보호를 위한 안전하고 간편한 솔루션을 제공합니다. CryptoSwift은 스위프트 언어의 강력한 기능과 표현력을 활용하여 데이터 암호화, 해시 함수, HMAC, 인증 부호, AES, RSA 등 다양한 암호화 작업을 수행할 수 있습니다.
해당 라이브러리는 대칭 및 비대칭 암호화를 위한 AES, RSA, ChaCha20 등의 암호화 알고리즘을 제공합니다. 간편한 인터페이스를 통해 데이터를 안전하게 암호화하고 복호화할 수 있습니다.
다양한 해시 함수인 MD5, SHA1, SHA256, SHA512 등을 지원하여 데이터의 해시 값을 계산할 수 있습니다. 해시 함수를 사용하면 데이터의 무결성을 검증하거나 비밀번호를 안전하게 저장할 수 있습니다.
CryptoSwift은 HMAC (Hash-based Message Authentication Code)을 지원하여 메시지 무결성을 검증할 수 있습니다. 메시지에 대한 인증 부호를 생성하고 검증하는 기능을 제공합니다.
CryptoSwift은 인증 부호를 생성하는 다양한 알고리즘을 제공합니다. 인증 부호를 사용하면 데이터의 무결성을 보장하고 송신자의 신원을 확인할 수 있습니다.
AES 암호화
/*
AES (Advanced Encryption Standard)는 대칭형 암호화 알고리즘 중 하나로, 2001년에 미국 정부에서 표준으로 채택한 알고리즘입니다. AES는 기밀성을 제공하기 위해 데이터를 암호화하는 데 사용되며, 널리 사용되는 암호화 기법 중 하나입니다.
AES는 다음과 같은 특징을 가지고 있습니다:
1. 대칭형 암호화: AES는 대칭키 암호화 알고리즘입니다. 암호화와 복호화에 동일한 키를 사용하며, 키는 암호화를 수행하는 측과 복호화를 수행하는 측 사이에서 안전하게 공유되어야 합니다.
2. 블록 암호화: AES는 블록 단위로 데이터를 암호화합니다. 기본적으로 128비트 블록 크기를 사용하지만, 192비트와 256비트 블록 크기도 선택할 수 있습니다.
3. 키 길이: AES는 128비트, 192비트, 256비트의 키 길이를 지원합니다. 키의 길이에 따라 암호화 강도가 달라집니다.
4. 라운드: AES는 여러 라운드로 구성됩니다. 각 라운드에서는 키와 블록 데이터에 대한 연산이 수행되어 암호화 과정이 진행됩니다.
5. 안정성: AES는 현재까지 알려진 공격에 대해 안전한 암호화 알고리즘으로 알려져 있습니다. 충분한 키 길이와 적절한 구현이 보장되면 안전한 암호화를 제공합니다.
AES는 다양한 애플리케이션 및 시스템에서 보안 요구사항을 충족시키기 위해 사용됩니다. 예를 들어, 데이터 전송 중에 기밀성을 유지하거나, 데이터베이스에서 저장된 데이터를 보호하거나, 파일 암호화 및 디스크 암호화 등에 사용될 수 있습니다.
중요한 점은 AES는 암호화 자체만을 담당하므로, 키 관리, 인증 및 데이터 무결성 등의 추가 보안 기능이 필요할 수 있습니다. 이러한 요소들은 AES를 사용하는 애플리케이션에서 전체 보안 솔루션을 구축하기 위해 고려되어야 합니다.
*/
▼ 암호화할 메시지와 키를 입력받고 iv 값을 입력받습니다. Padding 값은 .pkcs7 방식을 사용합니다. 암호화된 코드는 base64 문자열로 만든 뒤 반환합니다.
import CryptoSwift
func encryptAES(message: String, key: String, iv: String) throws -> String {
let data = Data(message.utf8)
let keyData = Data(key.utf8)
let ivData = Data(iv.utf8)
let aes = try AES(key: keyData.bytes, blockMode: CBC(iv: ivData.bytes), padding: .pkcs7)
let encrypted = try aes.encrypt(data.bytes)
let encryptedData = Data(encrypted)
let base64String = encryptedData.base64EncodedString()
return base64String
}
▼ 다음은 복호화 하는 코드입니다. 암호화된 base64 문자열과 키, iv 값을 받아서 데이터를 복호화합니다. 만약 데이터 복호화에 실패하면 예외처리를 하는 코드가 포함되어있습니다.
func decryptAES(encryptedBase64: String, key: String, iv: String) throws -> String {
guard let data = Data(base64Encoded: encryptedBase64) else {
throw CryptoError.invalidBase64String
}
let keyData = Data(key.utf8)
let ivData = Data(iv.utf8)
let aes = try AES(key: keyData.bytes, blockMode: CBC(iv: ivData.bytes), padding: .pkcs7)
let decrypted = try aes.decrypt(data.bytes)
guard let decryptedData = Data(bytes: decrypted, count: decrypted.count) else {
throw CryptoError.decryptionFailed
}
guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
throw CryptoError.invalidDecryptedData
}
return decryptedString
}
▼ 다음은 예외처리를 위한 에러 케이스입니다.
- invalidBase64String: base64 문자열이 아닐 경우 에러
- decryptionFailed: 복호화 실패 에러
- invalidDecryptedData: 복호화된 데이터를 문자열로 변환 실패 에러
enum CryptoError: Error {
case invalidBase64String
case decryptionFailed
case invalidDecryptedData
}
▼ 다음은 위의 암호화 함수를 사용하는 예시입니다.
let message = "Hello, CryptoSwift!"
let key = "SecretKey12345678"
let iv = "InitializationVe"
do {
let encrypted = try encryptAES(message: message, key: key, iv: iv)
print("암호화된 문자열: \(encrypted)")
let decrypted = try decryptAES(encryptedBase64: encrypted, key: key, iv: iv)
print("복호화된 문자열: \(decrypted)")
} catch {
print("오류 발생: \(error)")
}
해시함수
/*
데이터 무결성: 해시 함수는 데이터의 무결성을 보장하는 데 사용됩니다. 데이터의 내용이 변경되지 않았는지를 확인하기 위해 원본 데이터의 해시 값을 계산하고 저장합니다. 데이터를 다시 검색할 때 해시 값을 다시 계산하고, 저장된 해시 값과 비교하여 데이터가 변경되었는지 여부를 확인할 수 있습니다.
암호학적 보안: 해시 함수는 암호화 기술에서 중요한 역할을 합니다. 비밀번호, 메시지 인증 코드 (MAC), 디지털 서명 등을 생성하는 데 사용됩니다. 안전한 해시 함수는 입력 데이터를 암호화된 고정 길이 해시 값으로 변환합니다. 이 해시 값은 원래 데이터를 역으로 복원할 수 없으며, 같은 입력에 대해서는 항상 동일한 해시 값을 생성합니다.
고유한 식별자 생성: 해시 함수는 고유한 식별자를 생성하는 데에도 사용됩니다. 예를 들어, 파일이나 데이터베이스의 고유한 식별자를 생성하기 위해 해시 함수를 사용할 수 있습니다. 해시 함수는 임의의 크기의 입력을 고정된 길이의 해시 값으로 매핑하므로, 동일한 입력에 대해서는 항상 동일한 해시 값을 반환합니다.
데이터 검색 및 인덱싱: 해시 함수는 데이터 검색을 빠르게 수행하는 데 사용됩니다. 해시 함수를 사용하여 데이터를 해시화하고, 이를 인덱스로 사용하여 데이터를 검색하면 빠른 검색 속도를 얻을 수 있습니다. 예를 들어, 해시 테이블은 키-값 쌍을 저장하고 빠른 키 기반 검색을 제공하기 위해 해시 함수를 사용합니다.
*/
▼ 다음은 sha256을 이용한 단방향 해시함수입니다. 16진수의 형태로 반환되며 특정 문자열에 항상 동일한 값을 보장합니다. 해시 함수는 암호학적 보안, 데이터 무결성, 데이터 검색 및 식별, 고유한 식별자 생성 등 다양한 목적으로 사용됩니다.
"ABCDEFG".sha256()
// e9a92a2ed0d53732ac13b031a27b071814231c8633c9f41844ccba884d482b16
HMAC
/*
HMAC은 "Hash-based Message Authentication Code"의 약자로, 해시 기반 메시지 인증 코드를 의미합니다. HMAC은 메시지의 무결성과 인증을 보장하기 위해 사용되는 암호학적 기법입니다.
HMAC은 해시 함수와 비밀 키를 사용하여 메시지에 대한 인증 태그를 생성합니다. 이 인증 태그는 메시지를 보낸 측과 수신 측 간의 상호 인증을 수행하고, 데이터의 변조 여부를 확인하기 위해 사용됩니다.
HMAC은 다음과 같은 특징을 가지고 있습니다:
1. 해시 함수 사용: HMAC은 일반적으로 안전한 해시 함수 (예: SHA-256)를 사용하여 메시지를 해시화합니다. 해시 함수는 임의의 길이의 데이터를 고정된 길이의 해시 값으로 변환하는 함수입니다.
2. 비밀 키 사용: HMAC은 비밀 키를 사용하여 메시지를 인증합니다. 이 비밀 키는 HMAC을 생성하고 검증하는 양측에서 미리 공유되어야 합니다. 키는 메시지 무결성과 인증을 위한 중요한 구성 요소입니다.
3. 중복성 방지: HMAC은 메시지와 키의 결합으로 인해 중복성이 제거됩니다. 같은 메시지에 대해서는 항상 동일한 HMAC 값이 생성되며, 다른 메시지에 대해서는 거의 동일한 HMAC 값을 생성할 가능성이 매우 낮습니다.
4. 단방향 함수: HMAC은 단방향 함수이므로, HMAC 값을 통해 원래 메시지를 역으로 복원할 수는 없습니다. HMAC 값은 비밀 키와 함께 유지되어야 하며, 누군가가 HMAC 값을 알더라도 원래 메시지를 알아낼 수 없습니다.
HMAC은 메시지 인증, 데이터 무결성 검사, 암호화된 비밀번호 저장 등 다양한 보안 요구사항에 사용됩니다. 주로 인터넷 프로토콜 (예: TLS, IPsec), 메시지 인증 시스템, 웹 애플리케이션 등에서 HMAC이 널리 사용됩니다. HMAC은 강력한 보안 기법으로 알려져 있으며, 안정성과 검증 가능성을 제공하여 데이터의 신뢰성을 보장합니다.
*/
▼ 다음 코드는 주어진 키와 메시지에 대한 HMAC 값을 계산하는 함수입니다. HMAC 값을 계산하여 16진수 문자열로 반환합니다. 반환타입은 옵셔널 스트링으로 만약 값이 정상적이지 않다면 nil 이 반환됩니다.
func calculateHMAC(key: Data, message: Data) -> String? {
do {
let hmac = try HMAC(key: key.bytes, variant: .sha2(.sha256)).authenticate(message.bytes)
let hmacData = Data(hmac)
let hmacString = hmacData.map { String(format: "%02x", $0) }.joined()
return hmacString
} catch {
print("HMAC 계산 오류: \(error)")
return nil
}
}
▼ 다음은 위의 함수를 이용해 HMAC 값을 계산하는 예시입니다.
// 사용 예시
let keyString = "SecretKey"
let messageString = "Hello, HMAC!"
if let keyData = keyString.data(using: .utf8), let messageData = messageString.data(using: .utf8) {
if let hmac = calculateHMAC(key: keyData, message: messageData) {
print("HMAC-SHA256 값: \(hmac)")
}
}
▼ 다음은 생성된 HMAC 값으로 검증하는 함수입니다. hex 값을 Data 로 변환해 해당 값이 동일한지 검증하고 이를 Bool 값으로 반환합니다.
func verifyHMAC(key: Data, message: Data, hmacString: String) -> Bool {
let hmacData = Data(hex: hmacString)
do {
let hmac = try HMAC(key: key.bytes, variant: .sha2(.sha256)).authenticate(message.bytes)
return hmacData == Data(hmac)
} catch {
print("HMAC 검증 오류: \(error)")
return false
}
}
▼ 다음 코드는 만들어진 HMAC 값을 이용해 검증하는 단계입니다. 메시지 검증에 성공하면 문자열을 출력합니다.
let keyString = "SecretKey"
let messageString = "Hello, HMAC!"
let originalHMACString = "af70cc41a492e85b08092acf18a6cc6ef9219e7a31b145e35b5acc5afcbe6fb4"
if let keyData = keyString.data(using: .utf8), let messageData = messageString.data(using: .utf8) {
if verifyHMAC(key: keyData, message: messageData, hmacString: originalHMACString) {
print("메시지 검증 성공!")
} else {
print("메시지 검증 실패.")
}
}
'오픈소스 > Swift' 카테고리의 다른 글
[Swift] SwiftGen 스위프트 다국어 Localizable 사용 방법 (0) | 2022.09.16 |
---|---|
[Swift] SwiftGen 스위프트 리소스 관리 사용 방법 (2) | 2022.09.01 |
[Swift] SwiftyUserDefaults 사용법 - 스위프트 NSUserDefaults API (0) | 2022.03.22 |