컴퓨터가 다루는 정보의 양은 날로 많아지고, 그 중요도나 민감도도 날이 갈수록 올라가고 있다. 한 사람의 핸드폰에는 시간에 따른 사용자의 위치정보, 사용자가 매일 이용하는 웹사이트와 앱의 종류와 사용기록까지 오직 자신만이 알고 싶은 자료가 많다. 따라서 이러한 정보를 캐내려는 자로부터 소중한 것을 지키는 방법이 필요하게 되었다.
이 글에서는 해시를 이용하여 비밀번호를 저장하는 방법에 대해 다룬다.
해시(Hash)
해시란, 특별한 성질을 가진 함수를 통틀어 부르는 말이다. 한번 어떤 해시함수 $f(x)$를 두고 해시함수의 특징에 대해 알이 보자.
우선 해시함수는 어떤 값이던 입력이 될 수 있다. 문자 1개가 될 수도 있고 책 한 권의 내용 전체가 될 수도, 이 세계에 있는 모든 책의 내용이 입력이 될 수 있다.
하지만 해시함수의 결과는 일정한 범위 내에서 정해져 있고, 그 범위는 함수의 이름에 같이 적는다. 예를 들어 SHA-256 해시함수가 만들 수 있는 결과의 범위는 $0$부터 $2^{256}-1$까지이고, SHA-512 해시함수가 만들 수 있는 결과의 범위는 $0$부터 $2^{512}-1$까지이다(이때 범위의 끝이 2의 거듭제곱 꼴인 것은 해시함수가 이진수를 기반으로 설계되었기 때문이다).
해시함수는 입력값을 완전히 뭉개버려야 한다. 해시함수의 결괏값과 입력값은 어떠한 선형적 관계도 없으며, 해시함수를 통과하면 원래의 정보는 완전히 손실된다. 또한 입력값이 조금만 달라도 함숫값은 완전 달라져야 한다. 즉 "apple"과 "apples"의 함숫값은 전혀 비슷하지 않아야 한다는 것이다.
해시함수의 중요한 특징 중 하나는 결괏값으로부터 입력값을 역산할 수 없다는 것이다. 즉 "ABC"라는 정보를 해시해서 "3DFFC34A"가 나오는 것은 계산할 수 있지만, 어떤 값을 해시해야 “3DFFC34A”가 나올지 계산하는 것은 불가능하다.
또 다른 중요한 특징은 충돌이 적다는 것이다. 해시함수는 일대다 대응 함수이기 때문에 비둘기집 원리에 의해 분명 어떤 두 입력은 같은 해시값을 만든다. 하지만 이는 매우 매우 희박한 확률로 일어나야 한다.
이러한 해시함수의 성질은 암호분야에서 비밀번호를 저장하는데 매우 유용하게 활용된다. 대한민국 법률상 인터넷 서비스를 운영하는 자는 사용자의 비밀번호를 원문으로 저장해서는 안 된다. 이는 불법이며 위반하면 처벌받을 수 있다.
그럼 비밀번호를 어떻게 저장해야 할까? 비밀번호를 해시해서 저장해야 한다.
비밀번호를 해시하면 만일 사용자의 정보가 해킹으로 털리는 사고가 발생해도 공격자는 비밀번호를 알 수 없다. 저장된 것은 비밀번호가 아니라 해시된 비밀번호뿐이기 때문이다. 반면 사용자가 로그인을 시도하면 입력한 비밀번호의 해시값과 저장된 해시값을 비교하여 비밀번호가 맞는지는 확인할 수 있다.
비밀번호를 해시하여 저장함으로써 데이터베이스의 관리자도 사용자의 비밀번호를 알 방법이 없다. 사용자의 해시값만을 알 뿐. 따라서 사용자가 비밀번호를 잊어버려서 비밀번호 찾기를 해도 원래 비밀번호를 알려줄 수 없고 변경만을 도와준다.
레인보우 테이블을 통한 무력화
방패가 강해면 창도 강해지는 법, 오늘날 비밀번호를 해시만 해서 저장하는 것은 더 이상 안전하지 않다. MD5와 같이 안전하지 않은 해시함수는 컴퓨터를 활용하여 무차별 대입 공격으로 무력화할 수 있고, 다른 해시함수들도 레인보우 테이블 공격을 통해 원래 비밀번호를 알아낼 수 있다.
레인보우 테이블은 어떤 입력을 넣어야 어떤 해시값이 나오는지 미리 일대일로 전부 대응해놓은 표이다. 공격자는 해시값을 알면 이 표를 활용해서 원래 비밀번호를 알아낼 수 있다.
이 공격을 막으려면 같은 데이터도 다른 해시값을 가져야 한다. 이를 위해 비밀번호를 해시로 저장할 때는 "솔트(Salt)"를 치는 것이 좋다.
솔트를 이용하여 비밀번호를 해시하려면 해시하기 전에 "솔트 값"을 만들어야 한다. 이 솔트 값은 해시를 생성할 때마다 안전한 무작위(Secure Random)로 생성한다. 그리고 해시함수에 비밀번호와 함께 솔트 값을 입력하면 이 둘을 잘 버무려 해시값을 생성한다.
그리고 데이터베이스에는 사용자의 해시값과 솔트값을 같이 저장해서 나중에 로그인을 할 때 사용자가 입력한 비밀번호를 데이터베이스에 저장된 솔트 값으로 해시를 해서 저장된 해시값과 비교를 해서 인증을 할 수 있다.
솔트를 활용하면 같은 비밀번호라도 솔트 값에 따라 해시값이 다르다. 이렇게 되면 공격자는 더 이상 모든 솔트 값에 따른 모든 해시값을 표로 정리해두기엔 경우의 수가 너무 많아져서 레인보우 테이블이 불가능해진다.
'컴퓨터' 카테고리의 다른 글
FTP 서버 구축 (0) | 2021.12.12 |
---|---|
ARP 스푸핑 공격 - 개념 (0) | 2021.10.05 |
RSA 암호화 - 개념편 (0) | 2021.07.22 |
데이터베이스 Pt. 1 (0) | 2021.07.19 |