์ฉ์ด ์ ๋ฆฌ
- key : ํด์ฑ๋๊ธฐ ์ ์ ๊ฐ
- digest : ํด์ฑ๋ ํ์ ๊ฐ
- rainbow table : ์ฌ๋ฌ ๊ฐ๋ค์ ๋์ ํด๋ณด๋ฉด์ ์ป์ ๋ค์ด์ ์คํธ๋ค์ ๋ชจ์๋์ ํ ์ด๋ธ
ํด์ ํจ์
- ๋จ๋ฐฉํฅ ํจ์๋ก๋ง ์๋ํจ
- input ๊ฐ์ด ์์ฃผ ๋ฏธ์ธํ๊ฒ ๋ฌ๋ผ์ ธ๋ output ๊ฐ์ ์ ํ ๋ฌ๋ผ์ง → Avalanche Effect
- ํด์ ํจ์์ ์๋ ์ค๊ณ ๋ชฉ์ ์ ๋น ๋ฅธ ๊ฒ์์ ์ํจ์ (OS ๋ถ๋ถ ํด์ํ ์ด๋ธ ์ฐธ๊ณ )
- input ๊ฐ์ด ๊ฐ์ผ๋ฉด output ๊ฐ์ ํญ์ ๊ฐ์ (์ฆ ํจ์๋ก์ ๊ธฐ๋ฅํจ)
ํด์ ํจ์์ ์ํ์ฑ
- input์ด ๊ฐ์ผ๋ฉด output์ ํญ์ ๊ฐ์ผ๋ฏ๋ก ํด์ฑ๋ ๋ฌธ์์ด์ ์๋ฌธ์ ๋ ์ธ๋ณด์ฐ ํ ์ด๋ธ์์ ์ฐพ์ ์ํ์ฑ์ด ์กด์ฌํจ.
- brute-force
- ์๋ ํด์ ํจ์๊ฐ ๋น ๋ฅธ ๊ฒ์์ ์ํด ์ค๊ณ๋์๋ค ๋ณด๋ ์ค์ ๋ฐํ์์์์ ์๋๋ ๋น ๋ฅธ ๊ฑด ๋ง์. ํ์ง๋ง ๊ทธ๋ ๋ค๋ฉด ํด์ปค๋ ๋๊ฐ์ด ๋น ๋ฅด๊ฒ ๊ฐ์ ์ป์ ์ ์์.
์ํ์ฑ ๋ณด์ ๋ฐฉ๋ฒ
- salt
- ํจ๊ณผ์ ์ธ ์ํธ : ์ฌ์ฉ์๋ณ ๊ณ ์ ์ ์ํธ๋ฅผ ๊ฐ์ ธ์ผ ํ๋ฉฐ ์ํธ์ ๊ธธ์ด๋ 32๋นํธ ์ด์์ด์ด์ผ ํจ
- key stretching
- ์ ๋ ฅ๊ฐ -ํด์ฑ→ ๋ค์ด์ ์คํธ -ํด์ฑ→ ๋ค์ด์ ์คํธ’ -ํด์ฑ→ ๋ค์ด์ ์คํธ’’ ๋ฐฉ์์ผ๋ก ์ฌ๋ฌ๋ฒ ํด์ฑํ๋ ๊ฒ
ํด์ฑ ์๊ณ ๋ฆฌ์ฆ ์ข ๋ฅ
MD5 ๊ณ์ด
- ๊ฐ์ฅ ์ฝ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅํ์ง๋ง ์์ ํ์ง ์์
- ํด์๊ฐ์ด ๋จ์ํ๊ฒ ๋ฐ๋๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๊ตฌ๊ธ๋ง์ผ๋ก ์๋ณธ ๊ฐ์ ์ฐพ๊ธฐ ์ฌ์
- ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ๊ถ์ฅ๋จ
SHA ๊ณ์ด
- SHA-0 : ์์์ด ๋ง์ด ๋ ธ์ถ๋จ. ๋ณด์์ด ๊ฑฐ์ ์ ์ฉ๋์ง ์์. ์ฌ์ฉํ์ง ์๋ ๊ฒ์ ๊ถ์ฅ.
- SHA-1 : SHA-0์์ ๊ฐ์ ๋ ๋ฒ์
- SHA-2 : SHA-256์ด ์ฌ๊ธฐ ํฌํจ๋จ
- SHA-3 : SHA-384๊ฐ ์ฌ๊ธฐ ํฌํจ๋จ
Key Derivation Functions
- ํค ์ ๋ ํจ์๋ ์ํ , ํค ์คํธ๋ ์นญ์ ์ฌ์ฉํด ๊ธฐ์กด ํด์ ํจ์์ ์ฝ์ ๋ณด์
- PBKDF2
- ํค ์ ๋ ํจ์ ์ค ํ๋๋ก ํค ๊ฐ์ ์ํธ๋ฅผ ๋ฃ๊ณ ์ด๋ฅผ ์ํ๋ ๋งํผ ํค์คํธ๋ ์นญํ๋ ๋ฐฉ์
- DIGEST = PBKDF2(PRF, Password, Salt, c, DLen)
- PRF: ๋์ (HMAC)
- Password: key ๊ฐ
- c: ํค ์คํธ๋ ์นญ์ ์ํ๋ ํ์
- DLen: ์ํ๋ ๋ค์ด์ ์คํธ ๊ธธ์ด
- Scrypt
- ํค ์ ๋ ํจ์ ์ค ํ๋๋ก ๋ค์ด์ ์คํธ ์์ฑ ์ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒํคํธ๋ฅผ ๊ฐ๊ฒ ํ์ฌ brute force ๊ณต๊ฒฉ ๊ฐ๋ฅ์ฑ์ ๋ณด์ํจ.
์ธ์ฝ๋ฉ ๋ฆฌ์์น
SHA-256์ ๊ฒฐ๊ณผ๋ฌผ : ๋ฌด์กฐ๊ฑด 256 bit ๋ฆฌํด → 32 byte
base64 ์ธ์ฝ๋ฉ ์ ๋ฐ์ดํธ์ ๊ธธ์ด๊ฐ 3๋ฐฐ์์ผ ๋๋ง ํจ๋ฉ์ด ๋ค์ด๊ฐ์ง ์์.
SHA-256์ ๊ฒฐ๊ณผ๋ฌผ์ ๊ฒฝ์ฐ ๋ง์ง๋ง 2byte ์ธ์ฝ๋ฉ ๋ฐฉ๋ฒ
๋ง์ฝ SHA-256์ ํ ๊ฒฐ๊ณผ๋ฌผ์ด X๋ผ๊ณ ํจ. X๋ฅผ Base64๋ก ์ธ์ฝ๋ฉํ ๋ ์์ 30byte๋ 40๊ธ์๋ก ์ ์ธ์ฝ๋ฉ์ด ๋ ๊ฒ์. ๊ทธ๋ผ ๋จ์ 2byte์ ์ธ์ฝ๋ฉ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์. ์๋ฅผ ๋ค์ด ๋จ์ 2byte์ ๋ฐ์ด๋๋ฆฌ ๊ฐ์ด 0101010101010101 ์ด๋ผ๊ณ ๊ฐ์ .
๋ง์ง๋ง =์ 0์ด์ด์ =์ด ๋ค์ด๊ฐ๊ฒ ์๋๊ณ ํจ๋ฉ๊ฐ์ผ๋ก ๋ค์ด๊ฐ ๋์ ์๋ฏธ๋ฅผ ๊ฐ์ง 0์ด๊ธฐ ๋๋ฌธ์ ํจ๋ฉ์ ๊ฐ๋ ์ผ๋ก ๋ค์ด๊ฐ =์. ์ด์จ๋ SHA-256์ Base64๋ก ์ธ์ฝ๋ฉํ ๊ฒฐ๊ณผ๋ฌผ์ 44๊ธ์์ธ๋ฐ ๋ง์ง๋ง ํ ๊ธ์๋ ๊ณ ์ ์ ์ผ๋ก =์. ๋ฐ๋ผ์ ์ฌ๊ธฐ์ ์๊ฐํด๋ณธ ๋ฐฉ์์ด ๋ ๊ฐ์ง์.
- ๋ง์ง๋ง ๊ธ์๋ฅผ =์ด ์๋ base64 ๋ด๋ถ์ ๋๋ค ๋์ ๊ฐ์ผ๋ก ๋ง๋ค๊ณ 44๊ธ์ ๊ทธ๋๋ก ์ ์ก
- ๋ง์ง๋ง ๊ธ์ ์๋ฅด๊ณ 43๊ธ์๋ง ์ ๋ฌ ํ ์คํธ์ ๋ถ์ด๊ธฐ
= ๊ฐ์ ์ฌ์ฉํ์ง ์๊ธฐ ์ํด ์์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ ๋ ์น์๋ฒ์ ๋์์ ๋ค์๊ณผ ๊ฐ์. ํฌ๊ฒ ๋ค๋ฅด์ง ์๋ค๊ณ ํ๋จ.
- ์ ๋ฌ๋ฐ์ P.T๋ฅผ S.K๋ฅผ ์ฌ์ฉํด์ A.T, C.T์ผ๋ก decrypt
- ๋ณตํธํํ ๊ฐ ์ค C.T ๊ฐ์ ๋ฏธ๋ฆฌ ์ ํด๋์ salt๋ฅผ ๋ฃ์ ๊ฒ์ SHA-256์ผ๋ก ํด์ฑํ๋ฉด OTP๊ฐ ๋ง๋ค์ด์ง
- OTP๋ฅผ Base64๋ก ์ธ์ฝ๋ฉํ๋ฉด 44๊ธ์๊ฐ ๋์ฌ ๊ฒ์.
- ์์ฑํ OTP์ ์ 43 ๊ธ์๋ฅผ ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ์ ๋ฌ ๋ฐ์ OTP์ ๋น๊ตํ๋ฉด ๋จ.
Salt ๋ฆฌ์์น
์ํธ ๊ฐ์ ํ์ ๋ฒ ์ด์ค์ ๋ฌด์ธ๊ฐ๋ก ๋ง๋ค๊ฑฐ์. ๋ง๋ค์ด์ง ์ํธ ๊ฐ์ interval๋ฅผ x์ด๋ผ๊ณ ํ๋ฉด ์๋์ ๊ฐ์ด ์์ฑ๋ ๊ฒ์.
์๊ฐ | Salt |
0 ~ x - 1 | salt0 |
x ~ 2x - 1 | salt1 |
2x ~ 3x - 1 | salt2 |
… | … |
kx ~ (k + 1)x - 1 | saltk |
๋ง์ฝ 10์ด ๊ฐ๊ฒฉ์ด๋ผ๊ณ ํ๋ค๋ฉด ์๋์ ๊ฐ์ด ์์ฑ๋ ๊ฒ์.
์๊ฐ(์ด) | Salt |
0 ~ 9 | salt0 |
10 ~ 19 | salt1 |
20 ~ 29 | salt2 |
… | … |
k * 10 ~ (k + 1) * 10 - 1 | saltk |
์ด๊ฒ ์ด ๋จ์๋ก ํ ๋์ ์ํธ ๊ฐ ์์ฑ์. ๋จ ์ด๋ ๊ฒ ๋๋ฉด interval ๋์ ๋ง๋ค์ด์ง๋ api๋ค์ OTP ๊ฐ์ ๊ฐ๋ค๋๊ฒ ๋จ์ ์. ์ด์จ๋ api ๋์์ ๋์ฒด๋ก 1์ด ์์ ์ด๋ค์ง๊ธฐ๋ ํ๋๋ฐ 1์ด๋์ ์ด๋ค์ง๋ ์ฌ๋ฌ๊ฐ์ api๋ค์ OTP๊ฐ ๋ชจ๋ ๊ฐ์. ๋ณด์์ ์ผ๋ก ์ ๊ฒฝ์ฐ์ด๋ ๋ถ๋ถ์ด๋ผ๊ณ ํ์ จ์.
import Foundation
import Alamofire
import CommonCrypto
enum EncryptError : Error {
case serverErr
case clientErr
case encodingStringErr
}
class Encryptor {
init() {
}
// testํ ๋ ์ฌ์ฉ ๋ฐฉ๋ฒ
private func test() {
do {
Task {
let token = try getDigest()
}
}
}
// MARK: ํต์ ์ ํ์ํ value ๊ฐ์ ธ์ค๊ธฐ ์ํ ํจ์
func getDigest() throws -> String {
do {
let ct = try KeyChainUtil.shared.getStringTypeFromKeyChain(type: .ct)
let ctDigest = hashString(from: appendSalt(originalValue: ct))
let pt = try KeyChainUtil.shared.getStringTypeFromKeyChain(type: .pt)
let result = ctDigest.appending(pt)
if let encodedResult: String = result.addingPercentEncoding(withAllowedCharacters: .alphanumerics) {
return encodedResult
} else {
throw EncryptError.encodingStringErr
}
} catch (let keyChainException) {
throw keyChainException
}
}
func fetchTokenFromServer() async throws -> String {
return try await withCheckedThrowingContinuation { continuation in
WebServerSignInService().serverAction(type: WebSignInModel.self) { [self] response in
switch response {
case .success(let data):
guard let data = data as? WebSignInModel else { return }
if let dataToken: String = data.token {
try? KeyChainUtil.shared.storeStringTypeInKeyChain(type: .pt, data: dataToken)
// ์๋ฐํ ๋งํ๋ฉด ์ด ์๋ ์ฝ๋๋ค์ ๋ถ๋ฆฌ๋์ด์ผ ํจ. ๋ฐ์์จ ํ ํฐ์ผ๋ก ํด์ฑ๋ ๋ค์ด์ ์คํธ ๋ง๋๋ ๊ณผ์ ์.
let digest = hashString(from: appendSalt(originalValue: "1234"))
let result = digest.appending(dataToken)
let encodedResult = result.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
if let value: String = encodedResult {
continuation.resume(returning: value)
} else {
continuation.resume(throwing: EncryptError.encodingStringErr)
}
} else {
continuation.resume(throwing: EncryptError.clientErr)
}
case .pathErr(_):
continuation.resume(throwing: EncryptError.clientErr)
default:
continuation.resume(throwing: EncryptError.serverErr)
}
}
}
}
func appendSalt(originalValue: String) -> String {
// ๋น๊ณต๊ฐ
}
func hashString(from originalValue: String) -> String {
return originalValue.sha256()
}
}
extension Data{
public func sha256() -> String{
return base64StringFromData(input: digest(input: self as NSData))
}
private func digest(input : NSData) -> NSData {
let digestLength = Int(CC_SHA256_DIGEST_LENGTH)
var hash = [UInt8](repeating: 0, count: digestLength)
CC_SHA256(input.bytes, UInt32(input.length), &hash)
return NSData(bytes: hash, length: digestLength)
}
private func base64StringFromData(input: NSData) -> String {
var result = input.base64EncodedString()
return result
}
}
public extension String {
// String ํ์
์ ๊ฐ์ NSData ํ์
์ผ๋ก ๋ณํ ํ SHA256 ๋ณํ
func sha256() -> String {
if let stringData = self.data(using: String.Encoding.utf8) {
return stringData.sha256()
}
return ""
}
}
์ฌ๊ธฐ ์ฝ๋์์ ๊ฒฐ๋ก ์ ์ผ๋ก hash ๊ด๋ จ ๋ถ๋ถ์ appendsalt(), hashString(), Data.sha256(), digest(), base64StringFromData(), String.sha256() ์ด๊ฑฐ์. ๋์ ๊ณผ์ ์ ์๋์ ๊ฐ์.
- String.sha256()์ ๋ถ๋ฌ ํ๋ผ๋ฏธํฐ๋ฅผ ์ธ์ฝ๋ฉํด์ค. ์ธ์ฝ๋ฉํด ์ค ๊ฒฐ๊ณผ๋ฌผ์ ๋ํด Data.sha256()์ ์คํ
- Data.sha256()์์ ํ๋ผ๋ฏธํฐ๋ฅผ NSData format์ผ๋ก digest() ํจ์๋ก ๋๊น
- digest๋ ์ ๋ฌ๋ฐ์ ๊ฐ์ผ๋ก SHA256 ํด์ฑ์ ํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํจ
- 2์์ digest()์ ๊ฒฐ๊ณผ๋ฌผ์ ๋ํด NSData ํ์์ base64๋ก ์ธ์ฝ๋ฉํ๋ ๊ณผ์ ์ด ํ์ํจ. ์ด๋ฅผ base64StringFromData() ํจ์๋ฅผ ๋ถ๋ฌ ์ํํจ
- base64StringFromData() ํจ์์์๋ ๋๊ฒจ๋ฐ์ ๊ฐ์ ์ธ์ฝ๋ฉํด์ค. SHA256์ ์ํด ๋ง์ง๋ง ๊ธ์๋ ๊ผญ ํจ๋ฉ์ด ๋ค์ด๊ฐ. Padding ๊ฐ์ธ =๋ฅผ ์ ์ธํ๊ณ ์ถ์ผ๋ฉด result = String(result.dropLast()) ์ด ์ฝ๋ ์ถ๊ฐํด์ฃผ๋ฉด ๋จ.
- 5๊น์ง ์๋ฃํ๋ฉด 2์์ ์ต์ข ๊ฐ์ ๋ฆฌํดํด์ค.
'CS > iOS, Swift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[iOS] ์น๋ทฐ ์ฟ ํค ๊ด๋ จ ์ ํธ (0) | 2023.04.07 |
---|---|
[iOS] ํค์ฒด์ธ ์ ํธ (0) | 2023.04.07 |
[iOS] Framework, Library RnD (0) | 2023.04.07 |
[iOS] static framework to xcframework, cocoapod ๋ฐฐํฌ (0) | 2023.04.07 |
[iOS] pod dependency trouble shooting (0) | 2023.04.07 |