JCA(Java Cryptography Architecture)
JAVA에서의 보안 관련 기능 중에서 JCA(Java Cryptography Architecture)는 핵심이라고 할 수 있다.
JCA는 프로바이더 구조를 사용하여 보안과 관련된 다양한 API를 제공한다.
ex) 전자서명(Digital Signature), 메시지 다이제스트(Message Digest), 인증서 유효성 검사(Certificate Validation), 키생성 등등
설계 원칙
JAVA 플랫폼을 기반으로 구현한 애플리케이션에 정보보호 기술을 적용할 때는 직접 알고리즘을 구현할 필요 없이 JAVA 보안 플랫폼(JCA) API를 통해 보안 서비스를 요청하면 된다. JCA에서 제공하는 보안 서비스는 JAVA 보안 플랫폼에 장착된 프로바이더로 구현된다.
프로바이더 목록은 jre/lib/security/java.security 파일에 기술되어 있다.
아키텍처
Cryptographic Service Providers
모든 프로바이더는 java.security.Provider클래스의 구현체이다. 특정 알고리즘의 인스턴스가 필요하면, JCA프레임워크는 프로바이더 저장소에서 해당 알고리즘의 적합한 구현체 클래스를 찾아 클래스 인스턴스를 생성한다.
JCA를 사용하기 위해서는 간단히 특정 객체 타입(ex.MessageDigest)과 알고리즘 또는 서비스를 요청하면 된다.
(명시적으로 특정 프로바이더의 객체를 요청할 수도 있다.)
MessageDigest md = MessageDigest.getInstance("SHA-256");
MessageDigest md = MessageDigest.getInstance("SHA-256", "ProviderC"); // 명시적으로 요청하는 경우
(이미지 출처)
Key Management
JAVA는 키스토어(KeyStore)라고 부르는 일종의 키 데이터베이스를 사용해 키/인증서 저장소를 관리한다. 키스토어는 인증 또는 암호화, 서명 목적의 정보가 필요한 애플리케이션에서 유용하게 쓰일 수 있다.
키스토어는 비밀키(SecretKey, SymmetricKey), 공개키/개인키 쌍(Public/Private KeyPair, AsymmetricKey), 자가 서명된 인증서(Self-Signed Certificate), 신뢰 받은 인증기관(CA, Certificate Authority)으로부터 서명된 인증서 또는 사설 인증기관으로부터 서명된 인증서를 파일에서 저장 관리할 수 있도록 한다.
인증서
인증서의 암호확적 의미는 RSA 알고리즘에 의해 생성되는 키 쌍의 공개키(Public Key)에 해당하는 것을 인증기관의 개인키(Private Key)로 전자 서명한 것이다.
'갑'과 '을'이 서로 정보를 암호화하여 교신할 때, 갑은 자신의 공개키를 공개하고 한 쌍을 이루는 개인키만 보호하면 된다. 을은 공개된 갑의 공개키로 갑에게 전송할 정보를 암호화하는데, 이때 을이 획득한 공개키가 갑이 제공한 것인지 어떻게 신뢰할 수 있느냐의 문제가 남는다. 악의적인 공격자인 '병'이 자신의 공개키를 갑의 것으로 위장해 을을 속일 수 있다면 공개키 방식은 사용할 수 없는 것이 된다. 바로 이 문제를 해결하기 위해 신뢰할 수 있는 인증기관 '정'이 필요하다. 인증기관은 최상위 루트 인증 기관부터 그 아래 서브 인증기관으로 계층구조를 가지는 체인 구조인데, 상위 계층이 하위 계층을 서명하여 인증하는 구조를 가지고 있다. 이미 오래전에 전세계 표준으로 정착된 기술이기 때문에 전세계 인증서의 서명 체인은 몇 가지 공통 최상위 루트 인증기관(예를 들어, VeriSign, Thawte 등)을 갖는다. 정보 통신 환경이 일정 수준 이상인 국가는 국가별 루트 인증기관(대한민국, KISA)이 있는 게 보통이다. 최상위 루트 인증기관은 서로 서로 서명하는 순환구조를 갖거나, 자신의 개인키로 공개키를 자가 서명할 수도 있다.
HTTPS
HTTPS로 서버와 클라이언트가 통신할 때, 클라이언트의 신원을 확인할 필요 없이 통신 구간만 암호화하는 경우에는 간단한 인증서 유효성 검사만을 한다. 실제 데이터에 대한 암호화는 대칭키 방식이 사용된다.
HTTPS 동작 방식
- 클라이언트가 HTTPS 프로토콜로 서버에 접속
- 서버는 자신의 인증서 공개키를 클라이언트로 전송(유효성 검사를 위한 여러 메타 정보와 서버가 지원하는 Cipher 등도 포함)
- 클라이언트는 서버가 전송한 공개키와 메타 정보를 통해 유효성 검사를 진행(서버의 인증서 공개키가 신뢰할 수 있는 공인 Root CA로 서명됐는지 확인)
- 유효성 검사 과정에서 서버의 인증서가 공인된 CA로 서명됐으면 통과(공인 CA는 시스템상에 신뢰할 수 있는 기관으로 디폴트로 등록돼 있음)
- 사설 CA라면 클라이언트에서 생성한 SSL 소켓(SSLContext)의 트러스트 매니저를 확인한 후, 등록이 되어있다면 통과
- 서버 인증서가 유효성 검사를 통과하면, 클라이언트는 대칭키를 생성 그리고 대칭키와 Cipher를 서버의 공새키로 암호화하여 서버로 전달
- 서버는 클라이언트로 받은 (대칭키와 Cipher : 서버의 공개키로 암호화된 상태)를 자신의 개인키로 복호화하여 앞으로 암호화 통신에서 사용할 대칭키를 획득
- 이후부터 서버와 클라이언트 사이의 데이터 통신은 클라이언트가 생성한 대칭키로 암호화하여 이루어짐
JCA 구조
JCA 구조는 Engine 클래스와 알고리즘으로 설명된다.
JCA에서 엔진 클래스는 특정 암호화 알고리즘 또는 프로바이더에 상관 없이 모든 암호화 서비스 타입을 위한 인터페이스를 제공한다.
MessageDigest
MessageDigest는 입력정보의 메시지 다이제스트(해시)를 계산하는데 사용된다.
메시지 다이제스트의 목적은 원본 파일이 그대로인지 파악하는 무결사 검사이다. 입력값으로 전달된 다양한 길이의 원본 값을 고정 길이 해시 값으로 출력한다. (이 알고리즘은 단방향이기 때문에 해시 값에서 원본 값을 추출할 수 없다.)
Signature
키를 가지고 데이터를 서명하고 전자 서명 유효성을 판단하는데 사용된다.
(이미지 출처)
Signature 객체는 초기화 시 개인키와 서명될 원본 데이터를 인자로 받아 서명을 위한 준비를 끝낸다. Signature의 sign() 메서드는 원본 데이터를 개인키로 서명하고, Signature Bytes를 반환한다. 서명된 데이터의 유효성을 검증할 때는, 서명한 개인키와 쌍을 이루는 공개키로 검증 Signature 객체를 초기화 한다. 이 객체는 원본 데이터와 서명 산출물, Signature Bytes를 추가로 주입받아 verify() 메서드에서 두 인자가 서로 일치하는지 계산하여 원본 정보를 신뢰할 수 있는지 결정한다.
- 전자서명
전자서명 역시 일종의 암호화이다. 하지만 전자서명은 비대칭키 방식 암호화가 필수 조건이다. 전자서명은 메시지 다이제스트와 비대칭키 암호화가 결합한 형태이다. 가변 길이의 대용량 정보는 먼저 메시지 다이제스트로 고정 길이의 관리하기 쉬운 형태로 압축한 후 개인키로 서명하여 고정 길이의 signature Bytes를 생성한다. Signature 인스턴스를 생성할 때 Signature.getInstance() 메서드의 인자로 전달하는 SHA1withRSA, MD5withRSA, SHA1withDSA 등 서명 알고리즘 이름에서 비대칭키 암호화 알고리즘 RSA와 메시지 다이제스트 알고리즘, SHA1, MD5 등이 결합된 전자서명 원리를 볼 수 있다.
Signautre sign = Signature.getInstance("SHA1withRSA");
Cipher 클래스
Cipher 클래스는 암호화/복호화 기능을 제공한다.
대칭키 블록 암호화(AES, DES, DESede, Blowfish, IDEA), 스트림 암호화(RC4), 비대칭키 암호화(RSA) 등을 제공
스트림 암호화 방식(Stream) vs 블록 암호화 방식(Block Cipher)
블록 암호는 고정된 크기의 블록단위로 데이터를 암호화한다. 고정된 길이를 맞추지 못하는 데이터는 의미 없는 더미 값을 덧붙이는 패딩 작업이 필요하다. (복호화 단계에서 제거해야함) 패딩 작업은 Cipher 초기화 시 인자로 전달하는 패딩 유형(PKCS5Padding)에 따라 수행된다.
스트림암호는 바이트 또는 비트 단위로 입력 데이터를 처리하기 때문에 가변 길이 데이터를 패딩 없이 처리할 수 있다.
Modes Of Operation
블록암호화에서 중요한 개념이 피드백 모드(Feedback Modes)이다. 블록 암호화시, 입력데이터가 같으면 암호화된 결과도 동일한 값을 가진다. 이러한 특징 때문에 공격자들은 반복되는 동일패턴의 암호화 데이터에서 암호를 해독할 수 있는 힌트를 얻는다.
이러한 보안 취약점을 막고, 암호화 복잡도를 높이기 위해 피드백 모드가 도입. 피드백 모드는 N번째 암호화 과정에서 N번째 입력 데이터 블록과 N-1번째 입력 데이터블록을 조합하는 (XOR연산) 것이다. 이러한 방식으로 실제로 입력된 데이터 블록의 내용이 동일하더라도 선행 암호화 과정에서 사용된 변수에 따라 값의 차이가 난다. N=1인 경우, N-1 번째 암호화 단계로부터 어떠한 변수도 취할수 없다. 그래서 선행 단계의 변수 대신 그역할을 하는 것이 IV(Initial Value)다. 피드백 모드를 사용하려면 반드시 IV 값을 랜덤하게 생성하여 암호화를 위해 준비해야한다. 복호화시에도 필요하기 때문에 보관하고 있어야 한다.
피드백 모드에는 CBC, CFB, OFB 등이 있다.
Cipher 객체 생성
cipher 인스턴스를 생성할 때, 필수적인 것이 트랜스포메이션(Transformation)을 지정하는 것이다. 트랜스포메이션은 암호화 알고리즘(피드백 모드/패딩)으로 구성된다. 피드백모드를 설정하지않으면, 내부적으로 디폴트 피드백 모드/패딩(ECB/PKCS5Padding)이 지정된다.
Cipher c= Cipher.getInstance("DES/ECB/PKCS5Padding");
또는
Cipher c = Cipher.getInstance("DES");
출처 : https://d2.naver.com/helloworld/197937
'프로그래밍 노트 > JAVA' 카테고리의 다른 글
[JAVA] 컬렉션프레임워크(CollectionFramework) 3 - HashSet (0) | 2018.09.12 |
---|---|
[JAVA] JCA(Java Cryptography Architecture) 자바 암호화와 보안 2 (0) | 2018.09.06 |
[JAVA] 컬렉션프레임워크(CollectionFramework) 2 (0) | 2018.08.13 |
[JAVA] 네트워크 프로그래밍 TCP 소켓 통신 (5) | 2018.07.08 |
[JAVA] 자바7 try-with-resources문, multicatch 문 (1) | 2018.07.08 |