자바 SSL 사용법

2011.12.30 13:24

가을의 곰을... 조회 수:8013

자바 SSL 사용법

POP3

POP3에 암호화된 연결(SSL : Secure Sockets Layer)이 필요한 경우가 종종 있다. JSSE(Java Secure Socket Extension, J2SE 1.4 이후 버전에는 JSSE가 포함되어 있다.)를 이용하여 SSL 연결을 시도할 때 아래와 같은 exception이 발생할 수 있다. 공인 인증기관에서 받은 인증서가 아닌 개인 인증서를 사용하는 경우 많이 발생할 수 있다.


javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target


그렇다면 어떻게 해야 하느냐?? 여러 가지 방법이 있지만, 간단한 방법은 서버의 인증서를 신뢰할 수 있는 인증서 목록(KeyStore)에 추가하면 된다. 인증서를 추가하려면 우선 인증서를 받아야겠다. 인증서는 첨부된 파일을 받아서 컴파일하고 실행하면 된다. 실행시키면 아래와 같은 화면이 나타날 것이다. "ecc.fedora.redhat.com" 부분에 인증서를 원하는 서버의 ip와 port를 써주면 된다.


% java InstallCert ecc.fedora.redhat.com
Loading KeyStore C:\Program Files\Java\jre1.5.0_08\lib\security\cacerts...
Opening connection to ecc.fedora.redhat.com:443...
Starting SSL handshake...

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1476)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:846)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:815)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1025)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1038)
at InstallCert.main(InstallCert.java:63)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:221)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:145)
at sun.security.validator.Validator.validate(Validator.java:203)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
at InstallCert$SavingTrustManager.checkServerTrusted(InstallCert.java:158)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:839)
... 7 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:236)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:194)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:216)
... 13 more

Server sent 2 certificate(s):

1 Subject CN=ecc.fedora.redhat.com, O=example.com, C=US
Issuer CN=Certificate Shack, O=example.com, C=US
sha1 2e 7f 76 9b 52 91 09 2e 5d 8f 6b 61 39 2d 5e 06 e4 d8 e9 c7
md5 dd d1 a8 03 d7 6c 4b 11 a7 3d 74 28 89 d0 67 54

2 Subject CN=Certificate Shack, O=example.com, C=US
Issuer CN=Certificate Shack, O=example.com, C=US
sha1 fb 58 a7 03 c4 4e 3b 0e e3 2c 40 2f 87 64 13 4d df e1 a1 a6
md5 72 a0 95 43 7e 41 88 18 ae 2f 6d 98 01 2c 89 68

Enter certificate to add to trusted keystore or 'q' to quit: [1]


실행시키면 SSL handshake가 일어난다. 화면에는 exception 부분도 출력된다. exception이 출력되는 이유는 서버에서 사용하는 인증서가 없기 때문에 SSL 연결을 성공할 수 없기 때문이다. 자, 인증서를 받자. 그리고 화면에는 trusted KeyStore에 인증서를 추가할 것인지 묻고 있다. sha1과 md5를 확인해서 올바른 인증서인지 확인한 다음, 올바른 인증서인 경우 "1"을 입력해서 인증서를 받으면 되고, 받고 싶지 않은 경우는 "q"를 입력해서 프로그램을 종료시키면 된다. 인증서를 받게 되면 아래와 같은 화면이 출력되고, "jssecacerts" 파일로 인증서가 저장된다.


