GitHub

https://github.com/Choidongjun0830

Spring

Spring Security 없이 비밀번호 암호화, 로그인 구현하기

gogi masidda 2024. 6. 30. 00:36
@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://wonchan.tistory.com/4

https://www.baeldung.com/java-password-hashing

 

728x90