기존의 hashing은 rainbow table에 의해 추적이 가능했다. 왜냐하면 동일한 password에서는 동일한 message digest가 생성되기 때문이다.
우리는 이러한 rainbow table attack을 두 개의 패스워드 input에서 절대 같은 hash가 나올 수 없도록 우리의 input을 바꿀 수 있다. 이것을 가능하게 하는 것이 salt이다. Salt는 충분한 random string이며 password의 앞에 붙는다. Salt와 패스워드를 붙인뒤 동일한 hashing algorithm을 통해 message digest를 만든다. 다른 유저가 같은 비밀번호를 설정했더라도 salt를 각각 다르게 적용함으로써 유저에 따라 다른 message digest를 table에 저장하게 된다.
만약 암호가 attacker에게 알려지지 않았다면, 그들은 각각의 고유한 salt에 대해 rainbow table을 생성하는 non-tractable한 문제를 마주할 것이다. 이것은 시간이 매우 오래 걸릴 것이다.
우리에게는 기존의 authentication checks에서 크게 달라지는 것이 없다. 데이터베이스에 message hash만 저장하는 것이 아니라 salt와 hash를 모두 저장하면 된다. 보통 그들은 concatenate를 통해 single string이 된다. 사용자가 password를 입력하면 그 input을 가져와서 salt와 붙이고 hash algorithm을 통과시켜 결과를 비교한다. message digest가 일치한다면 해당 사용자가 valid하다는 것을 안다.
이 개념에서 우리는 Salt Rounds를 간단히 언급한다. 이것은 비밀번호와 salt를 몇 번 re-hash해야 하는지에 대한 비용 요인이다. 즉, salt rounds를 10회 선택하면 2^10회 또는 1024회 계산이 수행된다. 각각의 시도는 이전 라운드에서 나온 해시를 입력으로 받아들인다. 회진이 많이 수행될수록 해시 계산에 더 많은 계산이 필요하다. 이는 단일 시도(즉, 로그인 시 비밀번호 확인)에 상당한 시간을 초래하지 않지만, brute force나 rainbow tables을 생성을 시도하려고 할 때 상당한 시간을 유발할 것이다.
Python은 bcrypt라는 패키지가 bcrypt hashing algorithm 뿐만 아니라 random salt generation까지 수행한다.
# Import the Python Library
import sys
!{sys.executable} -m pip install bcrypt
import bcrypt
password = b"studyhard"
# Hash a password for the first time with a certain number of rounds
salt = bcrypt.gensalt(14)
hashed = bcrypt.hashpw(password, salt)
# Check a plain text string against the salted, hashed digest
bcrypt.chekcpw(password, hashed)
보안을 위해서는 우리들끼리 패스워드를 수행하는것이 아니라 전문적인 팀원에게 맡기거나 third party authentication을 이용하는 것이 좋다.