2017-04-11 49 views
0

嗨我正在與客戶端和服務器使用SSL套接字與客戶端身份驗證設置爲true的Java項目。我有一切工作,但我想確定每個方面應該包含在他們的jks中。與java socketSSL的客戶端 - 服務器通信。什麼證書真的需要

客戶
1.客戶端的私有密鑰(key.pem)&公鑰(cert.pem)。
2.中級CA公鑰(cert.pem)。

服務器
1.服務器私有密鑰(key.pem)&公鑰(cert.pem)。
2.中級CA公鑰(cert.pem)。

我一直在閱讀很多關於證書的知識,但我無法真正理解什麼證書是真正需要的。

問題

1.我讀的客戶端應該只包含根CA和他的證書,以及服務器的所有鏈條和他的證書。這是處理這個問題的正確方法嗎?

2.我還讀了服務器應該有兩個jks,一個帶有證書,另一個帶有trustchain。我真的不知道應該包含哪些內容。

3.代碼僅在服務器和客戶端具有javax.net.ssl.keyStore和javax.net.ssl.trustStore時有效。如果我刪除其中一個他們停止工作,爲什麼?從我讀的客戶端應該能夠只與trustStore一起工作。

我知道互聯網上有很多信息,我花了一個星期的時間閱讀,但我仍然無法真正瞭解這個問題。即使代碼有效,我真的想知道它爲什麼有效,以及正確的方法是什麼。

我從以下網站的tutorila創建了一個批次:https://jamielinux.com/docs/openssl-certificate-authority/

我正在使用一個輔助項目來測試ssl套接字連接。這是我使用的是什麼:

客戶端(MWE)

package com.test.ssl; 

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 

import javax.net.ssl.SSLSocket; 
import javax.net.ssl.SSLSocketFactory; 


public class Client { 

    private static final String IP = "127.0.0.1"; 
    private static final int PORT = 15000; 
    private static DataOutputStream os; 
    private static DataInputStream is; 
    private static final byte messageEnd = 0; 

    public static void main(String[] args) { 
     System.setProperty("javax.net.ssl.keyStore", "D:\\workspace\\Client_Server_SSL\\clientKeyStore.jks"); 
     System.setProperty("javax.net.ssl.keyStorePassword", "CertPass"); 
     System.setProperty("javax.net.ssl.trustStore", "D:\\workspace\\Client_Server_SSL\\clientKeyStore.jks"); 
     System.setProperty("javax.net.ssl.trustStorePassword", "CertPass"); 

     SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); 

     try { 
      SSLSocket sslsocket = (SSLSocket) factory.createSocket(IP, PORT); 
      sslsocket.setNeedClientAuth(true); 
      is = new DataInputStream(sslsocket.getInputStream()); 
      System.out.println("Loading output streams"); 
      os = new DataOutputStream(sslsocket.getOutputStream()); 
      System.out.println("Streams loaded"); 
      os.write("Hi\0".getBytes()); 

      byte character; 
      List<Byte> message = new ArrayList<>(); 
      while ((character = is.readByte()) != messageEnd) { 
       message.add(character); 
      } 

      byte[] messageBytes = byteListToByteArray(message); 
      String response = new String(messageBytes); 
      System.out.println("Server response: " + response); 

     } catch (IOException e) { 

      e.printStackTrace(); 
     } 

    } 

    public static byte[] byteListToByteArray(List<Byte> bytes) { 
     byte[] result = new byte[bytes.size()]; 
     for (int i = 0; i < bytes.size(); i++) { 
      result[i] = bytes.get(i).byteValue(); 
     } 

     return result; 
    } 

} 

服務器(MWE)

package com.test.ssl; 

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 

import javax.net.ssl.SSLServerSocket; 
import javax.net.ssl.SSLServerSocketFactory; 
import javax.net.ssl.SSLSocket; 

public class Server { 

    private static boolean serverListening = true; 
    private static SSLServerSocket sslserversocket; 
    private static final int PORT = 15000; 
    private static DataInputStream is; 
    private static DataOutputStream os; 

    public static void main(String[] args) { 
     System.setProperty("javax.net.ssl.keyStore", "D:\\workspace\\Client_Server_SSL\\serverKeyStore.jks"); 
     System.setProperty("javax.net.ssl.keyStorePassword", "CertPass"); 
     System.setProperty("javax.net.ssl.trustStore", "D:\\workspace\\Client_Server_SSL\\serverKeyStore.jks"); 
     System.setProperty("javax.net.ssl.trustStorePassword", "CertPass"); 

     SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); 

     try { 
      sslserversocket = (SSLServerSocket) factory.createServerSocket(PORT); 
      sslserversocket.setNeedClientAuth(true); 
      while (serverListening) { 
       System.out.println("Waiting for client"); 
       // Accept return a new socket to handle the client. 
       SSLSocket sslsocket = (SSLSocket) sslserversocket.accept(); 

       is = new DataInputStream(sslsocket.getInputStream()); 
       os = new DataOutputStream(sslsocket.getOutputStream()); 
       System.out.println("Client connected"); 

       List<Byte> message = new ArrayList<>(); 
       byte character; 

       while ((character = is.readByte()) != 0) { 
        message.add(character); 
       } 

       byte[] messageBytes = byteListToByteArray(message); 
       String response = new String(messageBytes); 
       System.out.println("Client sad: " + response); 

       os.write("Welcome\0".getBytes()); 
      } 
     } catch (IOException e) { 
      System.err.println("Exception: " + e); 
     } 

    } 

    public static byte[] byteListToByteArray(List<Byte> bytes) { 
     byte[] result = new byte[bytes.size()]; 
     for (int i = 0; i < bytes.size(); i++) { 
      result[i] = bytes.get(i).byteValue(); 
     } 

     return result; 
    } 

} 

