비밀번호 암호화

팀 프로젝트를 진행하던 중 비밀번호 암호화 하는 방법을 배우게 되었다. 비밀번호를 암호화 하기 위해 해싱함수를 이용하여 비밀번호를 해싱하고 해싱된 비밀번호에 salt를 한다. "salt-소금치기". 필자는 salt 암호화에 대한 좋은 블로그를 발견하여 그 블로그를 다시 정리하면서 공부하기로 하였다.

출처: https://starplatina.tistory.com/entry/비밀번호-해시에-소금치기-바르게-쓰기


  • 데이터베이스 안 사용자의 패스워드는 반드시 암호화 되어야 한다.
  • 암호화를 하는 가장 좋은 방법은 salt값을 이용하는 것이다.(소금치기)

비밀번호 해싱이란?


해시 함수(hash function)는 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수이다. 한글자만 달라도 전혀 다른 해시값을 생성하기 때문에 비밀번호를 보호하는데 아주 좋은 방법이다.

  1. 사용자가 계정을 생성한다.
  2. 사용자의 비밀번호는 해싱되어 데이터베이스에 저장된다. 원본 패스워드는 하드 디스크 어디에도 기록되지 않는다.
  3. 사용자가 로그인을 시도 할 때 사용자가 입력한 패스워드의 해시값이 데이터베이스에 저장된 값과 동일 한지 비교 한다.
  4. 만약 해시값이 동일하면, 사용자는 로그인에 성공하고 아니면 잘못된 값을 입력했다고 알려준다.
  5. 로그인을 계속 시도 하는경우 3~4번 과정을 반복한다.

!로그인이 실패할 경우 비밀번호가 틀렸다고 알려주면 안된다. 반드시 'ID 혹은 비밀번호가 틀렸습니다'라고 알려줘야 한다.!

암호화 해쉬 함수로는 SHA256, SHA512, RipeMD WHIRLPOOL 같은 것들이 있다.


이렇게 비밀번호를 해싱해도 해킹이 될 수 있다. 해시를 해킹하는 가장 쉬운 방법은 비밀번호를 예측하고 무작위 대입해보는 것이다. 가장 유명한 패스워드 예측 방법은 단어사전을 통한 공격과 무차별 대입 공격이다. 이러한 방법으로 효율은 좋지 않지만 결국 비밀번호를 알아낼 수 있다. 그러므로 Salt를 이용하여 해싱을 해야 한다.


Salt(소금치기)란?

salt라고 불리는 무작위 문자열을 비밀번호를 해싱하기 전에 붙여서 해시값을 무작위로 만들 수 있다. 같은 비밀번호인데도 결과로 생성된 해시값은 다르게 할 수 있다. 인증을 할 때 비밀번호가 동일한지 확인을 하기 위해서는 salt값이 필요한데 이 값은 사용자 정보를 저장하는 데이터베이스에 같이 저장한다.


salt값과 함께 비밀번호 해싱하기

salt값은 암호학적으로 안전한 난수 생성기에 의해 생성되어야 한다. CSPRNG은 C언어의 rand() 함수처럼 일반 난수생성기와 매우 다르다. 이름을 통해 짐작하듯이 CSPRNG는 암호화를 사용하도록 설게되어 있고 이 것은 완벽히 예측 불가능 한것을 의미한다. 소금값은 예측가능한 것을 사용할수 없기 때문에 반드시 CSPRNG를 사용해야 된다. 언어마다 CSPRING을 제공하고 있다.

salt값은 사용자와 비밀번호 별로 유일한 값을 가져야 한다. 사용자 계정을 생성할때와 비밀번호를 변경할때마다 새로운 임의의 랜덤 소금값을 사용해서 해싱 해야 된다. 소금값은 절때 재사용 하지 말아야 되고 길게 만들어야 되기 때문에 다양한 값을 생성할 수 있다. 소금값은 해쉬 함수의 출력 값 만큼 길게 만들고 사용자 계정 테이블에 같이 저장되도록 한다.


비밀번호 저장하기


  1. CSPRNG를 사용해서 임의의 소금값을 생성한다.
  2. 소금값을 비밀번호 앞에 덧붙이고 SHA256 같은 표준 암호화 해시 함수를 사용해서 해시한다.
  3. 소금값과 해시값을 사용자 계정 테이블에 저장한다.


비밀번호 유효성 검사


  1. 사용자의 소금값과 비밀번호 해시값을 데이터베이스에서 찾는다.
  2. 입력한 비밀번호에 소금값을 덧붙이고 비밀번호 해싱에 사용했던 동일한 해싱함수를 사용하여 해싱한다.
  3. 입력한 비밀번호로 생성한 해싱값과 저장되어 있는 해싱값과 비교해서 일치하는지 확인하고 동일 하면 비밀번호가 정확한 비밀번호를 입력한것이고 아니면 잘못된 비밀번호를 입력한 것이다.


웹 어플리케이션에서는 항상 서버에서 해시를 해야 한다.


웹 어플리케이션에서을 개발중이라면 어디서 해시를 해야할 지 고려해야 한다.

클라이언트 부분에서 해싱을 사용할 수 있지만 https를 대신할 수는 없다.

개인적인 의견으로는 클라이언트에서는 https 통신을 활용하고 서버에서 해싱을 하는 것이 좋다고 생각한다.



암호화에 대한 더 자세한 설명은 https://starplatina.tistory.com/entry/비밀번호-해시에-소금치기-바르게-쓰기 블로그에 되어 있다. 참고하길 바란다.

이윤재

이윤재
주니어 개발자 이윤재입니다. 공부한 내용을 바탕으로 기술하는 블로그 입니다.

JAVA8 - Lambda - stream api

Java8 lambda stream에 대하여 Continue reading

JAVA8 - Lambda란?

Published on July 29, 2019

NoSQL과 RDBMS의 장단점

Published on June 22, 2019