bcrypt는 암호를 단방향 암호화해주는 파이썬 라이브러리다
단방향 암호화를 하면 평문을 암호화하는것은 가능하지만 암호문을 평문으로 복호화 하는것은 d어렵다(불가능한건 아니다). 그래서 비밀번호를 관리할 때 유용하게 쓰인다. 왜냐하면 db에 암호화되어 저장된 비밀번호를 복호화 하는것도 불가능하기 때문에 내부자가 회원의 비밀번호를 알아내는것도 불가능하며 오직 회원이 입력한 비밀번호와 일치하는지만 확인 가능하기 때문이다.
가상환경을 구축한 뒤 bcrypt를 설치해 간단한 실습을 했다.
hahsing: 원본의 의미를 알 수 없게 섞어놓는 것
salting: 실제 비밀번호에 랜덤 값을 더해서 해시값을 계산하는 방법
key stretching : 해쉬 값을 여러번 반복해서 해시 하는 행위
conda create -n auth python=3.8 #auth라는 이름의 가상환경 구축
conda activate auth #구축한 auth 가상환경을 활성화. 접속
pip install bcrypt #1
pip install pyjwt #2
파이썬 패키지 관리 시스템인 pip를 이용해 bcrypt와 pyjwt를 설치한다
pyjwt는 jwt(json web token)을 암호화, 복호화 해주는 파이썬 라이브러리다
python #파이썬 실행
-
>>> import bcrypt #1
>>> password = 'pass1234' #2
>>> bcrypt.hashpw(password, bcrypt.gensalt()) #3
bcrypt를 불러오고 password라는 변수에 str 형식의 암호화 할 대상을 담았다.
그리고 #3에서 오류가 발생했다.
TypeError: Unicode-objects must be encoded before hashing
암호화 함수는 오직 bytes string에서만 작동하기 때문에, 해싱하기 전에 password를 bytes string으로 변환해줘야 한다. 현재 password는 str이다. 이 때 utf8 인코딩을 하기로 한다.
password.encode('utf-8')
>>> b = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
암호화 된 bytes 형식의 password가 입력되는것을 볼 수 있다.
암호화 된 비밀번호는 데이터 형식이 바이츠이기 때문에 다시 디코딩을 해줘 데이터베이스에 저장해야 한다.
암호화(인코드)된 password가 입력한 문자열과 일치하는지 확인해보자
>>> c = 'password1234'
>>> bcrypt.checkpw(c.encode('utf-8'), b)
-
>>> c = 'password123'
>>> bcrypt.checkpw(c.encode('utf-8'), b)
각각 True, False가 도출된다
사용자가 id, password를 입력해 로그인 버튼을 누르면 서버는 id와 password를 db에 저장된 것과 비교하고 인증이 완료되면, 회원에게 토큰을 발행해준다. 그 토큰은 사용자 브라우저의 쿠키나 세션스토리지에 저장되어 서버에 데이터를 요청할 때 마다 토큰을 담아서 정보를 요청하고, 서버는 해당 토큰을 검증한 뒤 데이터를 전송한다.
jwt
>>> import jwt #설치는 pyjwt로 했지만, 쓸 때는 jwt로 한다
>>> jwt.encode({'user_id' : 1}, 'blah', algorithm='HS256') #2
>>> jwt.decode({'user_id' : 1}, 'blah', algorithm='HS256') #3
> {'user_id' : 1} #4
토큰 대상, 시크릿 키, 해싱 알고리즘을 차례로 넣어준다
다만 토큰 방식도 토큰이 탈취당할 경우 정보 보안에 타격을 입는다는 것은 같다. 이를 보완하기 위해 refresh token 방식도 존재한다.
참고
토큰 기반 인증에 대한 이해 https://velopert.com/2350
https://tansfil.tistory.com/58