
이 글에서는 자바 암호 패키지인 JCA(Java Cryptography Architecture)와 JCE(Java Cryptography Extension)에 대해서 알아보고, 실무 활용 방법에 대해서 알아보겠습니다.
안녕하세요. IT반장입니다.
최근에 많은 프로그램들이 자바 언어로 만들어지고 있습니다. 서버 프로그램뿐 만 아니라 클라이언트 프로그램도 자바 언어로 프로그래밍 되는 경우가 많습니다. (예, 스프링프레임워크, 안드로이드 등) 그리고 자바 언어에서는 암호화를 위해 JCA(Java Cryptography Architecture)와 JCE(Java Cryptography Extension) 패키지를 제공하고 있습니다. 이 글에서는 암호 프로그래밍에서 쉽게 자주 접하게 되는 JCA와 JCE에 대해서 알아보고 실무 활용 방법을 설명하겠습니다.
1. JCA(Java Cryptography Architecture) [1][2]
[참고] 기타 JDK 암호 라이브러리
- JSSE(Java Secure Socket Extension): SSL/TLS 기능 제공
- JGSS(Java Generic Security Services): Kerberos, 네트워크 보안 기능 제공
- SASL(Simple Authentication and Security Layer): 네트워크 보안 기능 제공
구조

[그림0] MD5 메시지 다이제스트 구현 설명도
[그림0]에서 보듯이 각각의 어플리케이션은 'Provider Framework'를 통해서 각각의 독립적인 'Provider'에 접근해서 암호 기능을 구현할 수 있습니다.
클래스명(인터페이스명) | 내용 |
Provider | 기본 Provider 클래스 |
Security | Provider' 및 'security property' 관리 |
SecureRandom | 난수(random number) 생성 |
MessageDigest | 해시값 생성 |
Signature | 전자 서명 & 검증 |
Cipher | 블록 암호(AES, DES, DESede, Blowfish, IDEA 등), 스트림 암호(RC4 등), 비대칭 암호(RSA 등), 패스워드 암호 (PBE 등) 등 제공 |
MAC (Message Authentication Codes) | MAC(해시값 생성 & 무결성 보장 기능) |
Key(Key) | 기본 키 클래스(인터페이스) |
KeyFactory | 키 타입 변환 |
SecretKeyFactory | 대칭키 타입 변환 |
KeyPairGenerator | 공개키/개인키 생성 |
KeyGenerator | 대칭키 생성 |
KeyAgreement | 키 교환 정보 |
KeyStore | 키 관리 |
AlgorithmParameters | 알고리즘 파라미터 |
AlgorithmParameterGenerator | 알고리즘 파라미터 생성 |
CertificateFactory | 인증서, 인증서폐기목록(CRL) 생성 |
CertPathBuilder | 인증서체인 생성 |
CertPathValidator | 인증서체인 검증 |
CertStore | 인증서, 인증서폐기목록(CRL) 관리 |
[표1] JCA 주요 클래스

[그림1] 전자서명 및 검증 설명도
/* 키생성을 위한 KeyPairGenerator 클래스 생성 */ KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA"); /* 랜덤값 생성 */ SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN"); keyGen.initialize(1024, random); /* KeyPair 생성 */ KeyPair pair = keyGen.generateKeyPair(); /* 'SHA1withDSA' Signature 클래스 생성 */ Signature dsa = Signature.getInstance("SHA1withDSA"); /* 개인키 생성 */ PrivateKey priv = pair.getPrivate(); dsa.initSign(priv); /* 데이터를 넣고, 전자서명 */ dsa.update(data); byte[] sig = dsa.sign(); /* 공개키 생성 */ PublicKey pub = pair.getPublic(); dsa.initVerify(pub); /* 데이터를 넣고, 서명검증 */ dsa.update(data); boolean verifies = dsa.verify(sig); System.out.println("signature verifies: " + verifies);
|
[소스코드1] 전자서명/검증 예제 소스코드
[그림1]과 [소스코드1]은 간단한 전자서명과 검증 예를 설명하고 있습니다. 위와 같이 JCA에서는 키생성, 전자서명/검증을 위한 API를 제공하고 그 외에 다양한 확장 기능을 제공합니다.
암호화

