2013-11-03 3 views
0

Java 및 네트워킹을 배우고 약 9 시간 동안 멈추었 기 때문에 개인 프로젝트 중 하나에 HTTPS 웹 서버를 구축하려고하는데 도움을 요청하고 있습니다. , 실제로 입력 스트림에서 읽으려고 할 때마다Java SSL 소켓 웹 서버 잘못된 인증서

문제는 내 HTTPS 서버 오류 ": 수신 치명적인 경고 bad_certificatejavax.net.ssl.SSLHandshakeException"로 충돌 것입니다. 나는 여러 시간 동안 인터넷 검색을 시도했지만 키를 생성하는 여러 가지 방법을 시도하고 모두 시도했지만 다른 오류 메시지가 계속 표시되었습니다.

내가하는 일은 내 컴퓨터에서 Java 응용 프로그램을 실행하고 포트 443에 바인드 한 다음 연결하기 위해 FireFox를 연 다음 받아 들인 소켓 입력에서 읽으려고 할 때 디버깅에서 엽니 다. 스트림 (코드에 명시된 위치)에서 위의 치명적인 오류로 인해 충돌합니다. 모든 것이 제대로 작동했다면 Firefox 인증서에 표시된 SSL 경고를 무시하고 페이지를 계속 진행할 수있는 기회가 Firefox에 부여되어야합니다. 그러나 치명적인 오류로 인해 내 Java SSL 웹 서버.

나는 인증서 생성 방법 :

#GENERATE KEYS 
keytool -genkeypair -alias plainserverkeys -keyalg RSA -dname "CN=Plain Server,OU=kl2217,O=kl2217org,L=Boston,ST=MA,C=US" -keypass password -keystore plainserver.jks -storepass password 
keytool -genkeypair -alias plainclientkeys -keyalg RSA -dname "CN=Plain Client,OU=kl2217,O=kl2217org,L=Boston,ST=MA,C=US" -keypass password -keystore plainclient.jks -storepass password 

#EXPORT SERVER CERT + IMPORT NEW KEYSTORE 
keytool -exportcert -alias plainserverkeys -file serverpub.cer -keystore plainserver.jks -storepass password 
keytool -importcert -keystore serverpub.jks -alias serverpub -file serverpub.cer -storepass password 

#EXPORT CLIENT CERT + IMPORT NEW KEYSTORE 
keytool -exportcert -alias plainclientkeys -file clientpub.cer -keystore plainclient.jks -storepass password 
keytool -importcert -keystore clientpub.jks -alias clientpub -file clientpub.cer -storepass password 

#EXPORT PLAIN CLIENT CERT + IMPORT TO MAIN JAVA KEYSTORE 
keytool -export -alias plainclientkeys -keystore plainclient.jks -rfc -file plainclient.cert 
keytool -import -trustcacerts -keystore /usr/java/jdk1.7.0_25/jre/lib/security/cacerts -storepass changeit -noprompt -alias mycert -file plainclient.cert 

소스 코드 :

import java.io.BufferedReader; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.security.KeyManagementException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.UnrecoverableKeyException; 
import java.security.cert.CertificateException; 
import javax.net.ssl.KeyManagerFactory; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLServerSocket; 
import javax.net.ssl.SSLServerSocketFactory; 
import javax.net.ssl.TrustManagerFactory; 

