
우리는 수많은 웹사이트 속에 있고,
웹사이트 수 만큼 존재하는 각자의 ID가 있다.
웹에서는 어떻게 ID, PW를 보관하고 비교하고 암호화할 수 있을까??
위키에 따르면 bcrypt는 비밀번호 해시함수다. (Hash형 자료구조 참고)
Niels Provos와 David Mazieres에 의해 만들어졌으며 Blowfish라는 암호에 기반하였다.
일단 우리는 터미널에서 해당 입력어를 통해 install한다!
pip install bcrypt
그런 다음, import bcrypt를 해주고, 비밀번호를 암호화를 설정해준다!
암호화하는 방법은 의외로 간단하다!
bcrypt.hashpw(문자열.encode('utf-8'), bcrypt.gensalt())
위와 같은 코드로 작성하면 되는데, 받는 인자는 다음과 같다.
실제 프로젝트에 적용해보면,
import json
from django.views import View
from django.http import JsonResponse
import bcrypt
from .models import Accounts
class AccountView(View):
def post(self, request):
data = json.loads(request.body)
# 필수사항 미입력시
try:
email = data['email']
password = bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt())
.
.
.
mysql> select password from accounts;
+-----------------------------------------------------------------+
| password |
+-----------------------------------------------------------------+
| 12345678 |
| b'$2b$12$TqRaIL6suby0BQHBVfNL6udGCgBxc0F3Uz5KtsUkqaHlT6xJZlxFy' |
+-----------------------------------------------------------------+
2 rows in set (0.00 sec)
이와같은 결과가 나온다.
mysql에도 예전에는 '12345678'로 들어갔던 암호가 알수없는 문자열로 들어간걸 볼 수 있다! (위대한 암호화!!)
이건 더 쉽다!(너무 쉽다 쉬워!!)
bcrypt의 checkpw()를 쓰면 된다. 이 함수는 2개의 인자를 갖는데,
으로 비교해주면 쉽게 결과가 나온다.
# password 있는지 확인
if 'password' in data:
password = bcrypt.checkpw(data['password'].encode('utf-8'), account.password)
else:
return JsonResponse({'message': 'KEY_ERROR'}, status=400)
[01/Feb/2021 07:12:10] "POST /account/login HTTP/1.1" 200 22
잘 연결이 되는것을 확인 할 수 있다!
이번에 쓸 라이브러리는 pyjwt!

JWT는 JSON Web Token라는 약어로 정보를 안전하게 전송하기 위해 정의된 공개된 표준(RFC 7519)이다. 이 라이브러리는 아래와 같은 특징을 가지고 있다.
JSON 객체를 사용하여 자가수용적이다.stateless 같은 속성이 상쇄된다. 
pip install pyjwt
해당 JWT를 다운받아준다. (python이라서 pyjwt)
import jwt # 라이브러리 이름은 pyjwt지만 import는 jwt로 사용!
class LoginView(View):
def post(self, request):
data = json.loads(request.body)
access_token = data.get('token')
if access_token:
payload = jwt.decode(access_token, my_settings.SECRET, algorithms=my_settings.ALGORITHM)
if Accounts.objects.filter(email=payload['email']):
print('-------------------------- token!!')
return JsonResponse({'message': 'SUCCESS', 'token': access_token, 'info': payload}, status=200)
try:
...
access_token = jwt.encode({'email' : account.email}, my_settings.SECRET, algorithm=my_settings.ALGORITHM)
return JsonResponse({'message': 'SUCCESS', 'token': access_token}, status=200)
except KeyError:
return JsonResponse({'message': 'KEY_ERROR'}, status=400)
import는 jwt로 해주면 된다.
먼저, try안에 있는 access_token이라는 변수를 보면 jwt.encode()가 실행되었다.
해당 코드의 jwt.encode()에는 3가지 인자를 받아서 사용했다.
해당 인자를 바탕으로 생성하게 되면 salt가 추가되어 잘 양념된 JWT값이 나오게 된다!
HTTP/1.1 200 OK
Content-Length: 162
Content-Type: application/json
Date: Tue, 02 Feb 2021 01:20:02 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.5
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"message": "SUCCESS",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InRqZHduczAzMDlAbmF2ZXIuY28ua3IifQ.2m-qLIVJ__TT1pEnUjEkOSOvptcbozg6MvKIvRFIZBQ"
}
try문 밖에 있는 if문들을 살펴보자
첫번째 if에서는 token이라는 키가 있어 값이 있다면 해당 token이 우리가 발행한게 맞는지 검사하는 decode()를 실행하게 된다.
그뒤 payload 변수를 만들어 jwt.decode()를 실행하게 된다.
jwt.decode()도 3가지의 인자를 가지게 된다.
encode() 할 때 사용되었던 동일한 SECTER_KEYencode() 할 때 사용되었던 동일한 ALGORITHMSrequest.body에 발급받은 토큰의 정보를 보내주면 아래와 같이 잘 실행되어 'email'의 정보를 받아올 수 있다.
(id의 종류로는 3개가 있지만 지금의 경우엔 'email'을 사용했다.)
http POST 127.0.0.1:8000/account/login email="abc@naver.com"
password=12345678
token='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InRqZHduczAzMDlAbmF2ZXIuY28ua3IifQ.2m-qLIVJ__TT1pEnUjEkOSOvptcbozg6MvKIvRFIZBQ'
{
"info": {
"email": "abc@naver.com"
},
"message": "SUCCESS",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InRqZHduczAzMDlAbmF2ZXIuY28ua3IifQ.2m-qLIVJ__TT1pEnUjEkOSOvptcbozg6MvKIvRFIZBQ"
}
Bcrypt 종류를 처음 알게 되었다. (비밀키, 공개키만 알고 있었다.)JWT의 특징들과 쓰게되는 이유JWT가 가지는 각 부분들에 대한 정보JWT의 encode(), decode()의 사용 방법SCERET_KEY를 주고, 왜 그것을 git에 올리면 안되는지ㅋㅋㅋㅋhash 동작 방법을 알지만, 어렵게 느껴진다.. 만드신분들 감사합니다...ㅎㅎJWT가 다양한 언어에서 쓰이는 것을 보고 또 우리의 편의성을 위해 다른분들이 고생했다는 것을 절실히 깨닫는 오늘의 공부..발전하는 암호화기술, 그것을 부수려 발전하는 해킹기술... 그리고 그뒤를 맹렬히(?) 따라가는 나!!
오 성준님 이번 글 많이 도움됐어요. 감사합니당.