編輯:我修復了代碼。請參閱我的解答。帶有在運行時導入的自簽名證書的SSL客戶端服務器在握手時失敗
我想創建一個android應用程序,使用SSLSocket將數據發送到服務器。證書是自簽名的,我試圖使用SSLContext將其添加到服務器KeyManager和客戶端TrustManager中,按照我在其他線程上找到的說明進行操作。
但是,當我嘗試發送數據時,客戶端和服務器都會返回異常。
請記住,這是我第一次處理SSL連接。我使用Java keytool創建並創建了'server.crt'證書。
客戶例外
javax.net.ssl.SSLHandshakeException: Handshake failed
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:390)
at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:623)
at com.android.org.conscrypt.OpenSSLSocketImpl.getOutputStream(OpenSSLSocketImpl.java:609)
...
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x73c6ac00: Failure in SSL library, usually a protocol error
服務器異常
Exception in thread "main" javax.net.ssl.SSLHandshakeException: no cipher suites in common
...
at java.io.InputStream.read(InputStream.java:101)
固定的客戶端代碼(運行在Android上)
AssetManager assetManager = getAssets();
InputStream keyStoreInputStream = assetManager.open("keystore.bks");
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(null,null);
keyStore.load(keyStoreInputStream, KEY_PASSWORD);
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
SSLSocketFactory sslsocketfactory = sslContext.getSocketFactory();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("192.168.1.212", 4444);
InputStream inputStream = assetManager.open(MainActivity.FILE_NAME);
OutputStream outputStream = sslsocket.getOutputStream();
int count;
byte[] buffer = new byte[12 * 1024];
while ((count = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, count);
}
固定服務器代碼(在Windows上運行)
FileInputStream keyStoreInputStream = new FileInputStream(KEYSTORE_PATH);
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, null);
keyStore.load(keyStoreInputStream, KEY_PASSWORD);
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, KEY_PASSWORD);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
SSLServerSocket sslServerSocket =
(SSLServerSocket) sslServerSocketFactory.createServerSocket(4444);
while (true) {
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
InputStream inputStream = sslSocket.getInputStream();
FileOutputStream outputStream = new FileOutputStream(OUTPUT_PATH,false);
byte[] bytes = new byte[12 * 1024];
int count;
while ((count = inputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, count);
}
}
我已經檢查getEnabledCipherSuites()在客戶端和服務器上,並確認確實有一些常見的密碼套件。我也嘗試setEnabledCipherSuites()並選擇了客戶端和服務器都有共同的密碼套件。我也有同樣的例外。 – HomeIsWhereThePcIs