Django : Westagram #4 / 인증 / 인가 / bcrypt

Jinsung·2021년 11월 25일
0

인증(Authentication)

인증은 회원가입과 로그인을 생각하면 편하다. 누구인지 확인하는 절차

인가(Authorization)

인증으로 들어왔으니 그 유저에 대한 권한을 허락하는 것

  • 알고리즘 SHA-256을 대부분 사용
  • 암호화 방법에는 단방향과 양방향 두가지 방법이 있다
  • 단방향이 아닌 양방향 암호화는 카드 결제 방식 저장, 배송지 저장등에 사용된다.

로그인 절차

  • 유저 아이디와 비밀번호 생성
  • 유저 비밀번호를 암호화 해서 DB에 저장
  • 유저 로그인 → 아이디와 비밀번호 입력
  • 유저가 입력한 비밀번호를 암호화 한 후 암호화돼서 DB에 저장 -된 유저의 비밀번호와 비교
  • 일치하면 로그인 성공
  • 로그인 성공하면 access token을 클라이언트에게 전송
  • 유저는 로그인 성공 후 다음부터는 access token을 첨부해서 request를 서버에 전송함으로써 매번 로그인 해도 되지 않도록 한다.

회원 가입 할때 비밀번호를 암호화 해서 DB에 저장하는걸 bcrypt로 진행

bcrypt

취약점

위에서 설명한 단방향 해시 함수도 몇가지 취약점이 존재한다.

  • Rainbow table attack : 미리 해시값들을 계산 해 놓은 테이블을 Rainbow table 이라고 한다.
  • 해시 함수는 원래 패스워드를 저장하기 위해서 설계된 것이 아니라 짧은 시간에 데이터를 검색하기 위해 설계된 것이다. 그렇기 때문에 해시 함수는 본래 처리 속도가 최대한 빠르도록 설계되었다. 이러한 속성 때문에 공격자는 매우 빠른 속도로 임의의 문자열의 digest와 해킹할 대상의 digest를 비교할 수 있다. 이런 방식으로 패스워드를 추측하면 패스워드가 충분히 길거나 복잡하지 않은 경우 비밀번호를 알아내는데 그리 긴 시간을 필요로 하지 않는다.

보완점

  • Salting
  1. 임의의 문자열을 추가해서 암호화
  2. 실제 비밀번호에 랜덤 값을 더해서 해시 값을 계산합니다.
  • Key Stretching
  1. 해쉬 값을 여러번 반복해서 해시 하는 행위입니다.
  2. 여러 번 반복하면 그만큼 해킹하는데 걸리는 시간이 길어집니다.

Salting과 Key Stretching을 구현 한 해시 함수 중 가장 널리 사용되는 것이 bcrypt이다. bcrypt는 처음부터 비밀번호를 단방향 암호화 하기 위해 만들어진 해시 함수이다.

bcrypt

설치

pip install bcrypt

선언

import bcrypt
passwd = '1234567'

encode진행하면 type이 str -> byte로 바뀐다

>>> passwd.encode('utf-8')
b'1234567'

decode 진행하면 byte -> str로 바뀜

>>> a=passwd.encode('utf-8')
>>> a.decode('utf-8')
'1234567'

bcrypt.gensalt()는 바이트 형식이다

>>> bcrypt.gensalt()
b'$2b$12$u3h5n4YsXmF9SiFoxgEFJe'

암호화된 패스워드 만들기

입력 받은 패스워드를 바이트로 바꾸고 salt를 붙힌다 그리고 다시 decode하여 str로 변환시킨 후 DB에 넣어주면 된다.

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

create 위에 패스워드를 암호화 한 후 DB에 저장한다.


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

            User.objects.create(
                name     = name,
                email    = email,
                password = hashed_password,
                phone    = phone
                )

DB 값과 입력값이 동일한지 확인하는 명령어

>>> c = '1234567'
>>> d = '123'
>>> hashed_password = bcrypt.hashpw(passwd.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
>>> bcrypt.checkpw(c.encode('utf-8'),hashed_password.encode('utf-8'))
True
>>> bcrypt.checkpw(d.encode('utf-8'),hashed_password.encode('utf-8'))
False

0개의 댓글