TIL-45 인증 인가2

이동근·2021년 2월 9일
0

django

목록 보기
10/12

https://velog.io/@eagle5424/%EC%9D%B8%EC%A6%9D-%EC%9D%B8%EA%B0%80

요약 정리

인증 : 유저의 identification을 확인하는 절차를 의미
인가 : 유저가 요청하는 request를 실행할 수 있는 권한이 있는 유저인가를 확인하는 절차 이다.
bycrpt : 비밀번호 암호화 시에 사용하는 라이브러리를 의미한다. bycrpt에 관련해서 직접 알고리즘을 만들어서 사용할 수도 있지만 보안을 위해 이미 만들어진 것을 사용하는 것을 추천한다.
jwt(Json Web Token) : 로그인 즉 request 할 수 있는 권한을 가지고 있는 사람이라는 것을 알기 위해, Request의 headers 부분에 메타데이터를 보내는데, 이 메타 정보를 의미한다. 일종의 티켓이라고 생각하면 편하다.

단방향 해쉬 vs 양방향 해쉬

양방향 해시(AES-256)

  • 비밀번호를 암호화 하고 다시 복호화 할 수 있는 알고리즘
    (※ 복호화 : 아날로그 신호를 디지털 단위로 변환한 것을 부호화 라고 하는데, 이 부호화를 역순으로 수행하여 부호화 되기 전으로 되돌리는 것을 의미한다. 디코딩(decoding)이라고도 한다. )

  • 대표적으로 대칭키(비공개키), 비대칭키(공개키) 가 있다. 각각 장단점이 존재합니다.

    • 대칭키(비공개키) 방식

      • 암호화, 복호화시 모두 동일한 키를 사용한다.
      • 특징 : 암복호화에 동일한 키가 사용되는 방식 그래서 키를 비공개 한다.
      • 장점 : 속도가 빠르다.
      • 단점 : 키 배송 위험성이 존재하며 송신 측에 암호키를 전달과정에서 노출 우려가 있다.
      • 대표 : DES, AES
    • 비대칭키(공개키) 방식

      • 암호화와 복호화시에 다른 키를 사용한다.
      • 특징 : 암복화시에 다른 키가 사용되는 암호화 방식, 하나의 키는 공개키로 사용
      • 장점 : 키 배송의 문제를 근본적으로 차단하여 안정성이 높다.
      • 단점 : 대칭키방식보다 느리다.
      • 대표 : RSA

대칭형 암호화 방식은 훌륭한 암호화 방식이지만, 결정적인 문제가 존재한다. '키 배송'에 관련된 문제로 어떻게든 전달해야하지만, 키 배송과정중에 털리게 되면 아무리 뛰어난 알고리즘을 사용하더라도 속절없이 털리게 된다. 이런 단점을 해결하기 위해 나온것이 비대칭키 방식이다.

비대칭키 방식에 필요한 키는 두 개이다. 이 때 키를 A, B라고 가정했을때, 키 A로 암호화한 암호문은 키 B로만 복호화 할 수 있고, 키 B로 암호화한 암호문은 키 A로만 복호화 할 수 있다. 그래서 이 두개의 키 중 하나의 키만 비밀로 보호하고 다른 하나의 키는 공중에게 공개해도 관계가 없다. 어짜피 공개키로 암호화한 암호문은 개인키(비밀키)를 가진 사람만이 복호화 할 수 있기 때문에, 공개키로 암호화를 시킨뒤 개인이 가지고 있는 비밀키를 통해서 복호화를 하게 되면 키 배송시에 해킹당할 위험이 아예 사라지게 된다.

하지만 이러한 과정은 대칭키에 비해서 속도가 현저히 느리다는 단점이 있습니다. 따라서 현실적으로는 비대칭형 암호를 사용해서 대칭형 암호의 키를 배송하고, 실제 암호문은 대칭형 암호를 사용하는 식으로 상호보완적으로 이용하는 것이 일반적이다.

