post-thumbnail

사진출처

백엔드 개발자로서 회원가입과 로그인 기능 구현 시 꼭 알아야 할 인증의 개념과 비밀번호 암호화 방식에 대해서 알아보도록 하겠다.

🤙 인증(Authentication)

인증이란?

언제 인증을 사용할까?

어떤 과정으로 이루어질까?

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

🔑 비밀번호 암호화

img

사진출처

비밀번호를 암호화해서 저장해야 하는 이유

(페이스북에선 2019년까지도 사용자의 비밀번호를 평문으로 저장해왔다고 한다.. 참고 기사)

비밀번호 암호화 시기

  1. DB에서 비밀번호 저장할 때 암호화 Databases에 저장 시 개인 정보를 해싱하여 복원할 수 없도록 한다. (비밀번호가 이미 백엔드로 넘어갔을 때)
  2. 통신 시 개인 정보를 주고받을 때 SSL을 적용하여 암호화(HTTPS) –> 이 부분은 따로 포스팅할 예정 (프론트에서 백으로 텍스트가 전달될 때)

🔒 비밀번호를 저장할 때 사용하는 암호화 방식

단반향 해쉬 함수

img

사진출처

b2fd5cdba2b1484db46c26a3426f70878d2b31f44f18f806fd262f34887a6320
4d6ba57a1cbffa2fd4def7c2a0b74f1151971454659b78a833103c4e60d7da0d

단방향 해시 함수의 문제점

인식 가능성(recognizability)

속도(Speed)

단방향 해시 함수 보완하기

img

솔팅(Salting)

키 스트레칭(Key Stretching)

양방향 암호화는 언제 쓰이나?

양방향 암호화는 백엔드 개발자가 암호화해서 저장해야 하는 민감한 정보이나 다시 복호화해서 사용해야 하는 경우에 사용된다. 예를 들어 병원 시스템에서 주민등록번호는 민감한 정보이긴 하나 자주 사용해야 하므로 복호화할 수 있어야 한다. 또한, 쿠팡에서 쉽게 결제할 수 있는 이유도 신용카드 정보를 양방향 암호화로 저장해두었기 때문이다. 엄격하게 하는 곳은 주소도 양방향 암호화 해두기도 한다.


🔏 bcrypt

bcrypt 사용하기

bcrypt를 설치한다.

pip install bcrypt 

bcrypt를 import한다.

import bcrypt

비밀번호 암호화하기

bcrypt는 str데이터가 아닌 bytes 데이터를 암호화한다. str 을 encode해서 bytes로 만들어 준다.(반대는 decode이다.) encode 시에는 우리가 인식할 수 있는 형태로 변환하기 위해 UTF-8 유니코드 문자 규격을 사용한다.

password = '1234'
encoded_password = password.encode('utf-8')

bcrypt.hashpw() 메소드는 (bytes 형식의 패스워드, 소금값)을 인자로 받아 해싱된 비밀번호를 만든다. bcrypt.gensalt() 메소드로 랜덤한 소금값을 생성할 수 있다.

hashed_password = bcrypt.hashpw(encoded_password, bcrypt.gensalt())

print()로 확인해보자. 암호화된 데이터의 타입은 Bytes이다.

print(hashed_password)
b'$2b$12$YFs9rh.1LgJwZuf9ibyjpuLvBoCaGX0MzedFWF2Jo0zU3lMZurZ4a'

type(hashed_password)
<class 'bytes'>

비밀번호 확인하기

bcrypt.checkpw() 메소드로 입력된 비밀번호가 맞는지 확인할 수 있다. (입력받은 패스워드, 저장된 암호화된 패스워드)를 각각 인자로 받는다. 일치하면 True를 반환한다.

new_password = '1234'
bcrypt.checkpw(new_password.encode('utf-8'),hashed_password)
True

참고사이트 https://d2.naver.com/helloworld/318732 https://st-lab.tistory.com/100 https://k0102575.github.io/articles/2020-03/hash https://velog.io/@nameunzz/단방향-해시-함수 https://velog.io/@hwang-eunji/backend-django-비밀번호-암호화-구현