티스토리 뷰

개요

  • 과거 전산실 근무 시절 인하우스 개발된 시스템을 유지보수하다가 놀란 것은 생각보다 많은 비율로 사용자의 비밀번호를 암호화하지 않은채 그대로 데이터베이스에 저장한다는 것이다. 비밀번호는 반드시 해쉬 알고리즘을 이용하여 암호화하여 저장해야 한다. 데이터베이스가 MySQL이라면 간단하게 MD5() 함수를 이용할 수 있을 것이다. 하지만 MD5 또는 SHA-1과 같은 단방향 해쉬 알고리즘은 해커의 공격으로부터 자유롭지 못하다. 현재까지 가장 안전한 해쉬 알고리즘은 BCrypt이다. 비밀번호 암호화에 특화되어 고안된 알고리즘이다. 본 글에서는 Java에서 BCrypt 해쉬 알고리즘을 이용하여 비밀번호를 보호하는 방법을 간단히 설명하고자 한다.

라이브러리 의존성 추가

  • /build.gradle 파일에 아래 내용을 추가한다.
dependencies {
    compile group: 'de.svenkubiak', name: 'jBCrypt', version: '0.4.1'
}
  • Java 진영의 BCrypt 해쉬 알고리즘 구현체인 jBCrypt 아티팩트를 추가하였다. 만약 Spring Boot 기반의 프로젝트라면 spring-boot-starter-security 아티팩트의 추가 만으로 BCrypt 해쉬 알고리즘을 사용할 수 있다.

BCrypt 사용 예

  • BCrypt의 사용 예는 아래와 같다.
// 사용자의 비밀번호
String password = "!@#$password1234";

// 위 비밀번호의 BCrypt 알고리즘 해쉬 생성
// passwordHashed 변수는 실제 데이터베이스에 저장될 60바이트의 문자열이 된다.
String passwordHashed = BCrypt.hashpw(password, BCrypt.gensalt());

// 위 문장은 아래와 같다. 숫자가 높아질수록 해쉬를 생성하고 검증하는 시간은 느려진다.
// 즉, 보안이 우수해진다. 하지만 그만큼 응답 시간이 느려지기 때문에 적절한 숫자를 선정해야 한다. 기본값은 10이다.
String passwordHashed = BCrypt.hashpw(password, BCrypt.gensalt(10));

// 생성된 해쉬를 원래 비밀번호로 검증한다. 맞을 경우 true를 반환한다.
// 주로 회원 로그인 로직에서 사용된다.
boolean isValidPassword = BCrypt.checkpw(password, passwordHashed);
  • Bcrypt는 알고리즘 차원에서 의도적으로 같은 문자열에 대해 매번 실행할 때마다 다른 해쉬 문자열을 생성한다. 만약, 매번 같은 해쉬를 생성한다면 해쉬를 해석하는데 성공한 해커는 같은 해시에 해당하는 다른 사용자의 계정도 탈취할 수 있어 위험하기 때문이다.

참고 글

댓글
  • 프로필사진 하위 두 번의 시도를 해보았는데요.
    두 개의 결과가 다른데 어떻게 스프링 시큐리티는
    등록/로그인의 패쓰워드가 같다고 판단을 할 수 있는건가요?

    2019.10.13 11:03
  • 프로필사진 BlogIcon 지단로보트 하위 // 같은 문자열에 대해 매번 다른 해쉬 값을 생성하는 것이 바로 BCrypt 알고리즘의 특징이자 보안상의 강점이라고 할 수 있습니다. 매번 같은 해쉬를 생성한다면 해당 해쉬를 해석하는데 성공한 해커는 다른 사용자의 계정도 탈취할 수 있어 위험합니다. 2019.10.16 20:40 신고
  • 프로필사진 지나는이 shashpwd() 할때마다 Hash값이 달라지는 이유는 salt를 원문에 추가해서 hash 하기 때문입니다.
    BCrypt.hashpw()의 결과 앞부분에 salt 값이 들어 있기 때문에 checkpw()에서는 passwordHashed의 salt를 사용해서 password를 Hash 할 수 있습니다.
    2019.11.12 17:01
댓글쓰기 폼