[그림2] 암복호화 설명도
// 대칭키와 IV 설정 SecretKey myKey = ... byte[] myAAD = ... // 'Additional Associated Data' 로 무결성 확인 용도 byte[] plainText = ... int myTLen = ... byte[] myIv = ... // AES GCM모드 암호화를 위한 파라미터 설정 GCMParameterSpec myParams = new GCMParameterSpec(myTLen, myIv); Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); c.init(Cipher.ENCRYPT_MODE, myKey, myParams); // 암호화 c.updateAAD(myAAD); // if AAD is non-null byte[] cipherText = new byte[c.getOutputSize(plainText.length)]; c.doFinal(plainText, 0, plainText.length, cipherText // 복호화를 위한 Cipher 클래스 설정 및 복호화 c.init(Cipher.DECRYPT_MODE, myKey, myParams); c.updateAAD(myAAD); byte[] recoveredText = c.doFinal(cipherText); // GCM모드에서 동일키 사용을 위한 IV 재생성 byte[] newIv = ...; myParams = new GCMParameterSpec(myTLen, newIv);
|
[소스코드2] 암복호화 예제 소스코드
[그림2]와 [소스코드2]는 간단한 대칭키 암호화 예(AES GCM모드)를 설명하고 있습니다. 평문, 대칭키, IV(Initial Vector), ParameterSpec을 설정하고 Cipher.doFinal 메소드를 통해서 암복호화를 할 수 있습니다.
[그림 3] MAC 설명도
import java.security.*; import javax.crypto.*; public class initMac { public static void main(String[] args) throws Exception { // Generate secret key for HMAC-MD5 KeyGenerator kg = KeyGenerator.getInstance("HmacMD5"); SecretKey sk = kg.generateKey(); // Get instance of Mac object implementing HMAC-MD5, and // initialize it with the above secret key Mac mac = Mac.getInstance("HmacMD5"); mac.init(sk); byte[] result = mac.doFinal("Hi There".getBytes()); } }
|
[소스코드3] MAC 설명도
[그림3]와 [소스코드3]은 MAC(Message Authentication Code)을 설명하고 있습니다. 메시지("Hi There")의 MAC값을 생성하고, 이후 'Secret Key'를 공유하여 MAC값이 동일한지를 비교합니다.
Generators 와 Factories

[그림4] Generators와 Factories 설명도
[그림4]에서 보시는 바와 같이 Generator 클래스는 새로운 오브젝트(대칭키 등) 생성을 위한 파라미터를 설정하고, Factory 클래스는 이전에 정의된 오브젝트를 변환할 때 사용됩니다.
KeyFactory 클래스

[그림5] KeyFactory 클래스 설명도
[그림5]에서 보시는 바와 같이 KeyFactory 클래스는 'Key Spec'으로부터 'Key'를 생성하기도 하고, 반대로 'Key'로부터 'Key Spec'을 추출할 수 있습니다. 'Key Spec'에는 'Key'에 대한 정보가 포함되어 있습니다.
SecretKeyFactory 클래스

[그림6] SecretKeyFactory 클래스 설명도
[그림6]에서 보시는 바와 같이 'SecretKeyFactory' 클래스는 'Key Spec'에서 대칭키('Secret Key')를 생성할 수 있고, 대칭키로부터 'Key Spec'을 가져올 수 있습니다.
KeyPairGenerator 클래스

[그림7] KeyPairGenerator 클래스 설명도
[그림7]은 KeyPairGenerator가 두가지 방법으로 공개키/개인키를 생성하는 것을 보여줍니다. 하나는 알고리즘 독립적으로 키를 생성하는 방법이고, 다른 하나는 알고리즘을 정해서 키를 생성하는 방법입니다.
KeyGenerator 클래스

[그림8] KeyGenerator 클래스 설명도
[그림8]은 KeyGenerator 클래스가 대칭키를 생성하는 방법을 보여줍니다. 마찬가지로 알고리즘을 정해서 생성하는 방법과 그렇지 않은 방법이 있습니다.
KeyAgreement 클래스

[그림9] KeyAgreement 클래스 설명도
[그림9]은 Alice와 Bob이 DH 'Key Agreement'를 하는 과정을 보여줍니다. 공개키를 서로 교환하고 'Secret Key'를 생성하여 동일한지를 비교합니다.
KeyStore 클래스

[그림10] KeyStore 클래스
[그림10]는 KeyStore 클래스를 보여줍니다. 신뢰된 인증기관 인증서(Trusted Certificate), 공개키/개인키, 대칭키를 저장/추출할 수 있고, 파일 형태로 저장되는 것을 알 수 있습니다.
2. JCE(Java Cryptography Extension)
JCE는 JCA보다 더 강력한 확장된 보안 기능을 제공합니다. 미국에서 보안상 이유로 2000년 이후에나 해외로 보급되었습니다.[5]

[그림11] JCA와 JCE 구조 설명도
[그림11]에서 보시는 것처럼 JCA(java.security 패키지)와 JCE(javax.crypto 패키지)가 분리되어 있는 것을 알 수 있습니다. JDK1.4 이상부터는 모두 기본으로 포함되어 있습니다.
JCE에 포함되는 클래스는 Cipher, KeyGenerator, SecretKeyFactor, KeyAgreement, MAC 등입니다.
여기서 SUN JCE와 BouncyCastle 을 비교하겠습니다. [3][4]
| 장점 | 단점 |
SUN JCA/JCE | - JDK에 포함되어 있음 - 'provider'를 선택해서 사용할 수 있음 | - JDK 별로 provider가 일치하지 않아서 동작하지 않을 수 있음 (Java mobile 등) - 알고리즘을 많이 제공하지 않음 |
Bouncy Castle | - JCA보다 많은 알고리즘을 지원 * SEED128 알고리즘 지원 - 사용에 아무런 제한이 없음(128비트 암호키 제한 등[5]) | - 라이브러리 파일을 프로젝트에 추가시켜야함 |
[표2] JCA/JCE 와 BouncyCastle 비교
[표2]에서 보시는 것처럼 BouncyCastle이 더 많은 알고리즘 지원 및 호환성이 좋은 것을 알 수 있습니다. 특히, 국산암호알고리즘 SEED를 지원하므로 더 많은 곳에 사용할 수 있습니다.[4]
※ '암호알고리즘사용제한' 제거 설정
- [참고8]에서 정책 파일을 다운로드하고, zip 압축을 푼 후에, local_policy.jar, US_export_policy.jar 파일을 $JAVA_HOME/jre/lib/security 에 복사하면 됩니다. [6][7][8]
※ 자바암호패키지(JCA/JCE)는 JDK1.4이상에서 기본으로 포함되어 있기 때문에 별도의 설치 방법이나 활용 방법을 설명하지 않습니다.
이번 글에서는 JAVA에서 기본으로 지원하는 암호 패키지인 JCA와 JCE에 대해서 알아보았습니다. 기본적인 키생성, 암호화, 전자서명 등은 JCA/JCE로 가능합니다. 하지만 JDK별로 호환이 안 되는 경우가 있고, 많은 알고리즘을 지원하지 않기 때문에 BouncyCastle 등의 암호 패키지를 사용하는 것이 좋겠습니다.
참고 목록
[1] https://en.wikipedia.org/wiki/Java_Cryptography_Architecture
[2] http://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html
[3] https://blog.idrsolutions.com/2016/08/which-security-implementation-should-i-use-bouncy-castle-or-jca/
[4] http://bouncycastle.org/specifications.html
[5] https://en.wikipedia.org/wiki/Export_of_cryptography_from_the_United_States
[6] http://opensourceforgeeks.blogspot.kr/2014/09/how-to-install-java-cryptography.html
[7] http://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#importlimits
[8] http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
문서 이력
- v1.00(2016.09.01) : 최초 등록