django - 회원가입 시 bcrypt로 비밀번호 암호화하기 (5)

solee·2022년 2월 23일
0

Django

목록 보기
8/12

🚩목표

  • 회원가입 시 bcrypt를 사용해 암호화를 진행한다.



지금까지는 데이터를 테이블에 고냥 쏙 집어넣었다. 그런데 이 데이터베이스를 누가 해킹한다면? 내 고객들의 개인정보가 홀라당 털리겠지.

그래서는 안 된다!

그러므로 데이터를 암호화해야 하는데, 이때 해싱hashing이라는 방식을 사용한다.


Hashing

해싱이란 다진 고기를 뜻하기도 하는데, 고기를 다지듯 데이터를 작살내는 거라고 봐도 될 것이다. "1234"라는 데이터가 있을 때 SHA-256 방식으로 인코딩하면

03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4

이런 결과가 나온다. 이 값을 보고 1234라는 것을 알 수 있을까? 무리다. 이렇게 데이터를 지킬 수 있다.


...있었다.

이렇게 해싱하는 값은 1234에서 저 길고 어지러운 숫자로 변환할 수는 있지만 반대로 이 값을 다시 1234로 변환할 수는 없다. 이를 단방향 해싱이라 하는데, 큰 단점이 있다. 바로 "결과값이 항상 동일"하다는 점이다. A라는 사람도 비밀번호가 1234고 B라는 사람도 비밀번호가 1234라면, 두 사람은 비밀번호로 동일한 해싱값을 가지게 되는 것이다.

해커들은 이 점을 이용해 rainbow table이라는 것도 만들었는데, 사람들이 많이 사용하는 비밀번호를 해싱한 값을 저장해 몇백 기가씩 데이터를 저장해 두었다(엄청나다..)

또는 이런 사이트도 있다: https://md5calc.com/hash/sha256/1234
값을 넣으면 해싱된 값을 알려준다.



salt

그러면 어떻게 해야 할까? 해싱을 버리고 새로운 방법을 찾을까? 아니다. 새로운 방법을 사용한다. 바로 salt를 사용한 해싱이다.

해시값은 1234의 값과 1233, 혹은 12345의 해시값이 완전히 다르다. 띄어쓰기 하나만 들어가도, 언더바 하나만 들어가도 결과가 완전히 달라진다. 그래서 음식에 양념을 치듯이 데이터에 salt란 값을 붙여서 해싱한 후에, 값의 맨 앞에 이 salt에 대한 정보를 저장한다. 그러면 salt값을 알 수 없기 때문에 레인보우 테이블을 돌려도 해시값을 가지고 비밀번호를 알아내기 어려워진다. 또 salt값을 따로 관리할 필요도 없어 편리하며 안전하다.

이 방법을 사용해 회원가입할 때 비밀번호를 해싱해 저장하도록 하겠다.




회원가입 시 비밀번호 암호화 - bcrypt

비밀번호를 암호화하기 위해 bcrypt라는 라이브러리를 설치한다.

pip install bcrypt 

그리고 필요한 페이지에 import해준다. 지금은 회원가입 view가 있는 members.views.py에 import하면 될 것이다.

import bcrypt



bcrypt의 b는 bytes의 b다. bcrypt를 사용하기 위해서는 내가 가진 데이터, 해싱할 비밀번호값을 먼저 bytes로 변환해야 한다.

먼저 파일을 확인해 보자.

bcrypt를 import했다. 이메일과 비밀번호를 검증하는 if문들은 그대로 있으면 될 것이고, DB에 비밀번호를 그대로 삽입할 것이 아니라 해싱해 넣을 것이므로 create문 앞에서 암호화하면 될 것 같다.

  • 암호화를 하는 방법 : bcrypt.hashpw( byte화된 비밀번호, salt )
hashed_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())

password.encode("utf-8")는 password를 bytes형으로 인코딩하는 것이다. 단순 인코딩이기 때문이 디코딩하면 바로 원래의 값을 알 수 있다. utf-8을 소문자로 적는 것을 잊지 말자.

두번째 인자인 salt값은 직접 지정해줘도 되지만, 그렇게 하기보다 bcrypt.gensalt()를 이용하자.

파이썬 쉘에서 결과물을 확인하면 다음과 같다:

b'~~~'는 자료형이 bytes임을 말한다. 그러면 무사히 해싱된 이 값을 DB에 넣으면 될까?
땡!
bcrypt를 사용하기 위해서는 bytes형이 필요하고, 결과물도 bytes로 나오지만 DB에는 문자열로 넣어야 한다. 물론 그대로도 삽입할 수 있지만, b'~~~'형이 그대로 삽입되기 때문에 이 값을 다시 확인할 수 없게 된다. 그래서 이 값을 다시 decode한다.

hashed_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
str_password = hashed_password.decode("utf-8")

출력해 보면 다음과 같다. 앞의 $2b$12~가 salt다. 이 salt를 사용해 해싱했음을 알리는 것이다. 하지만 이렇게 할 것 없이 한번에 만들 수도 있다.

hashed_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8")

그리고 우리는 create문에 이 패스워드를 보내 줘야 한다. 이 hashed_password를 보내줘도 되겠지만,

이렇게 그냥 깡으로 입력하는 방법도 있다.




코드 전체를 따지면 이렇다.



마치며

이렇게 비밀번호를 무사히 암호화해 DB에 저장할 수 있었다.
그러면 이 로그인할 때엔 어떻게 해야 할까? jwt를 사용해 토큰을 발행할 수 있다.
다음 글에서는 jwt에 대해 포스팅하도록 하겠다.

profile
DA DA DA

0개의 댓글