💡 개요
오늘은 회원의 비밀번호를 암호화하는 로직에 대해 정리해 보자.
🛠️ 비밀번호 암호화
보통 회원의 정보를 담고 있는 데이터베이스의 테이블에선 비밀번호를 단방향 암호화를 진행한 후, 저장된다.
그렇게 때문에 아무리 실제 DB에 접근할 수 있는 개발자라고 해도, 회원의 비밀번호는 알 수 없다.
이러한 이유 때문에 비밀번호를 찾을 때 사용중이던 비밀번호를 알려주는 것이 아니라 아예 비밀번호를 재설정하는 것 이다. DB도 찐 비밀번호를 모르기 때문!
그런데 회원이 로그인을 위해 입력하는 비밀번호는 평문아닌가?
회원이 입력한 평문 형태의 비밀번호와 DB에 저장된 암호화된 비밀번호를 어떻게 비교하는 거지?
⚙️ 단방향 해시
Spring에서 사용하는 대표적인 단방향 해시 기술은 BCryptPasswordEncoder가 있다.
BCryptPasswordEncoder은 Spring Security에서 제공해주는 암호화 기술이다.
비밀번호를 암호화할 땐 대부분 단방향 해시를 사용하기 때문에 복호화를 진행할 수 없다.
하지만 BCryptPasswordEncoder을 사용하면 평문 비밀번호와 암호화된 비밀번호를 비교할 수 있다.
그 이유는 BCryptPasswordEncoder은 내부적으로 암호화된 비밀번호에서 salt 값을 추출할 수 있기 때문이다.
salt란, 평문 비밀번호에 추가하는 임의의 문자열로, 해시값을 랜덤하게 만들기 위해 사용되는 기술이다.
이 salt 덕분에 해커가 사용하는 비밀번호 사전인 Rainbow Table을 무력화할 수 있는 것이다.
만약 우리가 salt을 사용하지 않는다면 해커 입장에선 가능한 많은 비밀번호에 해당하는 해시값을 비교함으로서, 평문 비밀번호를 예측할 수 있다.
하지만 salt가 추가된다면 Rainbow Table에 존재하는 모든 비밀번호 - 해시값이 의미없는 데이터로 만들 수 있다.
다음은 BCryptPasswordEncoder을 적용한 비밀번호이다.
$2a$10$x0wV2Jv9mHoFFP0yMv2NBuUVwkkrhTZXwo4aPZ4B9ZDclt3lRrhFi
총 세 개의 $.. 으로 이루어져 있다.
- $2a : 사용된 Bcrypt의 알고리즘 버전
- $10 : cost factor로 연산 반복 횟수를 제어하기 위해 존재한다. 다시 말해, 원래 해시 함수가 1번이면 끝날 것을 1024번 반복해서 해싱하는 것이다. 이를 통해 해시값을 만드는 데 더 느리게 만든다. (해커의 공격 속도를 늦추기 위함임)
- $x0w… : 평문 비밀번호와 salt이 합쳐진 해시값이다.
⚙️ BCryptPasswordEncoder 내부 로직
🤔 평문 비밀번호 암호화
보다시피 getSalt() 메서드를 통해 salt값을 생성한 후, BCrypt.hashpw() 메서드에 평문 비밀번호와 salt을 함께 넣는다.
🤔 평문 비밀번호와 암호화 비밀번호 비교
이제 위에서도 언급했듯이 우리는 평문 비밀번호와 salt값만 있으면 해시값을 만들 수 있는 것을 알게되었다.
위 코드들은 BCrypt 내부의 평문 비밀번호와 암호화된 비밀번호를 비교할 때 사용되는 메서드들이다.
코드를 자세히 보면 계속해서 salt라는 변수가 나오는 데, 이것이 우리가 암호화에 사용한 salt에 해당한다.
여기서 찾은 salt값을 사용해 평문 비밀번호를 한번 더 해시값으로 만든 후, DB에 저장된 암호화된 비밀번호와 비교하는 것이다.
'개발 일기' 카테고리의 다른 글
[개발 일기] 2025.05.07 - WebRTC 구현 방식 (0) | 2025.05.07 |
---|---|
[개발 일기] 2025.05.06 - WebRTC 연결 (0) | 2025.05.06 |
[개발 일기] 2025.05.04 - JWT 페이로드 종류 (0) | 2025.05.04 |
[개발 일기] 2025.05.03 - JWT 말고 인증에 사용할 만한 기술 (0) | 2025.05.03 |
[개발 일기] 2025.05.02 -GraphQL, gRPC (2) | 2025.05.02 |