Spring/security

[시큐리티] PasswordEncoder

라임온조 2023. 3. 15. 11:54

1. PasswordEncoder 계약

1) 정의

계약을 구현해 스프링 시큐리티에 사용자 암호를 검증하는 방법을 알려줄 수 있음

인증 프로세스에서 암호가 유효한지를 확인

2) 인터페이스 코드로 계약 구현

public interface PasswordEncoder {
	String encode(CharSequence rawPassword);
    boolean matches(CharSequence rawPassword, String encodedPassword);
    
    default boolean upgradeEncoding(String encodedPassword){
    	return false;
    }
}

encode 및 matches 메서드는 계약의 책임을 정의

encode

  • 주어진 문자열을 변환해 반환
  • 암호화 수행

matches

  • 인코딩된 문자열이 원시 암호와 일치하는지 나중에 확인
  • 지정된 암호를 인증 프로세스에서 알려진 자격 증명의 집합을 대상으로 비교
  • encode 메서드에서 반환된 문자열은 항상 같은 PasswordEncoder의 matches 메서드로 검증할 수 있어야 함

upgradeEncoding

  • true를 반환하도록 메서드를 재정의하면 인코딩된 암호를 보안 향상을 위해 다시 인코딩

2. PasswordEncoder 구현 옵션

1) NoOpPasswordEncoder

  • 암호를 인코딩하지 않고 일반 텍스트로 유지.
  • 이 구현은 예제 용도로만 적당하며 암호를 해시하지 않기 때문에 실제에서는 절대 쓰지 말아야 함

2) StandardPasswordEncoder

  • SHA-256을 이용해 암호를 해시
  • 해싱 프로세스에 적용할 비밀을 지정할 수 있음
  • 강도가 약한 해싱 알고리즘을 사용하는 구식이라 새 구현에는 쓰면 안 좋음

3) Pbkdf2PasswordEncoder

  • PBKDF2를 이용
  • 반복 횟수 인수만큼 HMAC를 수행하는 단순하고 느린 해싱 함수
  • 인코딩 프로세스에 이용되는 키의 값, 암호 인코딩의 반복 횟수, 해시의 크기를 매개 변수로 받음
  • 해시가 길수록 암호가 강력해지지만 성능이 안 좋아짐
  • 반복횟수를 늘리면 암호가 강력해지지만 애플리케이션이 소비하는 리소스가 증가해서 성능이 안 좋아짐

4) BCryptPasswordEncoder

  • bcrypt 강력 해싱 함수로 암호를 인코딩
  • 인코딩 프로세스에 이용되는 로그 라운드를 나타내는 강도 계수 지정 가능, 로그 라운드는 해싱 작업이 이용하는 반복 횟수에 영향을 줌
  • 인코딩에 이용되는 SecureRandom 인스턴스 변경 가능

5) SCryptPasswordEncoder

  • scrypt 해싱 함수로 암호를 인코딩
  • cpu비용, 메모리 비용, 병렬화 계수, 키 길이, 솔트 길이를 매개변수로 받을 수 있음

3. DelegatingPasswordEncoder

1) 개념

다양한 암호 인코더를 갖추고 특정 구성에 따라 선택하는 방식을 지원

2) 방법

  • 다양한 암호 인코더의 접두사와 인스턴스를 맵에 저장하고 들어오는 접두사에 맞는 인코더를 리턴해서 구현을 위임
  • 스프링 시큐리티는 편의를 위해 모든 표준 제공 PasswordEncoder의 구현에 대한 맵을 가진 DelegatingPasswordEncoder를 생성하는 방법을 제공함
  • PasswordEncoderFactories 클래스에는 bcrypt가 기본 인코더인 DelegatingPasswordEncoder의 구현을 반환하는 정적 메서드 createDelegatingPasswordEncoder가 있음
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

4. 키 생성기

1) 개념

특정한 종류의 키를 생성하는 객체로서 일반적으로 암호화나 해싱 알고리즘에 필요

2) 종류

BytesKeyGenerator

  • 팩터리 클래스 KeyGenerators로 직접 만들 수 있음
  • 8바이트 길이의 키를 생성
BytesKeyGenerator keyGenerator = KeyGenerators.secureRandom();
byte [] key = keyGenerator.generateKey();
int keyLength = keyGenerator.getKey();

// 같은 키 생성기를 호출하면 같은 키 값을 반환하는 구현
BytesKeyGenerator keyGenerator = KeyGenerators.shared(16);
byte [] key1 = keyGenerator.generateKey();
byte [] key2 = keyGenerator.generateKey();

StringKeyGenerator

  • 팩터리 클래스 KeyGenerators로 직접 만들 수 있음
  • 문자열 키를 얻을 수 있음
  • 생성된 키는 보통 해싱 또는 암호화 알고리즘의 솔트 값으로 이용됨
  • 8바이트 키를 생성하고 이를 16진수 문자열로 인코딩
StringKeyGenerator keyGenerator = KeyGenerators.string();
String salt = keyGenerator.generateKey();

5. 암호기

1) 개념

데이터를 암호화 및 복호화하는 객체

2) 종류

BytesEncryptor

바이트 배열로 입력 데이터를 받음

Encryptors.standard()

  • 256바이트 AES 암호화를 이용해 입력 암호화

Encryptors.stronger()

  • standard보다 더 강력한 바이트 암호기 인스턴스를 만듦
String salt = KeyGenerators.string().generateKey();
String password = "secret";
String valueToEncrypt = "HELLO";

BytesEncryptor e = Encryptors.standard(password, salt);
byte [] encrypted = e.encrypt(valueToEncrypt.getBytes());
byte [] decrypted = e.decrypt(encrypted);

// 암호기 종류
BytesEncryptor e = Encryptors.standard(password, salt);
BytesEncryptor e = Encryptors.stronger(password, salt);

TextEncryptor

데이터를 문자열로 관리

Encryptors.noOpText()

  • 값을 암호화하지 않는 더미 TextEncryptor 반환

Encryptors.text()

  • Encryptors.standard 메서드로 암호화 작업 관리
  • 암호화 프로세스에 임의의 초기화 벡터가 생성되기 때문에 같은 입력으로 encrypt 메서드를 반복 호출해도 다른 출력이 반환됨

Encryptors.delux()

  • 암호화 프로세스에 임의의 초기화 벡터가 생성되기 때문에 같은 입력으로 encrypt 메서드를 반복 호출해도 다른 출력이 반환됨
  • Encryptors.stronger 인스턴스 이용

Encryptors.queryableText()

  • 순차 암호화 작업에서 입력이 같으면 같은 출력을 생성하도록 보장
String valueToEncrypt = "HELLO";
TextEncryptor e = Encryptors.noOpText();
String encrypted = e.encrypt(valueToEncrypt);
String decrypted = e.decrypt(encrypted);

// 암호기 메서드 종류
TextEncryptor e = Encryptors.noOpText();
TextEncryptor e = Encryptors.text(password, salt); 
TextEncryptor e = Encryptors.delux(); 
TextEncryptor e = Encryptors.queryableTexxt();

'Spring > security' 카테고리의 다른 글

[시큐리티] SecurityContext  (0) 2023.03.16
[시큐리티] AuthenticationProvider  (0) 2023.03.15
[시큐리티] UserDetailsService  (0) 2023.03.13
[시큐리티] 구성 요소 재정의  (0) 2023.03.10
[시큐리티] 인증 방법  (0) 2023.03.10