DEV

Secure Coding)해시함수와 문제점

시큐어 코딩

Featured image

@

단방향 해시란?

단방향 해시 함수는 수학적인 연산을 통해 원본 메시지를 변환하여 암호화된 메시지인 다이제스트(digest)를 생성한다. 원본 메시지를 알면 암호화된 메시지를 구하기는 쉽지만 암호화된 메시지로는 원본 메시지를 구할 수 없어야 하며 이를 ‘단방향성’이라고 한다. 대표적으로 MD5, SHA 등이 있다. ‘password’를 MD5로 변환하면 ‘5f4dcc3b5aa765d61d8327deb882cf99’ 다이제스트가 생성이 된다. ‘Password’를 똑같이 변환하면 ‘dc647eb65e6711e155375218212b3964’가 되어 전혀 다른 문자가 되는 것을 확인할 수 있다. 이러한 특징을 avalanche라 하고 사용자의 원본 패스워드를 추론하기 어렵게 만드는 중요한 요소이다.

단방향 해시함수의 문제점

같은 메시지가 같은 다이제스트를 갖는다면 다이제스트를 많이 갖고 있다면 그 둘을 비교하면 원본데이터를 찾을 수 있다. 이러한 행위를 레인보우 공격(rainbow attack)이라 한다. 또한 해시 함수는 처음부터 짧은 시간에 데이터를 검색하기 위해 설계된 것이다. 그러다보니 1초당 56억 개의 다이제스트를 대입할 수 있을 만큼 빠른 속도를 가지고 있다. 따라서 위와같은 공격은 치명적일 수 밖에 없다.

해결방안

  1. 다이제스트 생성에 딜레이를 준다.
  2. 솔팅(salting)
  3. 키 스트레칭(key stretching)

해결방안1 - 다이제스트 생성에 딜레이를 준다.

사용자는 패스워드를 인증하는 데 걸리는 시간에 그리 민감하지 않다. 그래서 다이제스트를 생성하는 시간을 0.1초에서 1초로 변경하더라도 사용자는 신경쓰지 않는다.

import CryptoSwift

extension String {
  func delayMD5(timeInterval:TimeInterval, completion:@escaping (_ md5:String)->()) {
        Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: false) { (timer) in
            completion(self.md5())
            timer.invalidate()
        }
    }
}

해결방안2 - 솔팅(salting)

솔트(salt)는 단방향 해시 함수에서 다이제스트를 생성할 때 추가되는 바이트 단위의 임의의 문자열이다. 그리고 이 원본 메시지에 문자열을 추가하여 다이제스를 생성하는 것을 솔팅(salting)이라 한다.

import CryptoSwift

extension String {
  func saltingMD5(salt:String) -> String {
        return (self+salt.md5()).md5()
  }
}

해결방안3 - 키 스트레칭(key stretching)

입력한 패스워드의 다이제스트를 생성하고, 생성된 다이제스트를 입력 값으로 하여 다이제스트를 생성하고, 또 이를 반복하는 방법으로 다이제스트를 생성할 수도 있다. 이렇게 하면 입력한 패스워드를 동일한 횟수만큼 해시해야만 입력한 패스워드의 일치 여부를 확인할 수 있다. 이것이 기본적인 키 스트레칭 과정이다. 최근에는 일반적인 장비로 1초에 50억 개 이상의 다이제스트를 비교할 수 있지만, 키 스트레칭을 적용하여 동일한 장비에서 1초에 5번 정도만 비교할 수 있게 한다. GPU(Graphics Processing Unit)를 사용하더라도 수백에서 수천 번 정도만 비교할 수 있다. 50억 번과는 비교할 수도 없을 정도로 적은 횟수다. 앞으로 컴퓨터 성능이 더 향상되면 몇 번의 반복을 추가하여 보완할 수 있다

import CryptoSwift

extension String {
  func keyStretchingMD5(round:Int) -> String {
        var ret = self
        for _ in 0..<round {
            ret = ret.md5()
        }
        return ret
    }
}

마침

CryptoSwift라는 오픈소스를 활용해서 해결방안들을 만들어보았다. 이 외에도 Adaptive Key Derivation Functions, PBKDF2, bcrypt 등 많은 알고리즘이 존재하고 그것을 활용하는 방법은 다음 포스팅에 쓰도록 하겠다.

출처

Why don't you read something next?

Secure Coding)해시함수 응용편

Share

BugkingK

Author

BugkingK

iOS developers who love to play guitar and develop

Comments

crossorigin="anonymous">