我跟隨這些執行緒和其他類似的例子:
- 如何在 Java 中通過 TLS v.1.2 創建安全的 TCP 連接
- 在 Java 客戶端中接受服務器的自簽名 ssl 證書
我已經為客戶端和服務器使用任何本地生成的自簽名證書實作了一個客戶端/服務器簡單的 Java 程式。順便說一句,我看到他們協商 TLS 1.3 而不是 1.2。那挺好的。
但我看到他們只使用服務器證書(客戶端配置為接受任何,好的)。我希望他們也要求客戶端進行身份驗證。并允許客戶端證書是任何自簽名的,而不是由任何 CA 簽名的。所以我嘗試了服務器使用sslServerSocket.setNeedClientAuth(true)或訪問客戶端證書資訊。然后我得到這樣的錯誤:
Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at java.base/sun.security.ssl.SSLSessionImpl.getPeerPrincipal(SSLSessionImpl.java:1122)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
所以我一直在使用這些工具來測驗我的實作的雙方:
ncat --sslncat --ssl --listenopenssl s_clientopenssl s_server
我的結論是我的客戶端運行良好,需要時在其他服務器上進行身份驗證。但是我的服務器需要向客戶端提供基本 CA(我不想要這個) ,或者只接受沒有客戶端身份驗證的任何客戶端(這就是我現在擁有的,這不是我的目標)。
我希望我的服務器需要客戶端證書并接受任何證書。我怎樣才能做到這一點?謝謝!
動機:我想使用 Java 而不是 Go 來實作一些Syncthing有據可查的特性。他們在連接的兩端使用自定義證書身份驗證。
uj5u.com熱心網友回復:
所以現在它正在作業。
首先,我只在客戶端強制握手。似乎沒問題,但在服務器端添加它會產生更好的錯誤訊息。
所以我在接受連接后在服務器端添加了最后一行(Groovy 代碼):
ss.setNeedClientAuth(true)
SSLSocket socket = ss.accept() as SSLSocket
socket.startHandshake()
然后,當客戶到達時,我得到了一個更指示性的錯誤:
Exception in thread "main" javax.net.ssl.SSLException: Cannot read the array length because "caCerts" is null
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:133)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:371)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:309)
at java.base/sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1702)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:465)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:421)
at javax.net.ssl.SSLSocket$startHandshake.call(Unknown Source)
所以過了一會兒,我在接受來自任何證書的連接的代碼中發現了一些可疑的東西:
def x509TrustAllCerts = new X509TrustManager() {
X509Certificate[] getAcceptedIssuers() {
return null // <--- SUSPICIOUS!!
}
void checkClientTrusted(X509Certificate[] certs, String authType) { }
void checkServerTrusted(X509Certificate[] certs, String authType) { }
}
TrustManager[] trustAllCerts = new TrustManager[] { x509TrustAllCerts }
所以我做了最簡單的修復更改null為空陣列:
def x509TrustAllCerts = new X509TrustManager() {
X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0] // <-- FIX
}
void checkClientTrusted(X509Certificate[] certs, String authType) { }
void checkServerTrusted(X509Certificate[] certs, String authType) { }
}
TrustManager[] trustAllCerts = new TrustManager[] { x509TrustAllCerts }
現在它正在按照我的預期作業。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/494054.html
