스프링 일지

[Spring] 스프링 시큐리티, BCryptPasswordEncoder, 암호화 개념 정리

뉴이네 2023. 12. 13. 13:36

📌 스프링 시큐리티는

 

자바 기반의 애플리케이션에서 사용할 수 있는 강력한 인증 및 인가 솔루션입니다. 이는 스프링 프레임워크에 통합된 보안 프레임워크로서, 웹 보안, 인증, 권한 부여, 공격으로부터의 보호 등 다양한 보안 기능을 제공합니다.

인증(Authentication)과 인가(Authorization)는 보안의 두 가지 주요 측면입니다. 이 두 용어는 다음과 같은 차이점을 가지고 있습니다.

 

인증은 사용자의 신원을 확인하는 과정입니다. 이는 보통 사용자 이름과 비밀번호를 사용하여 수행되며, 사용자가 그들이 주장하는 사람인지 확인합니다.

반면에, 인가는 이미 인증된 사용자가 시스템의 특정 자원에 액세스하도록 허용하는 과정입니다. 이는 사용자의 권한 또는 역할을 기반으로 수행되며, 사용자가 수행할 수 있는 작업을 결정합니다.

 

✅ 스프링 시큐리티 관련 필터

스프링 시큐리티는 필터 체인을 사용하여 보안을 처리합니다. 이 필터 체인은 여러 보안 필터로 구성되어 있으며, 각 필터는 특정 보안 관련 작업을 수행합니다. 이 외에도 여러 가지 필터가 있으며, 개발자는 자신의 필요에 따라 필터 체인을 커스텀 할 수 있습니다.

  1. SecurityContextPersistenceFilter
    : 이 필터는 SecurityContext를 HTTP 세션에 저장하고 복원합니다. 이렇게 하면 사용자가 인증 된 후에도 보안 컨텍스트를 계속 사용할 수 있습니다.
  2. LogoutFilter
    : 이 필터는 사용자가 로그아웃하려고 할 때 사용자의 세션을 무효화하고 쿠키를 삭제하는 등 로그아웃 관련 처리를 수행합니다.
  3. UsernamePasswordAuthenticationFilter
    : 이 필터는 사용자 이름과 비밀번호 기반의 인증을 처리합니다.
  4. DefaultLoginPageGeneratingFilter
    : 이 필터는 사용자가 인증을 위해 로그인 페이지를 요청하면 자동으로 로그인 페이지를 생성합니다.
  5. BasicAuthenticationFilter
    : 이 필터는 HTTP Basic 인증을 처리합니다. 클라이언트가 보낸 사용자 이름과 비밀번호를 해독하고, 이를 사용하여 사용자를 인증합니다. 인증이 성공하면, 해당 사용자의 보안 컨텍스트가 설정되고, 이후 필터 체인이 계속됩니다. 만약 인증에 실패하면, 이 필터는 인증 실패 핸들러를 호출하고, 필터 체인 실행을 중지합니다.
  6. RememberMeAuthenticationFilter
    : 이 필터는 사용자가 'Remember Me' 옵션을 선택한 경우, 사용자를 인증하는 역할을 합니다. 이 필터는 사용자가 로그인 세션을 유지하도록 도와줍니다.
  7. SecurityContextHolderAwareRequestFilter
    : 이 필터는 현재의 SecurityContext를 요청에 연결합니다. 이를 통해 개발자는 요청 내에서 현재의 인증 정보에 접근할 수 있습니다.
  8. AnonymousAuthenticationFilter
    : 이 필터는 현재 사용자가 인증되지 않았을 경우, 사용자를 익명으로 인식하도록 설정합니다. 이렇게 함으로써 개발자는 익명 사용자와 인증된 사용자에 대해 다르게 처리할 수 있습니다.
  9. SessionManagementFilter
    : 이 필터는 세션 관리와 관련된 여러 작업을 수행합니다. 예를 들어, 세션이 만료된 경우나 세션이 동일한 사용자에 의해 동시에 열려 있는 경우 등에 대한 처리를 합니다. 또한, 세션이 유효하지 않을 경우에는 적절한 예외를 발생시키거나, 사용자를 로그인 페이지로 리다이렉트 할 수 있습니다.
  10. ExceptionTranslationFilter
    : 이 필터는 보안 관련 예외를 처리하고 적절한 응답을 생성합니다.
  11. FilterSecurityInterceptor
    : 이 필터는 보안 결정을 내리는 역할을 합니다. 즉, 특정 요청에 대해 접근 제어 결정을 내리고, 접근이 거부되었을 때 적절한 예외를 발생시킵니다.

 


 

📌 암호화, 복호화

 

암호화 : blog → daksfla@#$FDS%^df

복호화 : daksfla@#$FDS%^df → blog

 

