티스토리 뷰

웹 개발을 하다보면 비밀번호를 안전하게 저장해야한다. 일반적으로 해싱을 통해 이것을 해결하는데 단순 해싱의 문제점이 있다. 바로 동일한 문자열을 해싱했을 때 동일한 결과값이 나온다는 점이다. 만약 DB가 유출되었을 때 password의 해시값을 통해 원본 값을 얻어내긴 힘들겠지만, 비밀번호가 같다는 것을 알 수 있게 되므로 큰 문제다. 


Python에서는 암호화를 위해 pycrypto라는 라이브러리를 많이 사용한다고 한다. 실제로 github에서도 많이 starred 되어 있다. 하지만 나는 bcrypt를 추천하고 싶다. 특히 Flask-Bcrypt. 일단 사용법이 정말 간단하고 쉽다. 알아둬야 할 함수는 두 개 뿐일정도다. 


하지만 가장 큰 이유는 Flask-Bcrypt를 통해 암호화 된 결과값이 저장하기가 용이하다는 점이다. pycrypto를 통해 encrypt 된 결과값은 난해하다. 그리고 unicode로 곱게 변환이 되지 않는다! 이는 큰 문제인데, 왜냐하면 mysql에 저장할 수가 없게 되기 때문이다. 이를 해결하기 위해서 나는 hexlify시키는 등의 가공을 했었다. 그러나 또 하나 문제가 있다. 동일한 문자열을 pycrypto의 cipher로 encrypt를 할 때마다 다른 결과값이 나오긴 하지만, 새로 생성한 cipher의 최초 encrypt 결과는 동일하다는 것이다. 즉, 매번 암호화를 위해 cipher를 생성할 경우 같은 입력에 같은 결과가 나온다는 뜻이다. 


이는 내가 처음 원했던 결과와 완전히 엇나간다. 해결방법은 분명히 있지만 당시 나는 멘탈이 바스라져서 더 이상 삽질을 하고 싶지 않았고 곧바로 bcrypt로 갈아탔다. 그리고 나는 10분만에 원래 해결하고자 했던 이슈를 해결할 수 있었다.


from flask import Flask

from flask.ext.bcrypt import Bcrypt


app = Flask(__name__)

app.config['SECRET_KEY'] = 'I am your father'

app.config['BCRYPT_LEVEL'] = 10


bcrypt = Bcrypt(app)


pw_hash = bcrypt.generate_password_hash('password')

pw_hash2 = bcrypt.generate_password_hash('password')


bcrypt.check_password_hash(pw_hash, 'password') # True

pw_hash == pw_hash2 # False


이것이 사용 방법의 전부다. 보면 알겠지만 Flask랑 잘 붙어있게 되어 있다. (이름만 해도 벌써 Flask가 붙어있다.) 원래 bcrypt라는 것은 암호화 알고리즘 이름인지라 비슷한 이름의 라이브러리가 많이 있다. Flask-Bcrypt는 Flask 환경에서 쉽게 쓸 수 있게 만들어진 녀석인 것이다. 


1. bcrypt를 처음 생성한 뒤 해싱 결과는, 다음에 또 bcrypt를 처음 생성한 뒤의 해싱 결과와 다르다. 즉, 같은 조건으로 다시 cipher를 만들어도 첫 해싱 결과 값이 다르다.

2. 물론 같은 input을 해싱할 때마다 다른 결과값이 나오고

3. 그럼에도 불구하고 check를 할 때 문제가 없다.


이 녀석을 안 쓸 이유가 없지 않나? 처음부터 이 녀석을 썼어야 했는데 -_-



댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday