사상 최악의 개인정보 유출 사고로 시끄러운 가운데, 많은 분이 패스워드는 뭐고 암호화는 뭔지 궁금해하는 것 같아 서비스를 만드는 입장에서 재빠르게 써 보았습니다. 정확함보다는 이해하기 쉬움을 목표로 하였으니 실제 구현과 다른 부분이 있어도 너그러이 넘어가 주세요 (굽신굽신)
Step 1. 간단하게 로그인을 만들어보자
자, 여러분이 ㅍㅍㅅㅅ에 올라오는 허접스러운 글들을 참다못해 포스트모던 뉴미디어 대안언론 사이트인 픗픗슷슷을 만들고자 합니다. 일단 글을 쓰려면 필자들이 회원 가입을 하고 로그인을 해야겠죠. 회원 가입 화면에 아이디와 패스워드를 입력합니다. 아이디는 ‘admin’, 패스워드는 (전 세계에서 2번째로 많이 쓰는) ‘123456’으로 하겠습니다.
아이디와 패스워드를 입력받았으니 이걸 저장해야겠죠. 대부분의 사이트는 데이터베이스(DB)라는 저장공간을 이용합니다. 엑셀로 표 만드는 거 생각하시면 쉬워요.
혼자 있으면 심심하니까 한 명 더 가입시켜 봅시다.
그리고 해킹을 당해서 아이디와 패스워드를 몽땅 털립니다.
Step 2. 암호화를 해보자
이게 무슨 급전개냐고요? 리수령이 복숭아나무 아래에서 의기투합하여 사이트를 세우고 개발자인 저를 찾아 삼고초려를 하는 그런 스토리(뻥입니다)는 나중에 ㅍㅍㅅㅅ 독자모임 이런 거 할 때 와서 들으시면 됩니다. 지금은 패스워드에 집중하도록 하죠.
자, 이래서야 너무 위험하죠. 그렇다면 패스워드를 암호화 해봅시다. 암호화 알고리즘은 무수히 많지만 그냥 각 자리에 1씩 더해볼까요.
이렇게 하면 해커가 데이터베이스를 털어도 로그인을 할 수 없겠죠! 그러자 해커가 자기도 가입해봅니다. 패스워드는 ‘1111’로 해볼까요. 물론 사이트에서 자동으로 각 자리에 1을 더해서 ‘2222’가 저장됩니다.
해커는 다시 데이터베이스를 털어보고 쉽게 규칙을 알아냅니다.
Step 3. 좀 더 안전하게 해보자.
위와 같이 1111 2222 상호 전환이 가능한 암호화는 일단 알고리즘과 키를 알아내고 나면 쉽게 풀어낼 수 있습니다. 그렇다면 암호화는 쉽지만 풀어내기는 어려운 방법을 쓰면 어떨까요? 여러 가지 알고리즘이 있지만, 여러분이 이해하기 쉬운 방법을 써 보죠. 이제부터 패스워드는 무조건 (소수)x(다른 소수)로 정하고, 결과값을 저장하겠습니다.
당신은 패스워드인 ‘113×131’을 입력하면 그만입니다. 컴퓨터가 쉽게 둘을 곱한 다음 데이터베이스에 저장된 14803과 비교해보겠죠. 하지만 해커는 14803을 소인수분해해서 원래의 두 소수를 알아내기 위해 상당한 노력을 해야 합니다. 이러면 패스워드가 유출되어도 걱정이 없습니다. 충분히 긴 길이의 패스워드를 사용한다면 하나씩 대입해보다가 늙어 죽을 테니까요.
물론 사용자에게 매번 소수로 패스워드를 정하게 할 수는 없죠. 보통은 아무 값이나 넣으면 다시 되돌리기 어렵게 암호화해주는 수학 공식을 사용합니다. 좀 더 어려운 말로 단방향 해시(hash) 함수라고 합니다. 처음의 패스워드들을 해시 함수의 하나인 SHA1로 암호화해서 저장하면 아래와 같이 됩니다.
이렇게 단방향 해시를 통해 얻어낸 암호화된 패스워드를 다이제스트(digest)라고 합니다. 다이제스트를 수학적으로 계산해서 다시 패스워드로 만드는 간단한 방법은 (아직까지) 존재하지 않습니다.
Step 4. 실전 레벨의 패스워드 보안
이렇게 암호화된 패스워드를 해커가 풀어내는 방법은 크게 두 가지가 있습니다. 첫 번째는 미리 해시해둔 패스워드를 잔뜩 가지고 있다가(Rainbow Table이라고 부릅니다) 훔쳐낸 패스워드와 비교해보는 방법입니다. 이를 막기 위해서는 패스워드에 문자열을 붙여서 길고 복잡하게 만드는 방법(Salting)을 사용하면 됩니다. ‘123456’이 ‘7c4a8d09c…’ 이라는걸 알고 있더라도 모든 패스워드 뒤에 ‘n32n023nf02n’을 붙인 다음 해시해서 저장한다면 미리 만들어둔 해시와는 일치하는 경우가 거의 없겠죠.
다른 하나는 해시 연산 자체가 매우 빠르기 때문에 맞을 때까지 대입해보는 방법(Brute Force)입니다. 여러분이 쓰는 컴퓨터 정도만 되어도 1초에 수억 번을 대입해 볼 수 있으니 컴퓨터에게 맡겨두고 자고 일어나면 풀려있겠죠. 이 방법을 막기 위해서는 해시를 여러 번 반복해서 충분히 오래 걸리게 하면 됩니다(Key Stretching). 한 번 비교에 0.2초 정도 걸려도 여러분이 로그인할 때는 느껴지는 차이가 없지만, 해커들은 사실상 무차별 대입을 포기해야 합니다.
이런 방법들을 직접 만들어서 넣기는 어렵기도 하고 실수할 수도 있기 때문에 PBKDF2나 bcrypt와 같이 널리 알려진 방법(Adaptive Key Derivation Functions)들을 사용합니다. 제가 즐겨 쓰는 bcrypt를 사용하면 앞의 패스워드는 이렇게 믿음직스러운 모습이 됩니다.
마치며
Step 4 수준의 패스워드 보안은 업계 상식이고 제대로 된 사이트라면 모두 적용되어 있습니다. 하지만 작은 규모거나 오래된 사이트의 경우 Step 1 상태인 경우도 많죠. 사이트마다 패스워드를 다르게 사용하시는 것을 권장하는 이유 중 하나입니다.
그리고 보안이란 항상 생각지 못한 형태로 뚫리고는 하죠. 작년의 Adobe 해킹 사태 때는 모든 패스워드가 해시 되어 있었지만, 패스워드 힌트가 암호화되지 않은 상태였습니다. 힌트를 보고 적당히 패스워드를 맞추면 같은 패스워드를 가진 모든 사람들의 계정이 내 것이죠. 심지어 이 힌트로 십자말풀이를 하는 사이트도 있으니 심심할 때 해 보시면서 길고 추측하기 어려운 패스워드의 중요성을 다시금 느껴보시기 바랍니다.