대표적인 해시함수 SHA-256은 입력값을 아주 빠르게 해시값으로 변환할 수 있다.
요즘 GPU는 SHA-256을 초당 수십억 번 계산할 수 있어서, 입력값을 Salting해도 무차별 대입으로 암호를 풀 가능성이 있다.
이러한 경우를 보완하기위해 고안된것이 비밀번호 저장 전용 해시 알고리즘인 bcrypt이다.
"느리게 만든다."
내부적으로 해시 연산을 수천 ~ 수십만번 반복시켜 한 번의 해싱에 더 많은 시간이 걸리게 만든다.
그래서, 무차별 대입시 SHA-256보다 훨씬 더 많은 시간이 소요된다.
이때, cost factor는 해당 해시값에 해시연산이 몇번 반복되었는지를 나타낸다.
cost factor가 12라면 번만큼 해시 연산되었다는 의미이다.
초기 테이블 → 비밀번호+salt로 1번 변형 → 비밀번호로 다시 변형 → salt로 다시 변형 → ...
(이걸 무수히 반복)
↓
최종 테이블로 입력값 암호화 → 해시 결과
$2b$12$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
│ │ │ └────── salt(22자) ──────┘└────── hash(31자) ──────┘
│ │ └ cost factor (12)
│ └ 알고리즘 식별자 (2b = bcrypt)
└ 구분자
bcrypt에선 특정값을 해싱할때, 매번 랜덤한 salt값을 적용하여 해싱한다.
그래서, 같은 입력에도 매번 다른 해시값을 반환한다.
그럼 bcrypt은 어떻게 해시값을 검증할까?
bcrypt은 일반 해시처럼 단순 해시값끼리 비교하여 검증하지않는다.
검증하기위해 입력값과 해시값이 필요하다.
bcrypt.verify(입력_비밀번호, 저장 해시값)
해시값안에 salt와 cost factor가 저장되는 이유가 여기에 있다.
파라미터로 받은 해시값에서 salt와 cost factor를 추출해, 입력값에 동일하게 해싱하여 해싱된 값을 비교하여 검증한다.