어떤 웹사이트와 앱에 위와 같은 회원정보를 가진 데이터베이스가 있습니다. 가입된 회원들의 이름과 아이디, 그리고 비밀번호가 저장되어 있습니다.
데이터베이스에 자료가 저장되는 가장 기초적인 형태입니다. 그러나 개인정보를 위와 같이 저장하면 절대로 안됩니다. 왜냐하면 비밀번호가 평문 그대로 저장되어 있기 때문입니다. 민감한 개인정보를 평문 그대로 저장하는 것은 자살행위입니다. 해커의 입 속으로 소중한 정보들이 들어간 이후에는 돌이킬 수 없습니다.
요즘은 저런 기초적인 실수를 하는 개발자는 거의 없어졌지만, 예전엔 개인정보를 저렇게 저장하는 사례가 정말 많았습니다. 요즘도 몇몇 개인 쇼핑몰에서는 개인정보를 저런식으로 저장을 하다가 난리가 나기도 합니다.
그렇다면, 비밀번호를 해커와 내부의 직원들이 알아볼 수 없도록 한번의 암호화 과정을 거쳐야 합니다.
평문으로 저장되던 회원들의 비밀번호를 암호화하였습니다. 이제 한결 마음이 편해집니다. 해커나 직원들이 고객의 비밀번호 평문을 알아낼 수 없게 되었습니다. 위의 예제에서는 비밀번호 평문을 해시 함수 SHA-256을 이용해서 암호화하였습니다.
과거에는 평문을 암호화할 때 해시 함수 MD5를 많이 사용했습니다. 그러나 요즘은 거의 사용하지 않습니다. MD5는 이미 2000년대에 결함이 발견되었습니다. 그리고 MD5용 딕셔너리도 상당히 방대하게 구축되어 있어서 무차별 대입 공격(Brute Force)에도 매우 취약합니다. 또, 이제는 개인 PC로도 MD5의 해시 충돌을 발견할 수 있을 정도로 쓸모없는 알고리즘이 되었습니다.
그래서 이후에는 SHA 함수들을 보편적으로 사용하게 되었습니다. 그러나 SHA0과 SHA-1도 취약한 부분들이 발견되었기 때문에 일단 SHA-256 이상을 사용하여 암호화 하는 것이 권장되고 있습니다.
그러나 아무리 복잡한 해시 함수를 사용한다고 해도 딕셔너리가 구축되면 무차별 대입 공격에서 자유로울 수는 없습니다.
그래서 한 차례 더 안전장치를 만들게 되는데, 이때 사용되는 것이 바로 솔트(SALT)입니다. '소금을 친다'라는 은어로 표현하기도 합니다.
1차적으로 해시된 암호문에 소금을 쳐서 암호문을 한번 더 비꼬아 저장하는 것입니다. 위와 같이 회원 DB에는 SALT값을 저장할 애트리뷰트가 추가되었습니다. (SALT는 다른 곳에 보관하는 것을 추천)
소금을 치는 방식은 다음과 같습니다.
A9902!MGGA28356c7bd7b12c4c922d3e79666661d77d42473786f7547680354f3b014ae933
이렇게 단순하게 소금을 치는 것도 마음에 걸린다면 암호문의 7번째 문자의 뒤에 SALT를 결합한다는 식으로 응용을 해도 됩니다.
A9902!MGGAmylove1934!!
또는, 처음부터 평문과 솔트를 합해서 해시 함수로 암호화를 하기도 합니다.
이와 같이 1차 암호문이나 평문에 SALT를 결합해서 해시 함수를 한바퀴 더 돌리면 됩니다. 너무나 당연하게도 이 작업은 서버에서 이루어져야 합니다. 클라이언트에 어떤 힌트도 노출이 되어서는 안됩니다. 그렇다면 손쉽게 해커에게 비밀번호가 노출되기 때문에 이런 작업을 하는 것 자체가 무용지물입니다.
솔트는 길면 길수록 좋습니다. 그리고 간혹 SALT를 하드코딩하여 전체 회원에게 동일하게 적용하는 경우가 있던데, 이러면 SALT를 쓰나마나입니다. 회원별로 별도의 난수를 생성해서 각기 다른 SALT를 저장해서 사용하는 것이 좋습니다.
너무나 당연하게도 데이터베이스에는 회원이 입력한 비밀번호 평문과 1차적으로 만들었던 암호문은 저장하지 않습니다. 암호문에 소금을 쳐서 다시 암호화 한 암호문만 저장하면 됩니다.
이렇게 해두면 해커가 DB까지 털어간다 하더라도 회원들의 비밀번호가 안전하게 보호되겠죠? 물론, 회원들의 비밀번호가 지나치게 간결하면 궁극적으로는 보안에 취약할 수 밖에 없으니 회원 가입을 받을 때, 최소 자릿수이상으로 가입을 받고 특수 문자 등을 섞어서 받으면 좋을 것입니다.
2021년 8월 15일
송종식 드림