단방향 해쉬(SHA-256)

  • 본래 해쉬 함수는 자료구조에서 빠른 자료 검색, 데이터의 위변조를 확인하기 위해 사용되지만, 복원이 불가능한 단 방향 해쉬 함수는 암호학적 용도로 사용됩니다.
  • 1234를 SHA 해싱하게 되면
    '03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4' 이런식으로 암호화가 되어서 db에 저장이 되는데 보기에는 제대로된 암호화가 이루어진 것 같지만 같은 알고리즘으로 다시'1234'를 하게 되면 똑같은 값이 나오게 됩니다.
  • 이런 허점을 파고들어서 가능한 경우의 수를 모두 해시값으로 만들어서 판매하는 서비스도 존재하는데 이를 'Rainbow Table' 이라고 합니다.
  • 이 같은 허점을 해결하기 위해 Saltstretching 이라는 아이디어가 생겨나게 되#었습니다.

Salt와 keyStreching

  • 단순 해쉬값잉 노출되는 것을 막기위해 암호화된 해시값앞쪽에 임의의 무작위의 값을 Salt, 소금을 쳐서 저장하는 방법이 Salting 입니다.
  • 이런 Salting 값을 계산하는 시간을 늘리기 위해서 Salting과 해싱을 여러번 반복해서 원본값을 유추하기 어렵게 만드는 것이 KeyStretching 이라고 합니다.

이런 단방향 해시의 대표적인 라이브러리가 bycrpt 입니다.

  • bycrpt는 hash 결과값에 소금값과 해시값 및 반복횟수를 같이 보관하기 때문에 비밀번호 해싱을 적용하는데 있어 DB설계를 복잡하게 할 필요가 없습니다.
  • bycrpt를 통해 해싱된 결과값의 구조

실제로 사용하기

bycrpt

공식홈페이지 https://pypi.org/project/django-bcrypt/

pip install bycrpt

가상환경에 bycrpt를 설치를 해준다.

회원가입시에 비밀번호 암호화 후 저장

로그인 시에 암호화를 해줘야 하기 때문에

create 시에 password 에 bcrpyt.hashpw()를 통해 암호화를 해준다.
코드을 보면 request.body로 들어온 password 의 데이터를 encode를 통해 부호화를 해누고, gensalt()를 통해 salting까지 해주는 것을 볼 수 있다.
하지만 이렇게 되면 데이터 베이스에 바이트 타입으로 저장이 되게 된다.

이런 식으로 암호화된 비밀 번호 앞에 'b' 가 붙어서 바이트 타입으로 저장이 되는 것을 알수 있다. 하지만 models.py에서 만들때 binaryField로 만들지 않으면 문제가 된다. 나중에 로그인 View를 진행하는데 있어 checkpw에서 db에 저장되어 있는 비밀번호와 입력한 비밀번호를 비교하는 과정이 이루어진다. 그런데 이상태로 db에 저장이 되게 된다면 바이트 타입이라고 표시한 b 마저도 비밀번호로 인식이 이루어 지게 되서 오류가 나게 된다.

이를 방지하기 위해 암호화가 이루어진 비밀번호 끝에 decode('utf-8'), string 타입으로 변형 시켜주는 복호화를 한 번 해준 뒤에 저장을 해준다.


password의 앞에서 'b'가 없어진 채로 저장이 되어있는 것을 볼 수 있다.

로그인 시에 비밀번호 확인 후 토큰 발행

FE가 보내준 데이터의 password를 바이트 타입으로 바꾸고, db에 저장되어 있는 비밀번호를 다이 바이트 타입으로 바꾸어서 비교를 해준다.
코드

if bcrpyt.checkpw(data['password'].encode('utf-8'), user.password.encode('utf-8)):

data['passowrd'].enode('utf-8) -> FE에서 받은 비밀번호를 부호화
user.password.encode('utf-8') -> string 타입으로 저장되어 있는 db를 부호화 해서 비교
두개가 일치하지 않는다면 400에러
일치한다면!!!
access_token발급 -> JWT발행

access_token = jwt.encode({'id': user.id}, 'secret', algorithm='HS256').decode('utf-8')

JWT를 부호화(encode)를 해서 token에 정보를 담아줄 것이다. Json 으로 통신을 할것이기때문에 담아야 할 내용(user.id)를 dict의 형태로, 암호화키 = 'secret', 암호화한 algorithm='HS256'을 담아주고 로그인에성공했다는 티켓인 token을 JsonResponse에 담아서 return 해준다.


이런식으로 password를 암호화를 해서 저장하고 login시에 저장되어있는 password를 비교해서 token을 주는 형식으로 bcrpyt를 사용해서 암호화를 해보았다.

profile
하루하루 1cm 자라는 개발자

0개의 댓글