거의 대다수 시스템에서 구현이 되고 있는 로그인/로그아웃 기능, 여기서 만일 서버에 사용자의 비밀번호를 평문으로 저장한다면? 이건 말도 안되는 일이고 있어서도 안되는 일이다. 사용자의 비밀번호를 안전하게 보관해두기 위해서는 암호화가 절대적으로 필요하다. 이번 프로젝트에서 사용자의 로그인/로그아웃 기능을 구현하면서 알아본 암호화 방식에 대해 정리해보았다.
해싱과 암호화의 차이?
가장 큰 차이는 ‘방향성’이다. 해싱은 단방향이기 때문에 복호화가 불가능하지만, 암호화는 양방향이기 때문에 역으로 복호화가 가능하다.
단방향 해시 함수
단방향 해시 함수는 어떤 수학적 연산(또는 알고리즘)에 의해 원본 데이터를 매핑시켜 완전히 다른 암호화된 데이터로 변환시키는 것을 의미한다. 이 변환을 해시라고 하며, 해시에 의해 암호화된 데이터를 다이제스트(digest)라고 한다.
단방향 해시 함수의 한계점
- 동일한 메시지는 동일한 다이제스트를 갖는다.
- 하나의 평문에는 언제나 같은 해쉬 함수를 내뱉는다. 그렇기 때문에 사용자들이 많이 사용하는 passsword나 복잡하지 않은 암호의 경우 대입해보기 쉽다. 즉, 한 번이라도 유출된 패스워드를 사용할 경우 해킹당할 가능성이 높다.
단방향 해시 함수 보완 방법
해시 함수 여러번 수행하기(Key Stretching)
해시함수를 여러번 돌리는 만큼 최종 다이제스트를 얻는데 그만큼 시간이 소요되기 때문에, 브루트포스를 최대한 무력화 할 수 있다.
솔트
솔트란 해시함수를 돌리기 전에 원문에 임의의 문자열을 덧붙이는 것을 말한다. 단어 뜻 그대로, 원문에 임의의 문자열을 붙인다는 의미의 소금친다(salting)는 것이다.
이렇게 되면 다이제스트를 알아낸다고 쳐도 password가 다 다르기 때문에 알아내기 더욱 어려워진다. 그리고, 사용자마다 다른 salt를 사용한다면 같은 비밀번호더라도 다이제스트의 값은 다르다. 이는 결국 한 명의 패스워드가 유출되더라도 같은 비밀번호를 사용하는 다른 사용자는 비교적 안전하다는 것을 의미한다.
결국 두가지 방식을 혼용하면 아래와 같이 비밀번호를 해싱할 수 있다.