Swift Cryptokit 으로 대칭/비대칭 키를 알아보자 (+PKI)
안녕하세요.
이번 주제는 작성을 할까 말까 고민을 많이 했는데 개념이 낯선 것일뿐
코드 자체는 어려운게 아니기 때문에 최대한 쉽게 개념을 이해해보고 만들어 보도록 하겠습니다.
그래서 오늘의 주제는 대칭/비대칭키 만들고 활용해보기입니다.
비대칭키의 경우 PKI 처럼 공개키/개인키를 나누어 만들어 볼꺼에요.
* PKI 가 무엇인가요? (Public Key Infrastructure)
- 공개키 기반의 구조를 의미합니다.
- 즉 공개키 / 개인키를 사용해 암호화/복호화 를 하는 구조를 의미합니다.
- PKI 는 그래서 비대칭키 구조 를 기반으로 합니다. (암/복호화시 사용된 키가 다른 경우)
* 대칭키? 비대칭키 이건 뭔가요?
- 간단하게 그려보면 아래와 같습니다.
- 대칭키 구조 : 암/복호화시 같은 키를 사용한 경우
- 비대칭키 구조 : 암/복호화시 다른 키를 사용하는 경우
PKI 의 개념은 비대칭 구조를 기반으로 만들어졌다고 생각하시면 될 것 같습니다.
그래서 이걸 Apple에서 기본으로 제공해주시는 CryptoKit 으로 만들어보는게 오늘의 목적입니다.
(생각보다 간단하죠?)
그래서 코드를 시작하기전에 아래 한줄 먼저 추가하겠습니다.
import CryptoKit //ios 13.0이상만 가능
일단 대칭키부터 해볼까요?
대칭키는 생성부터 암복호화까지 CrptoKit 에서 지원하기때문에 암복호화까지 해보겠습니다.
* 대칭키 생성 및 암복호화
- 여기서 AES 는 대칭키 알고리즘 중 하나입니다.
print("Hello, Swift!")
// 암호화할 내용
let plainData = "Hello, Swift!".data(using: .utf8)
// 키 생성
let sysKey = SymmetricKey(size: .bits256)
// 키를 이용한 암호화
if let cryptBox = try? AES.GCM.seal(plainData!, using: sysKey){
// 암호화 성공시 데이터 출력(sealBox 라서 combine을 해야 Data 타입으로 바뀜)
print("Crypt Data : \(cryptBox.combined!.base64EncodedString())")
// 복호화 -> 암호화시 사용한 키를 넣어주세요.
if let decryptData = try? AES.GCM.open(cryptBox, using: sysKey){
// 복호화한 내용 출력
print(String(data: decryptData, encoding: .utf8)!)
}
}
* 실제 결과물
Hello, Swift!
Crypt Data : bLNmfBvO+Kw3sl59e29ZeGY1JeSIoa005sQhTlP3lilUurNnW9MLGBc=
Hello, Swift!
간단하죠? 명령어가 어색한 것 뿐이지 굉장히 간단합니다.
이제 비대칭 구조를 만들어볼께요.
* 비대칭 키 생성
// CryptoKit 은 ECC 를 기반으로 생성
// 암복호화용
let privateKey = P256.KeyAgreement.PrivateKey()
let publicKey = privateKey.publicKey
// 서명용
let privateSignKey = P256.Signing.PrivateKey()
let publicSignKey = privateSignKey.publicKey
- 자세히 보시면 키가 2가지 방법인데 이는 사용법에 따라 달라집니다.
- 암호화를 목적으로 하느냐 서명을 목적으로 하느냐로 나뉘게 됩니다.
- 공식 설명을 번역해서 보면 아래처럼 나옵니다.
- KeyAgreement : NIST P-256 타원 곡선 디피 헬만(ECDH) 키 교환을 수행하여 두 사용자 간의 공유 비밀을 생성하는 데 사용되는 메커니즘입니다.
- Signing : NIST P-256 타원 곡선 디지털 서명 알고리즘(ECDSA)을 사용하여 암호화 서명을 생성하거나 검증하는 데 사용되는 메커니즘입니다.
사용 목적이 다르기 때문에 원하시는걸로 선택하시면 될 것 같습니다.
아쉽게도 CryptoKit으로는 아직 암복호화 구현은 지원하지 않는다고 합니다.
(보통은 다른 오픈 소스 라이브러리를 사용한다고 합니다.)
그래서 저희는 CryptoKit이 지원하는 기능 중 서명을 생성 및 검증을 이용해보겠습니다.
서명이니 Signing 을 이용해서 만든 걸 활용해봅시다.
* 비대칭키 서명 생성 및 검증
// 서명용 키 생성
let privateSignKey = P256.Signing.PrivateKey()
let publicSignKey = privateSignKey.publicKey
// 메시지 준비
let plainData = "Hello Swift".data(using: .utf8)!
// 서명 생성
let makeSign = try! privateSignKey.signature(for: plainData)
print("서명 생성 결과: \(makeSign.derRepresentation.base64EncodedString())")
// 공개키로 서명 검증
let isValid = publicSignKey.isValidSignature(makeSign, for: plainData)
print("서명 검증 결과: \(isValid)")
* 실제 결과물
서명 생성 결과: MEUCIQDjwdgMfIxX0GSu1H8svGlo4Mgix63RbWBlyw/XLGLQowIgbTBNRopVTE9uipFh6qyLV15fyDVNXbX58lrg8xkcsV0=
서명 검증 결과: true
암복호화 쪽이 제공이 아직 안되는건 아쉽지만
서명이 가능하다는 것은 처음 알았습니다.
이번엔 우연히 접한 개념들을 CryptoKit 으로 만들어 봤습니다.
(간단하게 정리하려했는데 복잡해보이네요...)
저처럼 암복호화 부분을 잘 모르시거나 해메시는 분들에게
도움이 되었으면 좋겠습니다.

오늘도 파이팅입니다.