Netplix 구독형 멤버십 프로젝트로 배우는 SpringSecurity
[Ch 4. PasswordEncoder] - 01. PasswordEncoder 살펴보기
강의를 바탕으로 실습 내용을 정리하였습니다.
목차
1. 키 생성기
키 생성기는 특정한 종류의 키를 생성하는 객체로 일반적으로 암호화나 해싱 알고리즘에 필요함
스프링 시큐리티에서 제공하는 키 생성기 인터페이스:
- BytesKeyGenerator
- StringKeyGenerator
StringKeyGenerator
문자열 키 생성기를 이용해 문자열 키를 얻을 수 있음
- 이 키를 기반으로 해싱 또는 알고리즘의 솔트(salt) 값으로 이용할 수 있음
StringKeyGenerator 는 generateKey() 메소드를 제공함
StringKeyGenerator 와 솔팅
StringKeyGenerator 인스턴스를 얻고 솔트 값을 가져오는 예시
- HexEncodingStringKeyGenerator: 8바이트 키를 생성하고 이를 16진수 문자열로 인코딩함
StringKeyGenerator generator = KeyGenerators.string();
String salt = generator.generateKey();
BytesKeyGenerator
byte[] 키를 반환하며 키 값의 길이를 반환하는 기능을 제공함
- BytesKeyGenerator 는 generateKey() 메소드 뿐만 아니라 getKeyLength() 메소드를 제공함
- generateKey() 가 호출될 때마다 매번 다른 고유한(unique) 키 값이 생성됨
BytesKeyGenerator 사용하기
BytesKeyGenerator generator = KeyGenerators.secureRandom();
byte[] key = generator.generateKey();
int length = generator.getKeyLength();
8바이트 길이의 키를 생성함
- 다른 길이의 키를 생성하려면
KeyGenerators.secureRandom()
에 파라미터로 원하는 값을 전달하면 됨 KeyGenerators.secureRandom(16);
: 16바이트 길이의 키가 생성됨
만약 매번 같은 키 값을 반환하는 로직이 필요한 경우에는 KeyGenerators.shared()
를 활용할 수 있음
BytesKeyGenerator generator = KeyGenerators.shared(16);
byte[] key1 = generator.generateKey();
byte[] key2 = generator.generateKey();
// key1과 key2는 값을 값을 가짐
테스트 코드
- shared 로 생성된 key1 과 key2 가 동일한지 검증
package fast.campus.fcss01.generator;
import org.junit.jupiter.api.Test;
import org.springframework.security.crypto.keygen.BytesKeyGenerator;
import org.springframework.security.crypto.keygen.KeyGenerators;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MyGeneratorTest {
/** BytesKeyGenerator 사용하기 **/
@Test
public void test() {
// given
BytesKeyGenerator generator = KeyGenerators.shared(16);
// when
byte[] key1 = generator.generateKey();
byte[] key2 = generator.generateKey();
// then
assertEquals(key1, key2);
}
}
2. 암호기
암호기는 암호화 알고리즘을 구현하는 객체
암호화와 복호화는 보안을 위해 꼭 필요한 기능으로 애플리케이션에서 암호기를 많이 사용함
암호화는 서버 간 통신에서 데이터를 전송하거나 저장을 할 때 사용되는 경우가 많음
스프링 시큐리티에서는 아래 두 유형의 암호기가 정의되어 있음
- BytesEncryptor
- TextEncryptor
역할은 비슷하지만 다른 데이터 형식을 처리함에 있어 다름
⇒ BytesEncryptor는 Byte값을 핸들링, TextEncryptor은 String 값을 핸들링
TextEncryptor
TextEncryptor 는 두 개의 메소드를 제공함
- 암호화를 나타내는 encrypt() 와 복호화를 나타내는 decrypt() 가 있음
BytesEncryptor
TextEncryptor 와 비슷하게 encrypt() 메소드와 decrypt() 메소드를 제공함
- 인풋과 아웃풋에서 차이가 있음
Encryptors 팩토리 클래스
BytesEncryptors 암호기 사용
KeyGenerators.string() 기반으로 salt 생성
secret 과 salt 기반으로 BytesEncryptor 정의
- 더 강력한 암호기를 만들기 위해서는 standard 대신 stronger 를 활용하면 됨
encrypt 하고자 하는 값은 “HELLO”
decrypt 한 결과값과 encrypt 와 동일한지 확인
/** BytesEncryptors 암호기 사용 **/
@Test
public void test2() {
String salt = KeyGenerators.string().generateKey();
String password = "secret";
String valueToEncrypt = "HELLO";
BytesEncryptor bytesEncryptor = Encryptors.standard(password, salt);
byte[] encrypted = bytesEncryptor.encrypt(valueToEncrypt.getBytes());
byte[] decrypted = bytesEncryptor.decrypt(encrypted);
assertArrayEquals(valueToEncrypt.getBytes(), decrypted);
}
TextEncryptors 암호기 사용
TextEncryptors 는 두 가지 주요 형식이 존재함
- Encryptors.text(), Encryptors.delux()
값을 암호화하지 않는 더미 TextEncryptor 도 존재함
- Encryptors.noOpText()
/** TextEncryptors 암호기 사용 **/
@Test
public void test3() {
String valueToEncrypt = "HELLO";
TextEncryptor textEncryptor = Encryptors.noOpText();
String encrypted = textEncryptor.encrypt(valueToEncrypt);
String decrypted = textEncryptor.decrypt(encrypted);
assertEquals(valueToEncrypt, decrypted);
}
암호화되지 않은 평문 그대로임을 확인할 수 있음
Encryptors.text() 암호기는 Encryptors.standard() 메소드를 암호화 작업에 사용함
Encryptors.delux() 암호기는 Encryptors.stronger() 메소드를 암호화 작업에 사용함
같은 입력으로 encrypt() 메소드를 반복 호출해도 다른 출력이 반환됨
- 매번 새로운 값이 나올 수 있도록 초기화를 시키기 때문
값이 변경되는 것 확인
/** TextEncryptors의 encrypt()에서 매번 새로운 값이 나옴 **/
@Test
public void test4() {
String salt = KeyGenerators.string().generateKey();
String password = "secret";
String valueToEncrypt = "HELLO";
TextEncryptor textEncryptor = Encryptors.delux(password, salt);
String encrypted = textEncryptor.encrypt(valueToEncrypt);
String decrypted = textEncryptor.decrypt(encrypted);
assertEquals(valueToEncrypt, decrypted);
}
encrypted 값이 호출할 때마다 다른 값이 반환되는 것을 확인할 수 있음
'Course > Spring Security' 카테고리의 다른 글
[netplix-security-a] AuthenticationProvider 구현 (0) | 2024.10.03 |
---|---|
[netplix-security-a] AOP를 활용하여 비밀번호 암호화하기 (1) | 2024.10.03 |
[netplix-security-a] UserDetailsService 와 UserDetailsManager 구현 (1) | 2024.09.29 |
[netplix-security-a] UserDetails와 영속성 엔티티의 분리된 구현 (0) | 2024.09.29 |
[netplix-security-a] 기본 구성 재정의 (0) | 2024.09.29 |
댓글