如何创建包含客户端证书链的 BKS(BouncyCastle)格式的 Java Keystore [英] How to create a BKS (BouncyCastle) format Java Keystore that contains a client certificate chain

查看:34
本文介绍了如何创建包含客户端证书链的 BKS(BouncyCastle)格式的 Java Keystore的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个需要 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