gpt4 book ai didi

java - 具有在运行时导入的自签名证书的 SSL 客户端-服务器在握手时失败

转载 作者:行者123 更新时间:2023-11-30 10:50:49 27 4
gpt4 key购买 nike

编辑:我修复了代码。请参阅我的答案以获取解释。

我正在尝试创建一个使用 SSLSocket 将数据发送到服务器的 Android 应用程序。该证书是自签名的,我正在尝试按照我在其他线程上找到的说明使用 SSLContext 将其添加到服务器 KeyManager 和客户端 TrustManager 中。

然而,当我尝试发送数据时,客户端和服务器都返回异常。

请记住,这是我第一次处理 SSL 连接。我使用 Java key 工具创建并签署了“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);
}
}

最佳答案

看来问题出在我使用的证书上。我尝试导入使用 keytool 创建的“*.crt”文件,然后以编程方式将其添加到 keystore 。尽管我仍然不确定为什么它以前不起作用,但我通过跳过证书导入并直接导入 keystore (Windows 服务器上的“keystore.jks”和 Android 客户端上的“keystore.bks”)来修复此问题。

这就是我创建 keystore.jks 的方式:

keytool -genkeypair -alias serveralias -keyalg RSA -keysize 4096 -keystore keystore.jks 
-keypass changeit -storepass changeit -validity 10950

由于 Android 不支持 JKS,因此我复制了 keystore 并将扩展名重命名为 .bks。然后我使用一个名为“KeyStore Explorer”的程序将 keystore.bks 转换为“BKS-V1”格式,以便它可以在 Android 上运行。

我更新了原始问题以包含工作代码。

关于java - 具有在运行时导入的自签名证书的 SSL 客户端-服务器在握手时失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34931146/

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