@Component
public class PasswordEncoder {
public String encode(String loginId, String password) {
try {
KeySpec spec = new PBEKeySpec(password.toCharArray(), getSalt(loginId), 65536, 128);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = factory.generateSecret(spec).getEncoded();
return Base64.getEncoder().encodeToString(hash);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public boolean matches(String loginId, String rawPassword, String encodedPassword) {
String encodedRawPassword = encode(loginId, rawPassword);
return encodedRawPassword.equals(encodedPassword);
}
//비밀번호로 salt 값 생성하면 같은 비밀번호를 사용하는 유저끼리 같은 값을 가지게 됨. loginId는 모두 다르니까 loginId로 salt값 생성
private byte[] getSalt(String loginId) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest digest = MessageDigest.getInstance("SHA-512");
byte[] keyBytes = loginId.getBytes("UTF-8");
return digest.digest(keyBytes);
}
}
- encode
- PBEKeySpec은 비밀번호 기반 암호화를 위한 키 사양이다.
- password.toCharArray()는 비밀번호를 캐릭터 배열로 변환한다.
- getSalt(loginId): 로그인 ID를 기반으로 생성된 salt값을 가져오기
- salt는 암호화 해시 함수와 함께 사용되며 salt를 비밀번호에 추가함으로써 동일한 비밀번호를 가지더라도 다른 해시값을 갖게되게 한다.
- 65536은 해시 함수의 반복횟수로, 65536번 반복하는 것이다. 많을 수록 강력하다.
- 128은 생성할 키의 길이이다.
- SecretKeyFactory: 키 생성 알고리즘을 제공하는 클래스이다.
- PBKDF2WithHmacSHA1: PBKDF2 알고리즘과 HMAC-SHA1 해시 함수를 사용한다.
- byte[] hash = factory.generateSecret(spec).getEncoded();
- factory.generateSecret(spec): 주어진 키 사양(spec)을 사용하여 비밀번호 해시를 생성한다.
- .getEncoded(): 생성된 키를 바이트 배열로 인코딩한다.
- return Base64.getEncoder().encodeToString(hash);
- 생성된 해시를 인코딩하여 문자열로 변환한다.
- getSalt()
- 비밀번호로 salt값을 얻으면 같은 비밀번호를 쓰는 사람은 같은 salt값을 갖게 된다.
- 그래서 모두 다른 값을 가지는 loginId로 salt값을 구한다.
- matches
- 로그인을 위해 사용된다.
- 사용자가 입력한 비밀번호를 암호화하여 DB에 저장된 암호화된 비밀번호와 비교한다.
참고
https://www.baeldung.com/java-password-hashing
728x90
'Spring' 카테고리의 다른 글
[JPA 활용 2편] API 개발 고급 - 지연 로딩과 조회 성능 최적화 (0) | 2024.07.03 |
---|---|
[JPA 활용 2편] API 개발 기본 (0) | 2024.07.02 |
[JPA 활용 1편 복습] 회원, 상품 도메인 개발 (0) | 2024.06.28 |
[JPA 활용1 복습] 도메인 분석 설계 (0) | 2024.06.27 |
[JPA 기본편] 객체지향 쿼리 언어2 - 중급 문법 (0) | 2024.06.26 |