如何创建包含客户端证书链的 BKS(BouncyCastle)格式的 Java Keystore [英] How to create a BKS (BouncyCastle) format Java Keystore that contains a client certificate chain
问题描述
我正在编写一个需要 SSL 客户端身份验证的 Android 应用程序.我知道如何为桌面 Java 应用程序创建 JKS 密钥库,但 Android 仅支持 BKS 格式.我尝试创建密钥库的每一种方式都会导致以下错误:处理异常:javax.net.ssl.SSLHandshakeException:空证书链
I'm writing an Android app that requires SSL client authentication. I know how to create a JKS keystore for a desktop Java application, but Android only supports the BKS format. Every way I've tried to create the keystore results in the following error:
handling exception: javax.net.ssl.SSLHandshakeException: null cert chain
所以看起来客户端永远不会发送正确的证书链,可能是因为我没有正确创建密钥库.我无法像在桌面上那样启用 SSL 调试,所以这比应该的困难得多.
So it looks like the client is never sending a proper certificate chain, probably because I'm not creating the keystore properly. I'm unable to enable SSL debugging like I can on the desktop, so that's making this much more difficult than it should be.
以下是用于创建 BKS truststore 的命令供参考:keytool -importcert -v -trustcacerts -file "cacert.pem" -alias ca -keystore "mySrvTruststore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "bcprov-jdk16-145.jar" -storetype BKS -storepass testtest
For reference the following is the command that IS working to create a BKS truststore:
keytool -importcert -v -trustcacerts -file "cacert.pem" -alias ca -keystore "mySrvTruststore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "bcprov-jdk16-145.jar" -storetype BKS -storepass testtest
这是我尝试过的命令,它不能用于创建 BKS 客户端 keystore:
Here is the command I've tried that is NOT working to create a BKS client keystore:
cat clientkey.pem clientcert.pem cacert.pem > client.pem
keytool -import -v -file <(openssl x509 -in client.pem) -alias client -keystore "clientkeystore" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "bcprov-jdk16-145.jar" -storetype BKS -storepass testtest
推荐答案
我遵循的详细分步说明
- 从以下位置下载 bouncycastle JARhttp://repo2.maven.org/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.46/bcprov-ext-jdk15on-1.46.jar或从doc"文件夹中获取.
- 使用以下方法之一为 PC 配置 BouncyCastle.
- 静态添加 BC 提供程序(推荐)
- 将 bcprov-ext-jdk15on-1.46.jar 复制到每个
- D: oolsjdk1.5.0_09jrelibext(JDK(捆绑的 JRE)
- D: oolsjre1.5.0_09libext (JRE)
- C:(在环境变量中使用的位置)
- Download bouncycastle JAR from http://repo2.maven.org/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.46/bcprov-ext-jdk15on-1.46.jar or take it from the "doc" folder.
- Configure BouncyCastle for PC using one of the below methods.
- Adding the BC Provider Statically (Recommended)
- Copy the bcprov-ext-jdk15on-1.46.jar to each
- D: oolsjdk1.5.0_09jrelibext (JDK (bundled JRE)
- D: oolsjre1.5.0_09libext (JRE)
- C: (location to be used in env variable)
- D: oolsjdk1.5.0_09jrelibsecurity
- D: oolsjre1.5.0_09libsecurity
- 并添加以下条目
- security.provider.7=org.bouncycastle.jce.provider.BouncyCastleProvider
- CLASSPATH=%CLASSPATH%;c:cprov-ext-jdk15on-1.46.jar
- Security.addProvider(new BouncyCastleProvider());
- 运行以下命令
- keytool -genkey -alias myproject -keystore C:/myproject.keystore -storepass myproject -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
- keytool -list -keystore C:myproject.keystore -storetype BKS
为 TOMCAT 配置 BouncyCastle
Configure BouncyCastle for TOMCAT
打开 D: oolsapache-tomcat-6.0.35confserver.xml 并添加以下条目
Open D: oolsapache-tomcat-6.0.35confserver.xml and add the following entry
- <连接器端口=8443"keystorePass="我的项目"别名=我的项目"keystore="c:/myproject.keystore"密钥库类型 =BKS"SSLEnabled="真"客户端验证=假"协议="HTTP/1.1"方案=https"安全=真"sslProtocol="TLS"sslImplementationName="org.bouncycastle.jce.provider.BouncyCastleProvider"/>
在这些更改后重新启动服务器.
Restart the server after these changes.
- 无需配置,因为 Android 在提供的android.jar"中支持 Bouncy Castle 1.46 版.
- 只需实现您的 HTTP 客户端版本(MyHttpClient.java 可以在下面找到)并在代码中设置以下内容
- SSLSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- javax.net.ssl.SSLException:证书中的主机名不匹配:<192.168.104.66> !=
- SSLSocketFactory.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
MyHttpClient.java
package com.arisglobal.aglite.network; import java.io.InputStream; import java.security.KeyStore; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.SingleClientConnManager; import com.arisglobal.aglite.activity.R; import android.content.Context; public class MyHttpClient extends DefaultHttpClient { final Context context; public MyHttpClient(Context context) { this.context = context; } @Override protected ClientConnectionManager createClientConnectionManager() { SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); // Register for port 443 our SSLSocketFactory with our keystore to the ConnectionManager registry.register(new Scheme("https", newSslSocketFactory(), 443)); return new SingleClientConnManager(getParams(), registry); } private SSLSocketFactory newSslSocketFactory() { try { // Get an instance of the Bouncy Castle KeyStore format KeyStore trusted = KeyStore.getInstance("BKS"); // Get the raw resource, which contains the keystore with your trusted certificates (root and any intermediate certs) InputStream in = context.getResources().openRawResource(R.raw.aglite); try { // Initialize the keystore with the provided trusted certificates. // Also provide the password of the keystore trusted.load(in, "aglite".toCharArray()); } finally { in.close(); } // Pass the keystore to the SSLSocketFactory. The factory is responsible for the verification of the server certificate. SSLSocketFactory sf = new SSLSocketFactory(trusted); // Hostname verification from certificate // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506 sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); return sf; } catch (Exception e) { throw new AssertionError(e); } } }
如何在您的 Activity 类中调用上述代码:
How to invoke the above code in your Activity class:
DefaultHttpClient client = new MyHttpClient(getApplicationContext()); HttpResponse response = client.execute(...);
这篇关于如何创建包含客户端证书链的 BKS(BouncyCastle)格式的 Java Keystore的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- Copy the bcprov-ext-jdk15on-1.46.jar to each
- Adding the BC Provider Statically (Recommended)
- 将 bcprov-ext-jdk15on-1.46.jar 复制到每个
- 静态添加 BC 提供程序(推荐)