Home 암호 처리
Post
Cancel

암호 처리

PasswordEncoder 계약의 이해

일반적으로 시스템은 암호를 일반 텍스트로 관리하지 않고 공격자가 암호를 읽고 훔치기 어렵게 하기 위한 일종의 변환 과정을 거친다.

시큐리티에서는 이 책임을 위해 정의된 별도의 계약이 PasswordEncoder이다.

PasswordEncoder

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* PasswordEncoder 인터페이스 */
public interface PasswordEncoder {

  // 메서드는 주어진 문자열을 변환해 반환하는 메서드
  String encode(CharSequence rawPassword);

  // 지정된 암호를 인증 프로세스에서 알려진 자격 증명의 집합을 대상으로 비교
  boolean matches(CharSequence rawPassword, String encodedPassword);

  // 기본값은 false 로 true를 반환하도록 재정의하면 인코딩된 암호를 보안 향상을 위해 다시 인코딩
  default boolean upgradeEncoding(String encodedPassword) {
    return false;
  }
}

PasswordEncoder 계약의 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
/* PasswordEncoder의 가장 단순한 구현 */
public class PlainTextPasswordEncoder implements PasswordEncoder {

  @Override
  public String encode(CharSequence rawPassword) {
    return rawPassword.toString();
  }

  @Override
  public boolean matches(CharSequence rawPassword, String encodedPassword) {
    return rawPassword.equals(encodedPassword);
  }
}

PasswordEncoder의 제공된 구현

  • NoOpPasswordEncoder : 암호를 인코딩하지 않고 일반 테긋트로 유지
  • StandardPasswordEncoder : SHA-256을 이용해 암호를 해시한다. 이 구현은 이제 구식이며 잘 사용하지 않는다.
  • Pbkdf2PasswordEncoder : PBKDF2를 이용
  • BCryptPasswordEncoder : bcrypt 강력 해싱 함수로 암호를 인코딩
  • SCryptPasswordEncoder : scrypt 해싱 함수로 암호를 인코딩

StandardPasswordEncoder

1
2
// StandardPasswordEncoder(비밀의 값)
PasswrordEncoder p = new StandardPasswordEncoder("secret");

StandardPasswordEncoder은 SHA-456 해싱 방식을 사용한다. 추가적으로 비밀의 값을 설정으로 해싱 프로세스에 적용할 비밀을 지정할 수 있다.

비밀의 값은 생성자의 매개 변수로 전달하며 인수가 없는 생성자를 호출하면 빈 문자열이 키 값으로 이용된다.

Pbkdf2PasswordEncoder

1
2
// Pbkdf2PasswordEncoder(키의 값, 암호 인코딩의 반복횟수, 해시의 크기)
PasswrordEncoder p = new Pbkdf2PasswordEncoder("secret", 185000, 256);

Pbkdf2PasswordEncoder는 PBKDF2 방식으로 암호를 해싱한다.

PBKDF2는 반복 횟수 인수만큼 HMAC를 수행하는 아주 단순하고 느린 해싱 함수다. 반복횟수, 해시의 크기를 크게하면 암호는 강력해지지만 속도가 느려진다.

BCryptPasswordEncoder

1
2
3
// BCryptPasswordEncoder(강도 계수, SecureRandom);
SecureRandom s = SecureRandom.getInstanceStrong();
PasswordEncdoer p = new BCryptPasswordEncoder(4, s);

BCryptPasswordEncoder는 bcrypt 강력 해싱 함수로 암호를 인코딩한다. 또한 인코딩에 이용되는 SecureRandom 인스턴스를 변경할 수도 있다.

SCryptPasswordEncoder

1
2
// SCryptPasswordEncoder(CPU비용, 메모리 비용, 병렬화 개수, 키 길이, 솔트 길이);
PasswordEncoder p = new SCryptPasswordEncoder(16384, 8, 1, 32, 64);

SCryptPasswordEncoder는 scrypt 해싱 함수로 암호를 인코딩한다.

DelegatingPasswordEncoder

일부 애플리에키션에서는 다양한 암호 인코더를 갖추고 특정 구성에 따라 선택하는 방식이 유용할 수 있다.

DelegatingPasswordEncoder는 PasswordEncoder 인터페이스의 한 구현이며 자체 인코딩 알고리즘을 구현하는 대신 같은 계약의 다른 구현 인스턴스에 작업을 위임한다. 해시는 해당 해시를 의미하는 알고리즘의 이름을 나타내는 접두사로 시작한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* DelegatingPasswordEncoder 인스턴스 예시 */
@Configuration
public class ProjectConfig {
  // 생략된 코드

  @Bean
  public PasswordEncoder passwordEncoder() {
    Map<String, PasswordEncoder> encoders = new HashMap<>;
    encoders.put("noop", NoOpPasswordEncoder.getInstance());
    encoders.put("bcrypt", new BCryptPasswordEncoder());
    encoders.put("scrypt", new SCryptPasswordEncoder());
    // 기본 encoder를 bcrypt
    return new DelegatingPasswordEncoder("bcrypt", encoders);
  }
}

스프링 시큐리티 암호화 모듈에 관한 추가 정보

추후 필요시 다룸..

This post is licensed under CC BY 4.0 by the author.