Git :)

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ch04 : 암호화 방식
    IT 서적/Spring Security In Action 2023. 12. 30. 23:55
    728x90

    # PasswordEncoder 활용

    • 스프링 시큐리티에서는 기본적으로 PasswordEncoder라는 인터페이스를 제공해준다.
    • PasswordEncoder는 아래와 같다.
    public interface PasswordEncoder {
    
    	String encode(CharSequence rawPassword);
    	boolean matches(CharSequence rawPassword, String encodedPassword);
    
    	default boolean upgradeEncoding(String encodedPassword) {
    		return false;
    	}
    
    }

     

    • encode 메소드는 주어진 문자열을 변환해 반환하는 역할을 수행한다. 즉, 주어진 암호의 해시를 제공하거나 암호화를 수행하는 일을 한다.
    • 인코딩된 문자열이 원시 암호와 일치하는지 나중에 확인하는 데는 matches 메서드를 이용할 수 있다.
    • 세 번째 메소드인 upgradeEncoding은 기본값 false를 반환한다. true를 반환하도록 메소드 재정의하면 인코딩된 암호를 보안 향상을 위해 다시 인코딩한다. (모호하기 때문에 개인적으로 좋아하진 않는다.)

     

    # Password 인코더의 다양한 사용법

    • NoOpPasswordEncoder - 암호를 인코딩하지 않고 일반 텍스트로 사용하는 설정
    • StandardPasswordEncoder - SHA-256을 이용해 암호를 해시한다. (강도가 약한 알고리즘이기 때문에 레거시 시스템에서 사용한다.)
    • Pbkdf2PasswordEncoder - PBKDF2를 이용한다. (반복 횟수 인수만큼 HMAC를 수행하는 아주 단순하고 느린 해 함수이다.)
    • BCryptPasswordEncoder - bcrypt 강력 해싱 함수로 암호를 인코딩한다.
    • SCryptPasswordEncoder - scrypt 해싱 함수로 암호를 인코딩한다.

    # Password 인코더를 다양하게 활용하는 경우

    • PasswordEncoder의 Configuration을 아래와 같이 설정하면 된다.
    @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()) ;
            
            return new DelegatingPasswordEncoder("bcrypt", encoders) ;
        }
    }

     

    # Spring Security의 키 생성기 활용하기

    • 스프링 시큐리티는 아래와 같이 두 가지의 기능을 제공해준다.
      • 키 생성기 : 해싱 및 암호화 알고리즘을 위한 키를 생성하는 객체
      • 암호기 : 데이터를 암호화 및 복호화하는 객체
    • 키 생성기는 Byte와 String으로 나눌 수 있고 생성 방식은 아래와 같다.
    /** 단건인 경우 */
    BytesKeyGenerator keyGenerator = KeyGenerators.secureRandom() ;
    byte[] key = keyGenerator.generateKey() ;
    int keyLength = keyGenerator.getKeyLength() ;
    
    /** 공유하는 경우 */
    BytesKeyGenerator keyGenerator = KeyGenerators.shared(16) ;
    byte[] key1 = keyGenerator.generateKey() ;
    byte[] key2 = keyGenerator.generateKey() ;
    //key1과 key2의 key값은 일치한다.
    
    StringKeyGenerator keyGenerator = KeyGenerator.string() ;
    String salt = keyGenerator.generateKey() ;
    • 암호화 방식은 TextEncryptor와 BytesEncryptor를 활용할 수 있다.

     

    # BytesEncryptor 방식

    • Bytes 암호화 방식은 표준방식과 더 강력한 Stronger 방식이 있다. (두 방식 모두 AES 256 방식을 활용)
    • 표준방식은 GCM(갈루아/카운터 모드)를 사용하고 Stronger는 CBC(암호 블록 체인)을 활용한다
    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.stronger(password, salt) ;
    */

     

    # TextEncryptor 방식

    • TextEncryptor는 Encryptors.text(), Encryptors .delux(), Encryptors.queryableText()와 같이 세 가지 방식이 있다.
    • text와 delux의 경우 같은 입력으로 encrypt() 메서드를 반복 호출해도 다른 출력이 되지만 queryableText의 경우에는 같은 값이 출력된다.
    728x90