TIL no.63 - Back End - 암호화

박준규·2019년 10월 26일
0

개인정보보호는 매우 중요한 이슈입니다.
데이터베이스에 그대로 유저의 패스워드를 저장할 수는 없습니다.
데이터베이스가 해킹당하면 유저의 패스워드가 그대로 노출되기 때문입니다.

그렇기 때문에 데이터베이스에 유저의 패스워드를 암호화해서 저장해야 합니다.

암호화의 종류는 크게 단방향, 양방향 알고리즘으로 나뉩니다.

둘의 차이는
단방향은 복호화가 불가능하고
양방향은 복호화가 가능합니다.


1. one-way hash function

패스워드 암호화에는 일반적으로
단방향 해쉬 함수(one-way hash function)가 쓰입니다.

hash란 chop and mix를 뜻합니다.
해쉬 포테이토를 떠올리면 이해가 빨리 될 것입니다.

한마디로 복호화가 불가능하게 비밀번호라는 재료를 다지고 소금과 함께 섞어 요리를 완성하는 것입니다.

해쉬포테이토로 만든 감자는 다시 원형의 감자로 되돌릴 수 없듯이 말입니다.

여기서 해쉬포테이토처럼 완성된 요리.
즉, 암호화된 패스워드를 digest라고 표현합니다.


2. bcrypt

단방향 해쉬 함수의 취약점은 다음과 같습니다.
1. Rainbow table attack
미리 해쉬값을 계산해 놓은 table을 rainbow table이라고 합니다.
2. hash function은 원래 짧은 시간안에 데이터를 검색하기 위해 설계됨.
패스워드를 위해 설계된 것이 아니라 빠른 데이터 검색을 위해 설계되었기 때문에 처리속도가 매우 빠릅니다.
그래서 해커는 임의의 digest와 해킹할 대상의 digest를 빠른 속도로 비교할 수 있습니다.(초당 56억개)

위와 같은 취약점들을 보완하기 위해 일반적으로 다음 두가지 방법들이 사용됩니다.

  1. salting
    실제 비밀번호에 랜덤한 추가데이터를 넣어서 해시값을 계산합니다.
  2. Key Stretching
    반복적으로 해쉬합니다.

bcrypt는 패스워드 해쉬 함수여서
일반적으로 많이 사용됩니다.


Django로 회원가입 view를 구현하면서 bcrypt를 사용해보겠습니다.

import bycrypt

input_data = {
	'email':'devzunky@gmail.com',
    'password':'931206',
}

byted_password=input_data['password'].encode('utf-8')
hashed_password=bcrypt.hashpw(byted_password, bcrypt.gensalt())

Users(
	email=input_data['email'],
	password=hashed_password.decode('utf-8'),
	).save()

bcrypt의 hashpw() 메서드는 인자로unicode가 아닌 byte string을 사용해야하기 때문에 hashing하기 전에 꼭 encoding해야 합니다.

위의 과정을 간단히 표현하면 다음과 같습니다.

1. unicode -> byte string
    (encoding)
2. byte string -> hashed
    (hashing)
3. hashed -> unicode
    (decoding)
4. DB에 저장

그리고 로그인 view를 구현하겠습니다.

if Users.objects.filter(email=input_data['email']).exists():
			#DB에 존재하는 유저 정보 받아오기
			user_in_db=Users.objects.get(email=input_data['email'])
			#패스워드 일치 확인
			if bcrypt.checkpw(input_data['password'].encode('utf-8'), user_in_db.password.encode('utf-8')):
				return JsonResponse({'message':f'Hi!, {user_in_db.name}'}, status=200)
			else:
				return JsonResponse({'message':'Name or password does not match', status=401}

bcrypt의 checkpw() 메서드는
hash되어 있지 않은 원본과
hash되어 있는 값을 비교합니다.

그리고 이 메서드 또한 byte string을 인자로 받습니다.

checkpw() 메서드는 패스워드가 일치하면 True, 불일치하면 False를 return합니다.

profile
devzunky@gmail.com

0개의 댓글