티스토리 뷰
안녕하세요.
이번엔 이론적인 내용을 이야기 해볼까 합니다.
* 해당 포스트는 CryptoKit 을 사용합니다. (iOS 13.0 이상만 가능)
보안 회사에서 일할때 소금? 이야기를 많이 들었는데
오늘은 이게 뭔지 그리고 어떤 느낌으로 사용되는지 까지 해보도록 하겠습니다.
* 그래서 소금(Salt)이 뭔가요?
- 보안에서 말하는 소금이란 사용자가 자신의 데이터를 Hash로 만들기 전에 데이터를 들키지 않게 하기 위해 넣는 임의의 데이터를 의미합니다.
- Hash는 단방향 암호화 (복호화가 불가능한 데이터)이지만 같은데이터로 Hash값를 제작하면 같은 Hash 값이 나오게 되기때문에 이를 통해 원본 데이터를 유츄해보는 것은 이론적으로 가능합니다.
- 그래서 유추할수없도록 가짜 데이터를 추가하는것이라고 합니다. (보통 사용자마다 다른 소금을 사용한다고 합니다.)
* 번외 후추(Pepper)는 뭔가요?
- 소금이 사용자마다 다른 소금이라면 후추는 서버(관리자)만이 사용할수있는 특별 비밀 데이터입니다.(주방장의 비밀레시피?)
- 후추를 통해 사용자의 데이터를 서버에서 더 안전하게 저장하기 위해 사용되며 사용자마다 동일한 후추를 사용한다고 합니다.
- 후추는 소금과 달리 유출되면 여러 사람의 데이터가 위험하기 때문에 굉장히 안전한 장소에만 보관되고 소금처럼 개인 단위로 저장하지 않는다고 합니다.
결국 비슷한데 사용자마다 다르냐 같냐의 차이로 소금과 후추로 나뉘는 것 같네요.
아무튼 이걸 하려던게 아니라
그래서 이걸 어떻게 구현하는지 알아봅시다.
생각보다 간단한데
- 내가 사용할 소금 만들기
- 내 데이터에 소금 합치기
- 그걸로 Hash 만들기
이제 swift 에서 제공되는 친구들로 한단계씩 만들어봅시다.
1. 내가 사용할 소금 만들기
- 놀랍게도 좋은 함수를 제공해주고 있습니다.
- SecRandomCopyBytes 를 사용해서 소금을 만들어봅시다.
let saltLength = 16 // 소금 길이
var saltData = Data(count: saltLength) // 소금을 만들어 담을 공간 생성
// 빈 소금통이 잘 만들어졌는지 확인
print("Empty Salt Data : \(saltData.base64EncodedString())")
// 소금통 채우기 (랜덤값 채우기)
let makeSaltResult = saltData.withUnsafeMutableBytes{bytes in
SecRandomCopyBytes(kSecRandomDefault, saltLength, bytes.baseAddress!)
}
// 랜덤값이 잘 들어갔는지 확인
if makeSaltResult == errSecSuccess{// 잘 만들어졌는지
// 소금 값 확인
print("Salt Data : \(saltData.base64EncodedString())")
}
- 함수 이름이 길어 보이는 것 뿐 사실 내용을 따지면 별로 어렵지 않습니다.
- 소금을 넣을 통을 만들고 소금을 랜덤으로 만든다 이 의미입니다.
2. 내 데이터에 소금 합치기
- 저는 모두의 예시인 "Hello world"를 이용해보겠습니다.
- swift 에서는 복잡하게 할 필요없이 이런 식으로 합치는게 가능합니다.
let myData = "Hello world".data(using: .utf8)!
let mySecretData : Data = myData+saltData // 내 데이터와 소금 합치기
3. 그걸로 Hash 만들기
- CryptoKit 함수를 불러와야하기때문에 코드 맨위에 아래 한줄을 먼저 추가해줍니다.
import CryptoKit // Apple에서 제공해주는 친구입니다.
- 이 친구가 Hash 를 만드는 함수를 제공해주는데 저는 SHA256으로 만들어보겠습니다.
func makeHash(data:Data) -> SHA256Digest{
return SHA256.hash(data: data) // 데이터 해쉬값 만들기
}
- 보면 리턴 값이 굉장히 특이한데 이게 Apple 측 설명을 보면 아래처럼 되어있습니다.
- 아무튼 그래서 이걸 서버에 보내든 저희가 스트링으로 확인을 하든 그래야하는데 저 타입이면 곤란하기 때문에 바꿔봅시다.
- 참고로 그냥 .description 하면 결과가 아래처럼 나옵니다.
- 이거 말고 이렇게 뜨는게 있는데 이걸로 한번 만들어봅시다.
print(makeHash(data:mySecretData).compactMap { String(format: "%02x", $0) }.joined())
- 이러면 이제 SHA256 digest 가 붙어 있지 않은 상태로 원본 값이 String 으로 나오게 됩니다.
소금이 매번 달라지기 때문에
매번 Hash 함수를 통해 나오는 값이 달라지는 걸 알 수 있습니다.
오늘은 개인적으로 궁금했던 부분을 이론적으로 공부하고
Apple의 CryptoKit 을 통해 간단히 구현을 해봤습니다.

글이 많이 부족하긴 하지만
저처럼 이 부분에 대해 궁금하실 분들을 위해 한번 올려봅니다.
누군가에게 도움이 되었으면 좋겠네요.
오늘도 파이팅입니다.
'iOS개발 > Swift 기본' 카테고리의 다른 글
Swift iOS 저장소 알아보기 FileManager 편 (0) | 2025.06.12 |
---|---|
Swift Cryptokit 으로 대칭/비대칭 키를 알아보자 (+PKI) (0) | 2025.05.27 |
Swift public / private 외 다른 접근 제어자 (0) | 2024.08.29 |
iOS KeyChain 속성 모음 (0) | 2024.07.23 |
App Groups 에 대해 알아보자 (0) | 2024.07.19 |