12(1) 시큐리티(2) 비밀번호 암호화

Alex·2024년 6월 22일
0

이슈 트래커

목록 보기
20/21

디비에는 보통 비밀번호를 암호화한 책로 넣는다고 한다. 그렇다면, 유저가 입력한 비밀번호가 db에 저장된 비밀번호와 일치하는지 확인하는 단계가 필요하다.

PasswordEncoder를 구현하면 스프링 시큐리티에게 어떻게 비밀번호를 검증할지 알려줄 수 있다.

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

인터페이스는 위처럼 생겼다. 비밀번호를 encode하고, match하는 메서드가 있다.

스프링 시큐리티는 위와같은 구현체들을 이미 제공하고 있다. 여기서 필요한 것을 사용하면 된다.

NoOpPasswordEncoder는 패스워드를 암호화하지 않는다.

PasswordEncoder p = NoOpPasswordEncoder.getInstance();

//싱글톤이다.

StandardPasswordEncoder은 SHA-256를 사용해서 해시 암호를 만든다. 다만, 이 구현체는 depreate됐고 책에서는 사용을 권하지 않고 있다.

PasswordEncoder p = new StandardPasswordEncoder();
PasswordEncoder p = new StandardPasswordEncoder("secret");

Pbkdf2PasswordEncoder는 PBKDF2를 사용해서 암호화를 한다.

PasswordEncoder p = 
 new Pbkdf2PasswordEncoder("secret", 16, 310000, Pbkdf2PasswordEncoder. 
SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA256);

상당히 쉽고, slow_hasing 기능을 제공한다. 이는 매개변수에 명시된 만큼 HMAC를 반복한다고 한다.(각각의 매개변수는 기능이 있는데 필요할 때 공부하도록 하자)

BCryptPasswordEncoder는 bcrypt strong hashing function사용해서 암호화를 한다.

PasswordEncoder p = new BCryptPasswordEncoder();
PasswordEncoder p = new BCryptPasswordEncoder(4);
SecureRandom s = SecureRandom.getInstanceStrong();
PasswordEncoder p = new BCryptPasswordEncoder(4, s);

책에서는 이 전략들을 다양하게 사용하는 방식이 나오는데
사실 지금 내게 필요한 내용이 아니라서 일단 스킵한다. 나중에 필요할 때 찾아보자.

Spring Security Crypto module(SSCM)

스프링 시큐리티는 암호화를 위한 편리한 모듈을 제공한다.

1)Key generators 해싱과 암호화를 위한 키를 생성
2)Encryptors 암호화, 복호화에 사용용

Key generator

암호화에 사용하느 키를 만드는 기능이다. 다른 의존성을 추가하는 대신 스프링 시큐리티가 제공하는 것을 쓰면 된다.

BytesKeyGenerator and StringKeyGenerator.

Key generator의 두가지 인터페이스다.
키를 String으로 얻으려면 StringKeyGenerator를 쓸 수 있다.

public interface StringKeyGenerator {
 String generateKey();
}

StringKeyGenerator keyGenerator = KeyGenerators.string();
String salt = keyGenerator.generateKey();

BytesKeyGenerator은 byte[]로 키를 제공한다.

BytesKeyGenerator keyGenerator = KeyGenerators.secureRandom();
byte [] key = keyGenerator.generateKey();
int keyLength = keyGenerator.getKeyLength();

Encryptors

인코더로는 BytesEncryptor and TextEncryptor가 있다.
TextEncryptor는 데이터를 String으로 관린한다.

public interface TextEncryptor {
 String encrypt(String text);
 String decrypt(String encryptedText);
}

BytesEncryptors는 좀더 범용적이다.

public interface BytesEncryptor {
 byte[] encrypt(byte[] byteArray);
 byte[] decrypt(byte[] encryptedByteArray);
}
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); 

the standard byte encryptors는 256-byte AES encryption을 사용한다고 한다.

더 강하게 암호화하려면 Encryptors.stronger() method를 쓸 수 있다.

BytesEncryptor e = Encryptors.stronger(password, salt);
String valueToEncrypt = "HELLO";
TextEncryptor e = Encryptors.noOpText();
String encrypted = e.encrypt(valueToEncrypt);
String password = "secret";
String valueToEncrypt = "HELLO";
TextEncryptor e = Encryptors.text(password, salt); 
String encrypted = e.encrypt(valueToEncrypt);
String decrypted = e.decrypt(encrypted);

우선 프로젝트를 위해서

@Configuration
public class SpringSecurityConfig {

    private final String salt = KeyGenerators.string().generateKey();

    @Value("${spring.securiy.password}")
    private String password;


    @Bean
    public BytesEncryptor bytesEncryptor(){
        return Encryptors.stronger(password, salt);

    }
}

이렇게 구현을 해놨다.
stronger는 더 강력한 암호화 방식을 쓴다고 한다.
(나중에 더 공부해보자)

profile
답을 찾기 위해서 노력하는 사람

0개의 댓글