Salt는 암호화된 비밀번호의 보안을 강화하기 위한 임의의 데이터를 의미합니다. 일반적으로 비밀번호를 해시화할 때 Salt를 추가하여, 동일한 비밀번호라도 매번 다른 해시 값을 생성하도록 만듭니다. 이를 통해 무차별 대입 공격(Brute Force Attack)과 레인보우 테이블 공격(Rainbow Table Attack) 같은 공격을 방어할 수 있습니다.
- 동일한 비밀번호에 대한 다른 해시 값 생성:
- 만약 사용자가 동일한 비밀번호를 사용하더라도, Salt를 추가하여 해시화하면 서로 다른 해시 값이 생성됩니다.
- 예를 들어,
password123
라는 비밀번호가 두 명의 사용자에게 입력되었을 때, 두 명의 사용자에게 저장되는 해시 값은 서로 달라집니다.
- 레인보우 테이블 공격 방어:
- 레인보우 테이블은 미리 계산된 해시 값과 원본 비밀번호를 매칭시킨 테이블입니다. 이를 통해 해시된 비밀번호를 빠르게 복호화할 수 있습니다.
- Salt를 사용하면 동일한 비밀번호라도 매번 다른 해시 값을 생성하기 때문에, 레인보우 테이블을 사용한 공격을 어렵게 만듭니다.
- 무차별 대입 공격 방어:
- 무차별 대입 공격은 가능한 모든 비밀번호 조합을 시도하는 방식입니다. Salt를 사용하면 해시 값이 다르므로 공격자가 매번 새로운 해시 값을 계산해야 하므로 공격 속도가 느려집니다.
Salt 과정
- Salt 생성:
- Salt는 일반적으로 랜덤한 문자열로 생성됩니다. 이 문자열은 비밀번호와 결합하여 해시화됩니다.
- Salt와 비밀번호 결합:
- 비밀번호와 Salt를 결합하여 새로운 문자열을 만들고, 이를 해시 함수에 전달하여 해시 값을 생성합니다.
- 예를 들어, 비밀번호
password123
와 SaltrandomSalt
를 결합하면password123randomSalt
라는 문자열이 만들어지고, 이 문자열이 해시화됩니다.
- Salt 저장:
- Salt는 해시 값과 함께 저장됩니다. 이때, Salt는 평문으로 저장되며, 해시 값과 함께 데이터베이스에 저장됩니다.
- 비밀번호를 검증할 때는, 저장된 Salt를 다시 사용하여 동일한 방법으로 해시화하고, 결과를 비교합니다.
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class SaltExample {
public static void main(String[] args) {
String password = "password123";
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
// 비밀번호 해시화 (자동으로 Salt를 생성하고 포함)
String encodedPassword = encoder.encode(password);
System.out.println("Encoded Password: " + encodedPassword);
// 비밀번호 검증
boolean matches = encoder.matches(password, encodedPassword);
System.out.println("Password matches: " + matches);
}
}
출력 예시:
Encoded Password: $2a$10$e8a5d9d4b8a9e6f78c9e5fcb0e2d1d5a2d5f19e4d47f35f4a5h5W
Password matches: true
단방향 해시 함수는 해시된 값만으로 원래 비밀번호를 추측하는 것이 매우 어렵도록 설계되어 있습니다. 이를 통해 비밀번호의 안전성을 높이고 비밀번호 유출 시에도 공격자가 원본 비밀번호를 쉽게 추측할 수 없도록 만듭니다. BCrypt
와 같은 알고리즘은 Salt, 반복적인 해시 계산, 단방향 해시 특성을 결합하여 비밀번호 보안을 강화합니다.
- Salt 생성 및 결합: Salt는 해시 계산에 사용되는 무작위 값으로, 같은 비밀번호라도 다른 Salt를 사용하면 다른 해시 값을 생성합니다. 이를 통해 동일한 비밀번호라도 서로 다른 해시 값을 만들어 해시 충돌 공격을 방지합니다.
- 비밀번호와 Salt 결합: 비밀번호와 Salt는 결합되어 단방향 해시 함수에 입력됩니다. 해시 함수는 이 입력을 통해 고정된 길이의 해시 값을 생성하는데, 이 과정에서 원본 데이터를 복원할 수 없습니다. 이 점이 단방향 해시의 핵심입니다.
- 반복적인 해시 계산 (Work Factor): 해시 함수는 비용 인자(work factor)를 사용하여 해시 계산을 반복적으로 수행합니다. 이로 인해 해시 계산이 매우 느려지며, 무차별 대입 공격이나 사전 공격을 어렵게 만듭니다. 이 방식은 공격자가 해시 값을 추측하기 위해 많은 시간을 소모하도록 만듭니다.
- 복원 불가능성: 단방향 해시는 복원 불가능하다는 특성이 있습니다. 즉, 해시 값만으로 원본 데이터를 역으로 추적할 수 없습니다. 해시 함수는 입력값을 고정된 길이의 출력값으로 변환하는데, 이 과정에서 정보가 손실되므로 원본 데이터를 알 수 없습니다.
- Salt가 포함된 암호화된 비밀번호:
BCrypt
에서 생성된 암호화된 비밀번호에는 Salt가 포함되어 있습니다. 하지만 이 Salt만으로는 원본 비밀번호를 추측할 수 없습니다. 공격자는 Salt와 해시 값을 이용해 무차별 대입 공격을 시도할 수 있지만, 단방향 해시의 특성상 이를 성공시키는 데에는 엄청난 시간과 자원이 소모됩니다.
비밀번호와 Salt 생성 과정
- 비밀번호 X 제공: 사용자가 비밀번호를 입력합니다.
- 무작위 Salt A 생성: 매번 다른 무작위 Salt를 생성합니다. 이 Salt는 비밀번호와 결합되어 해시 과정에 사용됩니다.
- Salt와 비밀번호 결합: Salt와 비밀번호를 결합하여 해시 함수에 넣습니다.
- 해시 값 생성: Salt와 비밀번호를 사용하여 반복적인 해시 계산을 수행하고, 최종적으로 암호화된 비밀번호 P를 생성합니다.
유출된 암호화된 비밀번호 (P)와 Salt (A) 사용
- P 유출:
P
는 암호화된 비밀번호이고, 이 안에는 이미 Salt A가 포함되어 있습니다. - 공격자의 접근: 공격자는
P
와A
를 알게 되지만, 단방향 해시이기 때문에P
와A
만으로 원래의 비밀번호X
를 역으로 추적하는 것은 불가능합니다.