1. bcrypt설치 2. bcrypt 모듈 불러옴 import bcrypt 3. 해시할 문자열 인코딩 4. password 해시
import bcrypt maro_password = 'mypassword_1234' print (maro_password) enc_password = maro_password.encode('utf-8') print (enc_password) hashed_pw = bcrypt.hashpw(enc_password, bcrypt.gensalt()) print(hashed_pw)
5. 해시된 password 디코딩 6. 해시되고 디코딩된 password를 보관
dec_password = hashed_pw.decode('utf-8') print(f'DB Save\t\t: { dec_password}')
7. 비밀번호비교
a = '1234' # 사용자가 입력한 패드워드 # hased_pw는 DB에 저장된 암호화된 패스워드 isPass = bcrypt.checkpw(a.encode('utf-8'), hashed_pw) print(f"{a}\t\t: {isPass}")
단방향 암호화에 사용되는 해시 알고리즘은 동일한 평문에 대해 항상 동일 해시값을 갖는다. 따라서 특정 해시 알고리즘에 대하여 특정 평문이 어떤 해시값을 갖는지 알 수 있다.
또한 해시 함수는 본래 신속히 데이터를 검색하기 위해 탄생됐다. 따라서 공격자는 매우 빠른 속도로 임의의 문자열의 해시값과 해킹할 대상의 해시값을 비교하여 대상자를 공격할 수 있다.
이런한 문제를 보안하기 위해 단방향 암호화를 진행할 때 솔팅(Salting)과 키 스트레칭(Key Stretching)을 적용 시킨다.
솔팅은 단방향 해시 함수 암호화를 진행 할 때 본래 데이터에 추가적으로 랜덤한 데이터를 더하는 방식이다. 원래 데이터에 추가 데이터가 포함 되었기 때문에 이전의 해시값과 달라진다.
단방향 해쉬값을 계산 한 후, 그 해쉬값을 또 다시 해시하고 또 이를 반복하는 방식이다. 최근 일반적인 장비로도 1초에 50억 개 이상의 해시값을 비교할 수 있다. 하지만 키 스트레칭을 적용하면 동일 장비에서 1초에 5번 정도만 비교할 수 있다. GPU(Graphics Processing Unit)를 사용하더라도 수백에서 수천 번 정도만 비교할 수 있다.
Bcypt는 브루스 슈나이어가 설계한 키(key) 방식의 대칭형 블록 암호에 기반을 둔 암호화 해시 함수다. Niels Provos 와 David Mazières가 설계했다. Bcrypt는 레인보우 테이블 공격을 방지하기 위해 솔팅과 키 스트레칭을 적용한 대표적인 예다.
$2b$12$76taFAFPE9ydE0ZsuWkIZexWVjLBbTTHWc509/OLI5nM9d5r3fkRG \/ \/ \____________________/\_____________________________/ Alg Cost Salt Hash
Bcrypt는 단방향 해시 알고리즘이다. 따라서 복호화가 불가능하다. Bcrypt의 검증은 암호화된 값이 가지고 있는 알고리즘, Cost Factor, Salt를 이용한다.
$ npm install bcrypt --save
const bcrypt = require("bcrypt"); // (1)
const password = 'password'; // (2)
const saltRounds = 12; // (3)
const makeHash = async (password, saltRounds) => {
return await bcrypt.hash(password, saltRounds); // (4)
}
const main = async () => {
const hashedPassword = await makeHash(password, saltRounds);
console.log(hashedPassword);
}
main()
=> b'$2b$12$76taFAFPE9ydE0ZsuWkIZexWVjLBbTTHWc509/OLI5nM9d5r3fkRG'
const checkHash = async (password, hashedPassword) => { return await bcrypt.compare(password, hashedPassword) // (1) } const main = async () => { const hashedPassword = await makeHash("password", 12); const result = await checkHash("password", hashedPassword); console.log(result); }; main() => true(or false) // (2)