[
[
Version: V3
Subject: CN=ecc.fedora.redhat.com, O=example.com, C=US
Signature Algorithm: MD5withRSA, OID = 1.2.840.113549.1.1.4

Key: SunPKCS11-Solaris RSA public key, 1024 bits (id 5158256, session object)
modulus: 1402933022884660852748661816869706021655226675890
635441166580364941191074987345500771612454338502131694873337
233737712894815966313948609351561047977102880577818156814678
041303637255354084762814638611185951230474669455913908815827
173696651397340074281578017567044868711049821409365743953199
69584127568303024757
public exponent: 65537
Validity: [From: Wed Jan 18 13:16:12 PST 2006,
To: Wed Apr 18 14:16:12 PDT 2007]
Issuer: CN=Certificate Shack, O=example.com, C=US
SerialNumber: [ 0f]

Certificate Extensions: 2
[1]: ObjectId: 2.16.840.1.113730.1.1 Criticality=false
NetscapeCertType [
SSL server
]

[2]: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
Key_Encipherment
]

]
Algorithm: [MD5withRSA]
Signature:
0000: 6D F4 2A 63 76 2A 05 70 A2 21 0E 1E 4A 31 BE 6B m.*cv*.p.!..J1.k
0010: 15 64 D8 BB 35 36 82 B0 0D 2A 96 FA 7A 9F A1 59 .d..56...*..z..Y
0020: CA 90 C3 28 C5 A6 9B 59 05 3B EB B2 8D C9 5E 38 ...(...Y.;....^8
0030: 62 ED 1A D7 93 DF 2A A5 D6 54 94 23 15 A2 0C E5 b.....*..T.#....
0040: 13 40 2C 3E 59 E4 2A EB 51 AC 9E 28 44 23 87 B1 .@,>Y.*.Q..(D#..
0050: 34 0B AC F3 E0 39 CA B8 35 B4 78 07 BF 28 4C C4 4....9..5.x..(L.
0060: 9A 2B A3 E9 04 26 78 19 F0 62 EA 0A B5 BB DC 0B .+...&x..b......
0070: 90 59 E7 77 90 F8 BC 8A 1B 74 4B 4D C1 F8 3B 6C .Y.w.....tKM..;l

]

Added certificate to keystore 'jssecacerts' using alias 'ecc.fedora.redhat.com-1'


이제 이 인증서를 어떻게 사용할까?? 여기에도 몇 가지 방법이 있다. 가장 간단한 방법은 "$JAVA_HOME/jre/lib/security" 폴더에 받은 인증서 파일을 복사하는 방법이다. (이 경우는 파일명을 변경하면 인증서를 찾지 못 한다. 원인은 아직까지는 잘 모르겠다. 본인은 이 방법 대신 다음 방법을 사용한다.)
그리고 다른 방법은 인증서를 원하는 위치로 옮기고 (이 경우는 파일명을 변경해도 상관 없다.) SSL 연결이 필요한 java 명령을 실행할 때, VM 옵션으로 "-Djavax.net.ssl.trustStore=인증서의 경로(인증서 파일명 포함)"를 추가해주면 된다. 다시 첨부 파일을 실행시켰을 때, 아까와는 다른 아래와 같은 화면이 출력되면 성공이다.

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com


% java InstallCert ecc.fedora.redhat.com
Loading KeyStore jssecacerts...
Opening connection to ecc.fedora.redhat.com:443...
Starting SSL handshake...

No errors, certificate is already trusted

Server sent 2 certificate(s):

1 Subject CN=ecc.fedora.redhat.com, O=example.com, C=US
Issuer CN=Certificate Shack, O=example.com, C=US
sha1 2e 7f 76 9b 52 91 09 2e 5d 8f 6b 61 39 2d 5e 06 e4 d8 e9 c7
md5 dd d1 a8 03 d7 6c 4b 11 a7 3d 74 28 89 d0 67 54

2 Subject CN=Certificate Shack, O=example.com, C=US
Issuer CN=Certificate Shack, O=example.com, C=US
sha1 fb 58 a7 03 c4 4e 3b 0e e3 2c 40 2f 87 64 13 4d df e1 a1 a6
md5 72 a0 95 43 7e 41 88 18 ae 2f 6d 98 01 2c 89 68

Enter certificate to add to trusted keystore or 'q' to quit: [1]
q
KeyStore not changed


알고보면 간단하다. 첨부된 파일로 인증서를 받고, POP3 연결할 때 인증서를 사용하도록 VM 옵션을 추가해주기만 하면된다. 첨부파일에 관한 더 자세한 내용은 첨부파일을 열어 소스를 보기 바란다.

SMTP

[JavaMail] 보내는 메일 서버(SMTP) 인증이 필요한 경우

JavaMail API를 사용하여야 한다. 그런데 연구실 서버가 메일을 보낼 때 SMTP로 인증을 받아야 외부 메일로 발송이 가능하다. 내부로 보내는 것은 SMTP인증이 없이도 가능하다. 음... 한참을 해멨다. 분명히 Authenticator 클래스 까지 상속받아서 구현까지 했는데 getPasswordAuthentication() 메소드 조차 호출을 하지 않는 것이다. 해결 방법은 간단했다. Properties에 SMTP 인증을 사용한다고 지정해주기만 하면 된다.

이런 간단한 것 때문에 몇시간을 날린겨 -ㅅ-; 아래는 초간단 예제 코드


String host = "hostAddress";
String user = "xxx";
String password = "yyy";
String from = "xxx@fromHostAddress";
String to = "zzz@toHostAddress";

Properties properties = System.getProperties();
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.auth", "true");
// SMTP 인증이 필요한 경우 반드시 Properties에 SMTP 인증을 사용한다고 설정하여야 한다. 그렇지 않으면 인증을 시도조차 하지 않는다.

// 그리고 Authenticator 클래스를 상속받은 MyAuthenticator 클래스를 생성한다. getPasswordAuthentication() 메소드만 override하면 된다.
// 머 사실 다른 메소드는 final 메소드여서 override할 수 조차 없다. -ㅅ-;
Authenticator authenticator = new MyAuthenticator(user, password);

Session session = Session.getDefaultInstance(properties, authenticator);

MimeMessage message = new MimeMessage(session);
InternetAddress fromAddress = new InternetAddress(from, "sender", "euc-kr");
InternetAddress toAddress = new InternetAddress(to, "receiver", "euc-kr");

message.setFrom(fromAddress);
message.addRecipient(MimeMessage.RecipientType.TO, toAddress);
message.setSubject("mail test");
message.setText("this is test mail");

Transport.send(message);



 
본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
95 Best and Free Programming Ebooks with Open Source Licenses 가을의 곰을... 2012.02.12 6998
94 Stanford Univ Lecture : Web Applications file 가을의 곰을... 2012.02.11 5895
93 Mobile Web Application과 Webstore 가을의 곰을... 2012.02.11 6675
92 Libpcap File Format 가을의 곰을... 2012.02.05 12147
91 소프트웨어 특허 실제 사례 분석-4 가을의 곰을... 2012.01.23 7063
90 데스크톱 가상화 시장 뜰까 file 가을의 곰을... 2012.01.19 6737
89 MP3 탄생 배경 2. MP3와 디지털 오디오 3. MP3 압축 원리 4. MPEG의 종류 가을의 곰을... 2012.01.18 7525
88 소프트웨어 특허 실제 사례 분석-3 가을의 곰을... 2012.01.12 6364
87 소프트웨어 특허 실제 사례 분석-2 가을의 곰을... 2012.01.12 6775
86 소프트웨어 특허 실제 사례 분석-1 가을의 곰을... 2012.01.12 7063
85 How to run HelloWorld and tests of cocos2d-x on bada file 가을의 곰을... 2012.01.05 6823
» 자바 SSL 사용법 가을의 곰을... 2011.12.30 8013
83 Apache HttpClient로 https 연결 데이터 받기 가을의 곰을... 2011.12.30 10868
82 libpcap 를 이용한 프로그래밍 가을의 곰을... 2011.12.18 6272
81 소스 분석 툴 ( Linux) tools 가을의 곰을... 2011.12.18 11120
80 C 코드 분석 툴 file 가을의 곰을... 2011.12.18 11336
79 [공부] Tcpdump & pcap분석 file 가을의 곰을... 2011.12.08 10687
78 자바 입출력( java stream ) 가을의 곰을... 2011.12.08 6845
77 게임소설 쓰는 법 file 가을의 곰을... 2011.12.04 5572
76 게임소설이란 무엇인가? 위키백과에서 가을의 곰을... 2011.12.04 5870
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED