들어가면서
도서 : 스프링 시큐리티 인 액션
을 보고 내용을 정리한 글입니다. 자세한 내용은 책을 보는 것을 추천합니다.
이번 내용은 스프링 시큐리티의 암호화를 담당하는 모듈을 다루었다.
PasswordEncoder 인터페이스
비밀번호는 민감한 정보이다. 외부에 노출이 된다면 중요한 정보를 탈취당할 수 있기 때문에 단단히 챙겨하는 정보이다. 이런 민감한 정보를 안전하게 보관하기 위해서 암호화를 하는데 스프링 시큐리티에서는 이런 암호화를 처리하는 역할을 인터페이스로 정의하고 있다. 바로 PasswordEncoder
이다.
스프링 시큐리티를 적용하고 있다면 이 구현체 빈으로 등록하면 정의된 역할에 맞게 암호화를 적용할 수 있다.
PasswordEncoder 구현체
BCryptPasswordEncoder
, Argon2PasswordEncoder
, DelegatingPasswordEncoder
, Pbkdf2PasswordEncoder
, SCryptPasswordEncoder
와 같은 구현체가 있다. 제공하는 구현체는 모두 비밀번호와 같이 민감한 정보에 사용하는 느린 해시를 사용하는 알고리즘을 구현한 구현체들로 서비스에 맞는 알고리즘을 선택해서 사용하면 된다. 각 알고리즘에 대해서는 너무 방대해서 좀 더 공부를 해봐야 할 듯...
사용 방법은 다음 예제 처럼 선언을 해서 사용을 한다. 구현된 알고리즘에 따른 인자들을 제공하고 기본 값으로도 사용이 가능하다.
BCryptPasswordEncoder bcrypt = new BCryptPasswordEncoder();
new BCryptPasswordEncoder(4); // 4 ~ 31 까지 길이 지정
Argon2PasswordEncoder argon2 = new Argon2PasswordEncoder();
new Argon2PasswordEncoder(16, 32, 1, 1 << 12, 3);
Pbkdf2PasswordEncoder pbkdf2 = new Pbkdf2PasswordEncoder();
new Pbkdf2PasswordEncoder("secret", 4);
SCryptPasswordEncoder scrypt = new SCryptPasswordEncoder();
new SCryptPasswordEncoder(16384, 8, 1, 32, 64);
DelegatingPasswordEncoder
특정 상황에 따라서 다른 알고리즘을 사용하고 싶을 때, 사용하는 구현체이다. 생성시 패스워드 구현체를 맵으로 저장한 매핑 정보를 넘겨서 만들 수 있다.
책에서는 디폴트 구현체를 생성자를 통해서 지정할 수 있다고 하는데 테스트를 하니까 아닌 것 같다. 디폴트 구현체를 지정하기 위해서는 setDefaultPasswordEncoder()
를 통해서 지정을 해주어야 한다.
var map = new HashMap<String, PasswordEncoder>();
map.put("bcrypt", new BCryptPasswordEncoder());
map.put("no", noOpPasswordEncoder);
var encoder = new DelegatingPasswordEncoder("bcrypt", map);
encoder.setDefaultPasswordEncoderForMatches(map.get("no"));
Salt?
공개키 기반 알고리즘은 암호화와 복호화에 필요한 키가 같기 때문에 역해싱 과정을 통해서 데이터를 추출할 수 있다. 이런 공격을 레인보우 테이블이라고 하는데 이 과정은 리소스가 많이 드는 작업이지만 한번 공개키를 공격자가 알아내면 서비스를 이용하는 모든 고개의 데이터 정보를 공격자가 쉽게 볼 수 있어서 불안하다.
이런 한계를 극복하기 위한 해결책으로 Salt가 있다.
Salt는 데이터의 임의의 데이터를 가미한 이후에 해싱하는 기법을 사용할 때, 임의의 데이터를 salt라고 한다.
PasswordEncoder 구현체에서 Salt의 길이를 지정하면 암호화를 할 때, 지정한 길이의 Salt를 추가한 암호화 기법을 적용해준다.
더욱 더 안전하게 암호화를 사용할 수 있도록 편하게 사용할 수 있는 좋은 기능!!
key stretching
키 스트레칭은 무차별 대입 공격(브루드 포트 공격)에 대비하여 키를 대입하는데 필요한 자원의 총량을 늘려서 공격자의 자원을 낭비시키기 위한 기법이다.
구현 방법으로는 두가지가 있다.
- 반복적 해싱
해시를 만들 때, 해시 함수를 여러번 반복적으로 실행하여 계산량을 늘리는 방법!
- 메모리 요구 사항이 큰 암호화 해시 기능 사용
메모리 바인딩된 공격자의 공격을 막는데 효과적!
Reference
도서 : Spring security in action
키 스트레칭 : 여기
'spring > security' 카테고리의 다른 글
Spring Security Test 작성하기 (0) | 2023.11.20 |
---|---|
[Spring security] SecurityContext, 접근 제한, 권한 제한에 대해서 (0) | 2023.11.07 |
[Spring security] Redis를 이용한 글로벌 세션 스토리지 (0) | 2023.02.20 |
[Spring] UsernamePasswordAuthenticationFilter 를 통한 폼 로그인 하기 (0) | 2023.02.18 |
Oath2 로그인 구현 - 구글 (0) | 2023.02.13 |