암호화는 정보를 보호하기 위해 데이터를 변조하는 과정입니다. 이 과정을 통해 원본 데이터는 알아볼 수 없는 형태로 변환되며, 이를 "암호문"이라고 합니다. 암호화는 주로 비밀번호, 신용카드 정보, 개인 식별 정보 등 민감한 데이터를 보호하는 데 사용됩니다.

반면, 복호화는 암호화된 데이터를 원래의 형태로 되돌리는 과정입니다. 복호화는 암호화와 반대의 과정을 수행하여 암호문을 다시 원본 데이터, 즉 "평문"으로 변환합니다. 복호화는 암호화된 데이터를 안전하게 전송한 후, 수신자가 그 데이터를 이해하고 사용할 수 있도록 하는 데 필요합니다.

스프링 시큐리티는 암호화와 복호화를 지원하는 여러 가지 도구를 제공합니다. 이를 사용하면 개발자는 사용자의 데이터를 안전하게 보호하고, 시스템 간에 데이터를 안전하게 전송할 수 있습니다.

 

✅ 단방향 암호화와 양방향 암호화

암호화에는 크게 두 가지 유형, 즉 단방향 암호화양방향 암호화가 있습니다.

 

단방향 : blog → akdfc$lajdfdcfkdsalcjghieffa 만 가능 (다시 blog로 못돌림)

양방향 : blog ↔ akdfc$lajdfdcfkdsalcjghieffa (서로 가능)

 

단방향 암호화는 원본 데이터를 암호화된 데이터로 변환하는 과정이며, 이 변환된 데이터는 원래의 상태로 복원할 수 없습니다. 이러한 방식은 주로 해싱 알고리즘을 사용하며, 비밀번호 저장과 같이 원본 데이터를 복원할 필요가 없는 경우에 사용됩니다. 예를 들어, 사용자가 비밀번호를 입력하면 해당 비밀번호는 해싱 알고리즘을 통해 해시 값으로 변환되고 이 값이 데이터베이스에 저장됩니다. 사용자가 다시 로그인할 때, 입력한 비밀번호가 같은 해싱 알고리즘을 통해 해시 값으로 변환되어 저장된 해시 값과 비교됩니다.

저자 서명, 파일, 데이터의 식별자, 사용자의 비밀번호, 블록체인 등에서 활용

 

반면에, 양방향 암호화는 원본 데이터를 암호화된 데이터로 변환한 후, 필요에 따라 다시 원본 데이터로 복호화할 수 있는 과정입니다. 이러한 방식은 대칭키 또는 비대칭키 암호화 알고리즘을 사용하며, 데이터를 안전하게 전송하거나 저장해야 하는 경우에 사용됩니다. 예를 들어, 신용카드 번호, 개인 식별 정보 등 민감한 정보를 암호화하여 데이터베이스에 저장하고, 필요할 때 복호화하여 원본 데이터를 확인합니다.

 

✅ BCrypt

BCryptBlowfish 암호화 알고리즘을 기반으로 하는 암호화 방식입니다. 이 방식은 강력한 해싱 함수와 솔트를 사용하여 비밀번호를 암호화합니다. BCrypt는 원본 비밀번호에 랜덤한 문자열인 솔트를 추가하고, 이를 몇 차례 반복하여 해싱합니다. 이렇게 함으로써, 동일한 비밀번호라도 솔트 값이 다르면 해싱 결과도 다르게 되어, 무차별 대입 공격(brute force attack)을 어렵게 만듭니다.

스프링 시큐리티에서는 BCryptPasswordEncoder라는 클래스를 통해 BCrypt 암호화를 쉽게 사용할 수 있습니다. 이 클래스는 비밀번호를 암호화하거나, 원본 비밀번호와 암호화된 비밀번호를 비교하는 데 사용됩니다.

 

📌 BCryptPasswordEncoder

 

BCryptPasswordEncoder는 스프링 시큐리티에서 제공하는 비밀번호 암호화 도구 중 하나입니다. 이 클래스는 BCrypt 해싱 함수를 사용하여 비밀번호를 암호화합니다. BCrypt는 솔트(salt)를 사용하여 원본 비밀번호를 해싱하고, 이것을 다시 암호화하여 최종적인 해싱된 비밀번호를 생성합니다. 솔트는 각 비밀번호에 랜덤값을 추가하여 동일한 비밀번호라도 다른 해싱값을 생성하게 만듭니다. 이는 무차별 대입 공격(brute force attack)이나 레인보우 테이블 공격(rainbow table attack) 등 비밀번호 크래킹 방법을 매우 어렵게 만듭니다.

BCryptPasswordEncoder의 주요 메소드는 다음과 같습니다:

  • encode(CharSequence rawPassword): 원본 비밀번호를 암호화합니다. 이 메소드는 원본 비밀번호에 랜덤 솔트를 추가하고, 이를 BCrypt 해싱 함수에 적용하여 해싱된 비밀번호를 생성합니다.
  • matches(CharSequence rawPassword, String encodedPassword): 원본 비밀번호와 암호화된 비밀번호를 비교합니다. 이 메소드는 원본 비밀번호를 동일한 방법으로 암호화하고, 이것이 저장된 암호화된 비밀번호와 일치하는지 확인합니다.

