Spring Security ‐ OAuth 2.0 검증 - dnwls16071/Backend_Summary GitHub Wiki
📚 JCA(Java Cryptography Architecture) & JCE(Java Cryptography Extension)
- Java는 JCA & JCE 프레임워크를 통해 자체적인 보안 관련 기능을 제공하고 있으며 전자서명, 메시지 다이제스트, 인증서와 인증서 유효성 검사, 키 생성 및 관리 그리고 보안 랜덤 수 생성 등 현대 정보 통신 암호 기술 중에서 필수적인 것은 모두 제공하고 있다.
- JCA & JCE 프레임워크는 프로바이더 보안 구조를 사용하여 보안과 관련한 다양한 API를 제공하고 있다.
- 프로바이더는 java.security.Provider 클래스의 구현체로 보안 알고리즘 구현체 목록을 포함하고 있고 이를 통해 보안 서비스를 구현할 수 있다.
MessageDigest
- 메시지 다이제스트 목적은 원본 파일이 그대로인지 파악하는 무결성 검사이다.
- 메시지 다이제스트 알고리즘은 입력 값으로 전달된 다양한 길이의 원본 값을 고정 길이 해시 값으로 출력한다.
- 이 알고리즘은 단방향이기 때문에 해시 값에서 원본을 도출할 수 없다.
Signature
- Signature는 초기화 시 제공받은 키를 사용해서 데이터를 서명하고 전자 서명 유효성을 검증하는데 사용된다.
- 서명
- Signature 객체는 개인 키로 서명하기 위해 초기화되고 서명할 원본 데이터가 제공된다.
- Signature의
sign()은 개인 키로 원본 데이터를 서명하면 해시된 데이터를 암호화한 Signature Bytes를 반환하게 된다.
- 검증
- 검증이 필요한 경우 검증을 위해 Signature 객체를 생성 및 초기화하고 개인키와 쌍을 이루는 해당 공개 키를 제공한다.
- 원본 데이터와 Signature Bytes가 검증 Signature 객체에 전달되고
verify()를 실행하면 공개 키로 Signature Bytes의 해시 데이터를 추출하고 원본 데이터를 해시 값과 비교해서 일치하면 Signature 객체가 성공을 보고하게 된다.
- 서명은 메시지 다이제스트와 비대칭키 암호화가 결합한 형태로서 SHA256WithRSA처럼 메시지 다이제스트 알고리즘인 SHA256을 사용하여 초기에 대규모 데이터를 보다 관리하기 쉬운 고정길이 형식으로 압축한 다음 비대칭키 암호화인 RSA 알고리즘으로 고정 길이의 32바이트 메시지 다이제스트에 서명한다.
📚 JCA & JCE - 비대칭키/대칭키
대칭키 암호(Symmetric Key Algorithm)⭐
- 암호화 알고리즘의 한 종류로, 암호화와 복호화에 같은 암호 키를 쓰는 알고리즘을 의미한다.
- 대칭키 암호화에서는 암호화를 하는 측과 복호화를 하는 측이 같은 암호 키를 공유해야 한다.
- 비대칭키 암호에서 공개 키와 비밀 키를 별도로 가지는 것과 구별되며 대부분의 대칭키 암호 방식은 비대칭키 암호와 비교하여 계산 속도가 빠르다는 장점을 가진다.
MAC(Message Authentication Code)
- 메시지 인증 코드는 데이터가 변조(수정/삭제/삽입 등)가 되었는지를 검증할 수 있도록 데이터에 덧붙이는 코드
- 해시 값을 생성한다는 점에서 메시지 다이제스트와 비슷하나 초기화 시 비밀키(Secret Key)를 요구한다는 점에서 다르다.
- 메시지 다이제스트는 받은 측이 누구든지 무결성 검사가 가능하나 MAC는 오직 동일한 비밀키를 가진 쪽에서만 전달받은 메시지 무결성을 검사할 수 있다.
- 암호화 해시 함수를 기반으로 하는 MAC이 잘 알려진 HMAC이다.
- HMAC은 메시지 다이제스트 알고리즘과 공유된 비밀 키의 조합으로 가능하며 데이터 무결성과 기밀성, 송/수신자간 인증을 보증하기 위한 암호화 기법이다.
비대칭키 암호(Asymmetric Key Algorithm)⭐
- 암호화 알고리즘의 한 종류로, 암호화와 복호화에 사용되는 암호 키가 다르다.
- 외부에 절대 노출되어선 안되는 개인키와 공개적으로 개방되어 있는 공개키를 쌍으로 이룬 형태이다.
- A의 공개키를 이용해 암호화된 데이터는 A의 개인키로만 복호화가 가능하다.
- A의 개인키를 이용해 암호화된 데이터는 A의 공개키로만 복호화가 가능하다.
- 데이터 보안 문제 해결 : 송신자 공개키로 암호화를 하면 송신자 개인키로 복호화를 통해 데이터를 안전하게 전송할 수 있다.
- 인증 : 송신자 개인키로 암호화를 하면 송신자 공개키로 복호화를 통해 메시지를 인증하는 것이 목적이다.
RSA
- 현재 SSL/TLS에 가장 많이 사용되는 공개키 암호화 알고리즘으로 대부분의 인터넷 뱅킹이 이 RSA-2048 암호화를 사용한다.
Key
- JCA에서 지원하는 모든 종류의 키에 대한 최상위 인터페이스
getAlgorithm() : 키 알고리즘은 보통 대칭키 암호화 방식(AES, DSA) 또는 비대칭키 연산 알고리즘(RSA)
getEncoded() : 기본 인코딩된 형식의 키를 반환
getFormat() : 기본 인코딩 형식의 이름을 반환
KeyPair
- 키 쌍(공개키와 개인키)을 보관하고 접근할 수 있는 기능만을 제공한다.
KeyPairGenerator
- 공개키 및 개인키 쌍을 생성하는데 완전히 새로운 객체를 생성한다.
KeyFactor
- 어떤 키 데이터 객체를 다른 타입의 키 데이터 객체로 전환하는데 사용한다.
JCA & JCE 구조
- Cipher
- 암호화 및 복호화에 사용되는 암호화 기능을 제공한다.
- 암호화는 일반 텍스트와 키를 가져와 암호화된 데이터를 생성하는 프로세스
- 복호화는 암호화된 데이터와 키를 가져와 일반 텍스트를 생성하는 역과정
- Cipher 객체 인스턴스화하기
Cipher c1 = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding"); // 인스턴스 생성 시 변환 지정 [1]
Cipher c1 = Cipher.getInstance("RSA") // 인스턴스 생성 시 변환 지정 [2]
- Cipher 초기화하기
- Cipher 객체를 초기화하기 위해서 Cipher의 작동 모드를 나타내는 opmode와 Key 또는 증명서(Certificate)를 인자로 전달하고
init() 메서드를 실행한다.
- opmode -
ENCRYPT_MODE(암호화 모드로 초기화), DECRYPT_MODE(복호화 모드로 초기화)
📚 JWT
- JWT(Json Web Token, RFC7519)
- 클레임 보안 값을 나타내는 방법으로 두 당사자 간에 안전하게 전달되는 클레임을 표현하기 위한 개방형 표준
- JWT는 인증, 권한 부여 및 정보 교환에 사용된다.
- JWS 또는 JWE 방식으로 구현된다.
- JWS(Json Web Signature, RFC7515)
- Json을 사용하여 디지털 서명 또는 MAC으로 보안된 컨텐츠를 표현하는 방법
- JWE(Json Web Encryption, RFC7516)
- Json을 사용하여 의도한 수신자만 읽을 수 있도록 암호화된 데이터를 나타내는 형식
- JWK(Json Web Key, RFC7517)
- HMAC이나 타원 곡선 또는 RSA 알고리즘을 사용해 공개 키 세트를 JSON 객체로 나타내는 JSON 구조
- JWA(Json Web Algorithm, RFC7518)
- JWS, JWK 및 JWE에 필요한 알고리즘 목록으로 JWS 헤더 및 JWS 페이로드의 내용을 서명하는데 사용된다.
JWS 구조
- JOSE Header
- 일반적으로 JWT인 토큰 유형과 HMAC SHA256 또는 RSA와 같은 서명 알고리즘의 두 부분으로 구성된다.
- Base64Url로 인코딩되어 Json 웹 토큰의 첫 번째 부분을 형성한다.
- Payload
- 토큰에 포함할 내용인 클레임을 포함하는 페이로드로서 표준 필드인 7개의 등록 클레임 이름 및 사용자 지정 클레임 등으로 구성한다.
- Base64Url로 인코딩되어 Json 웹 토큰의 두 번쨰 부분을 형성한다.
- Signature
- 서명은 Base64Url 인코딩을 이용하여 헤더와 페이로드를 인코딩하고 이 둘을 점(.) 구분자와 함께 연결시킴으로써 계산되어 토큰을 안전하게 확인한다.
Claims
- 클레임은 주장하고자 하는 정보를 나타내는 것으로 이 정보를 가지고 있는 바디 부분을 Claim Set이라고 부른다.
- Claim Set은 키 부분인 Claim Name과 Claim Value의 여러 쌍으로 이루어져 있다.
- JWT에는 여러 클레임들을 넣을 수가 있다.
| 속성 |
설명 |
| iss |
토큰을 발급한 발급자(Issuer) |
| sub |
토큰의 주제 혹은 제목(Subject) |
| aud |
토큰을 사용할 수신자(Audience) |
| exp |
토큰 만료 시간, 언제나 현재 시간보다 이후로 설정(Expiration Time) |
| nbf |
not before로 이 시간 이전에는 토큰이 처리되지 않아야함을 설정 |
| iat |
토큰이 발급된 시간(Issued At) |
| jti |
JWT의 고유 식별자로서 중복 방지를 위해 사용되며 일회성 토큰에 사용한다. |
JWT
- 데이터 무결성과 취약점
- Payload의 클레임 값을 변조하여 토큰을 생성한 후 전달하더라도 서명에서 해시된 값과 변조된 값의 해시된 값이 서로 일치하지 않기 때문에 검증에 실패해 데이터 안전성을 보장한다.
- SecretKey를 탈취당했을 경우에는 중요한 정보가 도난당할 수 있는 위험이 발생하기 때문에 SecretKey를 주기적으로 변경하도록 하는 Key Rotation 정책이 필요할 수 있다.
📚 JWK 이해
- 암호화 키를 저장하는 방식으로 인가 서버에서 발행하는 JWT 토큰의 암호화 및 서명에 필요한 암호화 키의 다양한 정보를 담은 JSON 객체 표준이다.
- JwkSetUri 정보를 설정하면 인가 서버로부터 JWK 형태의 정보를 다운로드할 수 있고 JWT를 검증할 수 있다.
- 자바 표준 보안 클래스를 사용하여 대칭키/비대칭키 방식의 JWT 암호화 및 전자서명, 이후 검증을 위한 키 생성, 변환 등을 지원한다.
- RSAKey, OctetSequenceKey, OctetKeyPair 등이 있다.
- 암호화 알고리즘 방식에 따라 JWK의 구현체가 있고 각 구현체를 편리하게 생성할 수 있는 제너레이터 클래스이다.
- RSAKeyGenerator : 비대칭 암호화 알고리즘 키를 포함하는 JWK 생성기
- OctetSequenceKeyGenerator : 대칭 암호화 알고리즘 키를 포함하는 JWK 생성기
- EcKeyGenerator : 타원곡선 암호화 알고리즘 키를 포함하는 JWK 생성기