gpt4 book ai didi

java - 在 Java 中创建 HTTPS 服务器 - 本地证书在哪里?

转载 作者:太空宇宙 更新时间:2023-11-03 14:07:27 25 4
gpt4 key购买 nike

我找到了一些教程来处理 https 服务器和 https 客户端。我创建了一些 keystore ,它工作正常。但是我有一些问题在教程中并不清楚。

这是我的 https 服务器

public class HTTPSServer {

private int port = 9999;
private boolean isServerDone = false;

public static void main(String[] args) {
HTTPSServer server = new HTTPSServer();
server.run();
}

HTTPSServer() {
}

HTTPSServer(int port) {
this.port = port;
}

// Create the and initialize the SSLContext
private SSLContext createSSLContext() {
try {

//Returns keystore object in definied type, here jks
KeyStore keyStore = KeyStore.getInstance("JKS");
//loads the keystore from givin input stream, and the password to unclock jks
keyStore.load(new FileInputStream("x509-ca.jks"), "password".toCharArray());

// Create key manager
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, "password".toCharArray());
KeyManager[] km = keyManagerFactory.getKeyManagers();

// Create trust manager
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
trustManagerFactory.init(keyStore);
TrustManager[] tm = trustManagerFactory.getTrustManagers();

// opens a secure socket with definied protocol
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");

//System.out.println(keyStore.getCertificate("root").getPublicKey());
//System.out.println(keyStore.isKeyEntry("root"));
sslContext.init(km, tm, null);

return sslContext;
} catch (Exception ex) {
ex.printStackTrace();
}

return null;
}

// Start to run the server
public void run() {
SSLContext sslContext = this.createSSLContext();

try {
// Create server socket factory
SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();

// Create server socket
SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(this.port);

System.out.println("SSL server started");
while (!isServerDone) {
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();

// Start the server thread
new ServerThread(sslSocket).start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}

// Thread handling the socket from client
static class ServerThread extends Thread {

private SSLSocket sslSocket = null;

ServerThread(SSLSocket sslSocket) {
this.sslSocket = sslSocket;
}

public void run() {
sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
//System.out.println("HIER: " + sslSocket.getHandshakeSession());

//Klappt nicht, auch nicht, wenn der Client diese Zeile ebenfalls besitzt
//sslSocket.setEnabledCipherSuites(new String[]{"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"});
try {
// Start handshake
sslSocket.startHandshake();

// Get session after the connection is established
SSLSession sslSession = sslSocket.getSession();
System.out.println(sslSession.getPeerHost());
System.out.println(sslSession.getLocalCertificates());
System.out.println("\tProtocol : " + sslSession.getProtocol());
System.out.println("\tCipher suite : " + sslSession.getCipherSuite());
System.out.println("\tSession context : " + sslSession.getSessionContext());
//System.out.println("\tPeer pricipal of peer : " + sslSession.getPeerPrincipal());

// Start handling application content
InputStream inputStream = sslSocket.getInputStream();
OutputStream outputStream = sslSocket.getOutputStream();

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(outputStream));

String line = null;

String[] suites = sslSocket.getSupportedCipherSuites();
for (int i = 0; i < suites.length; i++) {
//System.out.println(suites[i]);
//System.out.println(sslSession.getCipherSuite());
}

while ((line = bufferedReader.readLine()) != null) {
System.out.println("Inut : " + line);

if (line.trim().isEmpty()) {
break;
}
}

// Write data
printWriter.print("HTTP/1.1 200\r\n");
printWriter.flush();

sslSocket.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}

这是我的输出:

SSL server started
127.0.0.1
null
Protocol : TLSv1.2
Cipher suite : TLS_DH_anon_WITH_AES_128_GCM_SHA256
Session context : sun.security.ssl.SSLSessionContextImpl@781df1a4

我想知道,为什么会这样

 System.out.println(sslSession.getLocalCertificates());

打印出“null”?

非常感谢你,米拉

最佳答案

来自documentation :

Certificate[] getLocalCertificates()

Returns the certificate(s) that were sent to the peer during handshaking.

Note: This method is useful only when using certificate-based cipher suites.

When multiple certificates are available for use in a handshake, the implementation chooses what it considers the "best" certificate chain available, and transmits that to the other side. This method allows the caller to know which certificate chain was actually used.

Returns:

an ordered array of certificates, with the local certificate first followed by any certificate authorities. If no certificates were sent, then null is returned.

我们关心的部分是“返回握手期间发送给对等方的证书”,以及“此方法仅在使用基于证书的密码套件时有用。”。

鉴于它返回 null,我们可以假设您没有向客户端发送任何证书。但它也是 HTTPS,那有什么用呢?嗯,看起来您正在使用 TLS_DH_anon_WITH_AES_128_GCM_SHA256,顾名思义,匿名。根据 OpenSSL Wiki :

Anonymous Diffie-Hellman uses Diffie-Hellman, but without authentication. Because the keys used in the exchange are not authenticated, the protocol is susceptible to Man-in-the-Middle attacks. Note: if you use this scheme, a call to SSL_get_peer_certificate will return NULL because you have selected an anonymous protocol. This is the only time SSL_get_peer_certificate is allowed to return NULL under normal circumstances.

虽然这适用于 OpenSSL,但它在 Java 中似乎是相同的——也就是说,您没有使用基于证书的密码。对 TLS 有更多了解的人需要介入,但看起来 AES key 生成的,并且它们被发送给客户端,但客户端无法保证这些 key 来自您,而通常您会生成 key ,然后使用 RSA key 对这些 key 进行签名/加密(并非 100% 确定)以证明它们来自您。

要解决此问题,我相信您需要选择不同的密码套件,例如TLS_RSA_WITH_AES_128_GCM_SHA256。我不是 100% 确定如何您会这样做,但这似乎是解决方案。

关于java - 在 Java 中创建 HTTPS 服务器 - 本地证书在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38498781/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com