批處理腳本:

下載openSSL來自:https://slproweb.com/products/Win32OpenSSL.html
將bin文件夾複製到單獨的文件夾中,並在其中添加批處理文件。 openssl.cnf是第一個鏈接指南中的一個副本。

@echo on 

cd /D %~dp0 

REM could not create all subfolder at onces, I got a syntax error when trying root\ca\{certs,crl,newcerts,private} 
mkdir root\ca\certs 
mkdir root\ca\crl 
mkdir root\ca\newcerts 
mkdir root\ca\private 
type NUL > root\ca\index.txt 
echo 1000 > root\ca\serial 
REM tried to use type but it was not working. 
copy "%~dp0ConfigurationFiles\openssl_ca_test.cnf" root\ca\openssl.cnf 

@echo ______________Creating CA 

openssl genrsa -aes256 -out root/ca/private/ca.key.pem -passout pass:CAPassword 4096 

openssl req -config root/ca/openssl.cnf -key root/ca/private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out root/ca/certs/ca.cert.pem -passin pass:CAPassword 

openssl x509 -noout -text -in root/ca/certs/ca.cert.pem 

@echo ______________INTERMEDIATE CERTIFICATES 

mkdir root\ca\intermediate\certs 
mkdir root\ca\intermediate\crl 
mkdir root\ca\intermediate\newcerts 
mkdir root\ca\intermediate\private 
mkdir root\ca\intermediate\csr 
type NUL > root\ca\intermediate\index.txt 
echo 1000 > root\ca\intermediate\serial 
echo 1000 > root\ca\intermediate\crlnumber 
copy "%~dp0ConfigurationFiles\openss_intermediate_test.cnf" root\ca\intermediate\openssl.cnf 

openssl genrsa -aes256 -out root/ca/intermediate/private/intermediate.key.pem -passout pass:InterMPassword 4096 

openssl req -config root/ca/intermediate/openssl.cnf -new -sha256 -key root/ca/intermediate/private/intermediate.key.pem -out root/ca/intermediate/csr/intermediate.csr.pem -passin pass:InterMPassword 

openssl ca -config root/ca/openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in root/ca/intermediate/csr/intermediate.csr.pem -out root/ca/intermediate/certs/intermediate.cert.pem -passin pass:CAPassword 

type root\ca\intermediate\certs\intermediate.cert.pem root\ca\certs\ca.cert.pem > root\ca\intermediate\certs\ca-chain.cert.pem 


@echo ______________GENERATING CERTIFICATES 

openssl genrsa -aes256 -out root/ca/intermediate/private/www.client.com.key.pem -passout pass:CertPass 2048 

openssl genrsa -aes256 -out root/ca/intermediate/private/www.server.com.key.pem -passout pass:CertPass 2048 

openssl req -config root/ca/intermediate/openssl.cnf -key root/ca/intermediate/private/www.client.com.key.pem -new -sha256 -out root/ca/intermediate/csr/www.client.com.csr.pem -passin pass:CertPass 

openssl req -config root/ca/intermediate/openssl.cnf -key root/ca/intermediate/private/www.server.com.key.pem -new -sha256 -out root/ca/intermediate/csr/www.server.com.csr.pem -passin pass:CertPass 

@echo ______________SIGNING CERTIFICATES 

openssl ca -config root/ca/intermediate/openssl.cnf -extensions usr_cert -days 7000 -notext -md sha256 -in root/ca/intermediate/csr/www.client.com.csr.pem -out root/ca/intermediate/certs/www.client.com.cert.pem -passin pass:InterMPassword 

openssl ca -config root/ca/intermediate/openssl.cnf -extensions server_cert -days 7000 -notext -md sha256 -in root/ca/intermediate/csr/www.server.com.csr.pem -out root/ca/intermediate/certs/www.server.com.cert.pem -passin pass:InterMPassword 

@echo ______________DONE 

PAUSE 

回答

1

我想應該知道什麼每側應包含在他們的JKS。

首先,對於相互認證的SSL,每一方需要 JKS文件:一個密鑰庫和一個信任。不要混淆這些文件,或混淆他們的目的,或者爲這兩個文件使用單個文件。

每種情況下的密鑰存儲都包含該方自己的私鑰和證書,並且簽署的證書鏈直到對等方信任的任何根CA。

每種情況下的信任庫都包含此端信任的根CA.如果對方因使用自簽名證書而出於某種不幸的原因,這相當於要求在該方的信任庫中輸出該證書的副本。

+0

好吧,我明白了,仍然有一些問題:每邊可以有不同的CA?什麼是證書鏈(不包括在自己的證書中)。 O,爲什麼只和中間CA一起工作(沒有根CA)? – MissingSemiColon

+1

是的,每一方都可以有不同的CA,並且通常雙方的信任庫都是JRE附帶的信任庫,它包含許多根CA證書。信任庫必須包含收到證書鏈中的* a *證書。通常這將是根源,但在某些情況下它可能是中級的。證書鏈是CA在簽名時提供的證書鏈,從剛剛簽署的證書開始,並通過其所有內部證書導向他自己的根CA證書,或者甚至更高。 – EJP

+0

非常感謝,所以你會推薦添加根證書和中間文件,還是隻能使用中間文件?我認爲只有分享中間人才更安全。再次感謝您的快速和清晰的答覆。 – MissingSemiColon

相關問題