public class Main 
{ 
    public static void main(String[] args) 
    { 
     SSLContext context; 
     KeyManagerFactory kmf; 
     KeyStore ks; 
     char[] storepass = "password".toCharArray(); 
     char[] keypass = "password".toCharArray(); 
     String storename = "plainserver.jks"; 
     try 
     { 
      //KEY MANAGER 
      context = SSLContext.getInstance("TLS"); 
      kmf = KeyManagerFactory.getInstance("SunX509"); 
      FileInputStream fin = new FileInputStream(storename); 
      ks = KeyStore.getInstance("JKS"); 
      ks.load(fin, storepass); 
      kmf.init(ks, keypass); 

      //TRUST MANAGER 
      KeyStore clientPub = KeyStore.getInstance("JKS"); 
      clientPub.load(new FileInputStream("clientpub.jks"),"password".toCharArray()); 
      TrustManagerFactory trustManager = TrustManagerFactory.getInstance("SunX509"); 
      trustManager.init(clientPub); 

      //INIT SERVER STUFF 
      context.init(kmf.getKeyManagers(), trustManager.getTrustManagers(), null); 
      SSLServerSocketFactory ssf = context.getServerSocketFactory(); 
      //ServerSocket ss = ssf.createServerSocket(443); 
      SSLServerSocket ss = (SSLServerSocket) ssf.createServerSocket(443); 

      while (true) 
      { 
       System.out.println("ACCEPT"); 
       Socket s = ss.accept(); 
       System.out.println("PROCESS! (1)"); 
       BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); 
       System.out.println("PROCESS! (2)"); 
       String x = in.readLine();  //!!!!!PROGRAM WILL CRASH HERE!!!! 
       System.out.println("PROCESS! (3)"); 
       System.out.println(x); 
       s.close(); 
      } 
     } 
     catch (KeyStoreException | IOException | NoSuchAlgorithmException | KeyManagementException | 
       UnrecoverableKeyException | CertificateException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

나는 오랫동안이 붙어 봤는데 알아 내기 위해 노력하고 싶습니다 왜 잘못되어 있고 왜. 나는 모든 것을 조사했고 인증서, 키 생성에 관한 약 15 개의 튜토리얼을 시험해 보았고 내 코드를 대체하여 다른 코드를 사용하여 내 문제의 원인인지 확인했습니다. 나는 여전히 자바를 배우고 있으며, 도움이 필요하다면 (코드 또는 기타) 도움을 줄 수있을 것입니다.

+0

응답 한 사람이 내 의견을 삭제 한 사람에게 다시 올리시겠습니까? –

+0

전체 스택 추적을 게시하십시오. – EJP

답변

1

A. '충돌'

예외가 충돌하지 않고, 당신의 응용 프로그램을 가지고는 안된다. 그것은 단지 코드 구조가 좋지 않고 예외 처리가 잘 못된 것입니다. run 메소드에서 고유 한 예외 처리를 사용하여 허용 된 소켓 당 스레드를 시작해야합니다.

B. 인증 단계.

#GENERATE KEYS 
keytool -genkeypair -alias plainserverkeys -keyalg RSA -dname "CN=Plain Server,OU=kl2217,O=kl2217org,L=Boston,ST=MA,C=US" -keypass password -keystore plainserver.jks -storepass password 
keytool -genkeypair -alias plainclientkeys -keyalg RSA -dname "CN=Plain Client,OU=kl2217,O=kl2217org,L=Boston,ST=MA,C=US" -keypass password -keystore plainclient.jks -storepass password 

지금까지는 그렇게 좋았습니다. 여기서는 두 개의 키 스토어 (하나는 서버 용, 하나는 클라이언트용)를 작성하거나 갱신했습니다.

#EXPORT SERVER CERT + IMPORT NEW KEYSTORE 
keytool -exportcert -alias plainserverkeys -file serverpub.cer -keystore plainserver.jks -storepass password 
keytool -importcert -keystore serverpub.jks -alias serverpub -file serverpub.cer -storepass password 

여기에서 클라이언트에 대한 신뢰 저장소를 만들거나 업데이트했습니다.

#EXPORT CLIENT CERT + IMPORT NEW KEYSTORE 
keytool -exportcert -alias plainclientkeys -file clientpub.cer -keystore plainclient.jks -storepass password 
keytool -importcert -keystore clientpub.jks -alias clientpub -file clientpub.cer -storepass password 

여기 서버에 대한 신뢰 저장소를 만들거나 업데이트했습니다.

따라서 상호 인증 된 SSL을 사용하는 것이 좋습니다.

#EXPORT PLAIN CLIENT CERT + IMPORT TO MAIN JAVA KEYSTORE 
keytool -export -alias plainclientkeys -keystore plainclient.jks -rfc -file plainclient.cert 
keytool -import -trustcacerts -keystore /usr/java/jdk1.7.0_25/jre/lib/security/cacerts -storepass changeit -noprompt -alias mycert -file plainclient.cert 

왜이 단계를 수행하는지 알 수 없습니다. 첫 번째 명령은 이미 가지고있는 'clientpub.cer'파일의 또 다른 복사본을 만듭니다. 두 번째 부분에서는 이해할 수없는 이유로 JDK 트러스트 스토어에 넣습니다. 이 두 단계와 이전 두 가지 모두 필요하지 않습니다. 이전 두 개 또는 이전 두 개 중 하나만 필요합니다.

하지만 네가 네 가지 이유 중 어떤 것을하고 있는지 이해할 수 없습니다. 당신은 클라이언트 인증서를 설치 한

  1. 당신은 서버에 wantClientAuth 또는 needClientAuth을 활성화하고,
  2. : 당신은 클라이언트 인증서, 클라이언트 키 스토어, 전혀,하지 않는 한 신뢰 서버가 필요하지 않습니다 Firefox 브라우저에서.
+0

JDK 트러스트 스토어에 자체 생성 키를 가져 오는 이유는 다른 튜토리얼에서 제안했기 때문입니다. 나는 9 시간 동안 여기에 있었고 당신은 완전히 옳았다. 방금 코드를 변경하고 소켓을 수락 한 후 내 코드에 try/catch {}를 추가하면 모든 것이 잘 동작합니다. 정말 고맙습니다! 저는 여전히 Java를 배우고 있습니다. 그렇습니다. 코드가 좋지 않지만, 오늘 많은 책을 읽었습니다. 곧 개선 될 것입니다. –

+0

한 가지 더, 나는 인증 생성이 엉망임을 안다. 나는 당신의 충고를 받아 들일 것이고, 그것을 약간 교정 할 것이다. 도와 주셔서 다시 한 번 감사드립니다! –

+0

이 외에도 서버 인증서에는 ('CN = Plain Server') 대신 'CN = the.actual.host.name.' (또는 더 나은 SAN)이 있어야합니다. 나는 이것이 "Plain Server"와 함께 작동한다면 호스트 이름을 검사하지 않을 수도 있다고 생각합니다. (이것들이 더미 이름의 질문으로 대체되었는지는 확실하지 않습니다.) – Bruno