따라서, 비밀번호를 저장하거나 검증할 때는 다음과 같이 BCryptPasswordEncoder를 사용할 수 있습니다.

BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
// 비밀번호 암호화
String rawPassword = "secret";
String encodedPassword = encoder.encode(rawPassword);
// 비밀번호 검증
boolean result = encoder.matches(rawPassword, encodedPassword);

✅ 솔트(salt)

솔트는 암호화 과정에서 중요한 역할을 하는 랜덤 데이터입니다. 이는 원본 데이터(예: 비밀번호)에 추가되어 암호화 과정을 복잡하게 만듭니다. 솔트의 사용은 각각의 비밀번호에 고유한 값을 부여하여, 동일한 원본 데이터라도 서로 다른 암호화 결과를 가져오게 합니다.

→ (랜덤 데이터)솔트로 인해서 equals 비교가 불가능, 꼭 제공하는 mathches를 사용할 것

✅ 키 스트레칭(Key Stretching)

키 스트레칭은 비밀번호의 안전성을 높이는 방법 중 하나입니다. 이 방법은 암호화된 비밀번호를 생성할 때 해싱 함수를 여러 번 반복적으로 적용하는 것을 의미합니다. 이렇게 하면 비밀번호를 추측하려는 공격자가 더 많은 시간을 소비하게 됩니다.

  1. 비밀번호가 짧거나 간단한 경우: 키 스트레칭을 사용하면 짧거나 간단한 비밀번호도 더 안전하게 보호할 수 있습니다. 이는 공격자가 모든 가능한 비밀번호를 시도하는 무차별 대입 공격(brute-force attack)을 방어하는 데 도움이 됩니다.
  2. 해시 함수가 빠른 경우: 키 스트레칭을 사용하면 해시 함수의 속도를 늦추어 공격자가 빠르게 비밀번호를 추측하는 것을 방지할 수 있습니다.

따라서 키 스트레칭은 비밀번호의 안전성을 높이는데 중요한 역할을 합니다. 이 방법은 간단하지만 효과적인 방법으로, 비밀번호를 보호하는 데 필수적인 보안 기능입니다.

✅ 해싱 함수

해싱 함수는 원본 데이터를 고정된 길이의 고유한 값으로 변환하는 함수입니다. 이는 원본 데이터를 원래의 상태로 복원할 수 없는 단방향 암호화 방식을 사용합니다. 일반적으로, 해싱 함수는 비밀번호 저장, 디지털 서명, 체크섬 등에 사용됩니다. 잘 설계된 해싱 함수는 원본 데이터의 작은 변화라도 해시 결과에 큰 변화를 가져와야 합니다.

 

 


 

✔️ 레인보우 테이블

 

레인보우 테이블은 해시 함수의 출력을 빠르게 역산하기 위해 사용되는 기법 중 하나입니다. 이는 미리 계산된 해시 값과 그에 해당하는 원본 데이터를 저장한 대형 데이터베이스인데, 이 테이블을 사용하면 해시 값만을 가지고 원본 데이터를 빠르게 찾아낼 수 있습니다.

하지만, 레인보우 테이블을 이용한 공격을 방어하기 위해 솔트를 사용하는 방법이 일반적으로 사용됩니다. 솔트를 사용하면, 동일한 비밀번호라도 각각 다른 해시 값을 가지게 되므로 레인보우 테이블을 이용한 공격을 효과적으로 방어할 수 있습니다. 이는 각각의 비밀번호가 고유한 솔트와 함께 저장되기 때문에, 공격자는 각각의 솔트 값에 대해 별도의 레인보우 테이블을 계산해야 하는 상황을 만들어냅니다. 이렇게 되면 레인보우 테이블을 이용한 공격은 더 이상 경제적으로 이득이 되지 않게 됩니다.

✔️ CSRF

CSRF는 Cross-Site Request Forgery의 약자입니다. 이는 웹 사이트의 취약성을 이용하여 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행동을 하도록 만드는 공격 방법입니다. 사용자가 로그인한 상태에서 CSRF 공격을 받게 되면, 공격자는 사용자의 권한을 도용하여 원하지 않는 작업을 수행하게 만들 수 있습니다.

스프링 시큐리티는 CSRF 공격을 방어하기 위해 CSRF 보호 기능을 제공합니다. 이 기능은 기본적으로 활성화되어 있으며, 서버는 클라이언트에게 CSRF 토큰을 전송합니다. 클라이언트는 이 토큰을 사용하여 요청을 서버에 보내고, 서버는 이 토큰을 검증하여 요청의 정당성을 확인합니다. 이렇게 함으로써, 공격자가 위조한 요청을 서버가 거부하도록 할 수 있습니다.