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

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

问题描述

我正在写一个Android应用程序,需要SSL客户端身份验证。我知道如何创建一个JKS密钥库为桌面Java应用程序,而Android仅支持BKS格式。每一个方式,我一直在努力,创建密钥库导致以下错误:
处理异常:javax.net.ssl​​.SSLHandshakeException:空证书链

因此​​,它看起来就像客户端是永远不会发送一个适当的证书链,可能是因为我没有创建密钥库正常。我无法启用SSL调试像我一样的dekstop,所以这使得这个更加困难比它应该是。

有关参考下面是努力创造一个BKS 信任库命令:
密钥工具-importcert -v -trustcacerts -filecacert.pem-alias ca的-keystoremySrvTruststore.bks-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpathbcprov-jdk16-145。罐子-storetype BKS -storepass testtest


下面是命令我试过,是不是努力创造一个BKS客户端密钥库

 猫clientkey.pem clientcert.pem cacert.pem> client.pem

密钥工具-import -v -file≤(OpenSSL的X​​509 -in client.pem)-alias客户-keystoreclientkeystore-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpathbcprov-jdk16-145.jar-storetype BKS -storepass testtest
 

解决方案

详细的一步一步的指示,我也跟着来实现这个

  • 下载BouncyCastle的从JAR         <一href="http://repo2.maven.org/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.46/bcprov-ext-jdk15on-1.46.jar">http://repo2.maven.org/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.46/bcprov-ext-jdk15on-1.46.jar 或者把它从文档文件夹中。
  • 配置BouncyCastle的个人电脑使用的下述方法之一。
    • 添加BC提供静态(推荐)
      • 的bcprov-EXT-jdk15on-1.46.jar复制到每个
        • D:\工具\ jdk1.5.0_09 \ JRE \ lib中\分机(JDK(捆绑的JRE)
        • D:\工具\ jre1.5.0_09 \ lib中\分机(JRE)
        • C:(在ENV变量使用位置)\
      • 修改下的java.security文件
        • D:\工具\ jdk1.5.0_09 \ JRE \ lib \ security中
        • D:\工具\ jre1.5.0_09 \ lib \ security中
        • ,并添加以下条目
          • security.provider.7 = org.bouncycastle.jce.provider.BouncyCastleProvider
      • 添加以下环境变量在用户变量部分
        • 在CLASSPATH =%CLASSPATH%; C:\ bcprov-EXT-jdk15on-1.46.jar
    • 添加bcprov-EXT-jdk15on-1.46.jar到项目的CLASSPATH,并添加下面一行在code
      • 在Security.addProvider(新BouncyCastleProvider());
  • 生成使用充气城堡的密钥库
    • 运行以下命令
      • 的keytool -genkey -alias MyProject的-keystore C:/myproject.keystore -storepass MyProject的-storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
    • 此生成文件:C:\ myproject.keystore
    • 运行下面的命令来检查它是否正确生成与否
      • 的keytool -list -keystore C:\ myproject.keystore -storetype BKS
  • 配置BouncyCastle的为Tomcat

    • 打开D:\工具\ Apache的Tomcat的6.0.35 \的conf \ server.xml中,添加以下项

      • &LT;连接器 端口=8443 keystorePass =MyProject的 别名为MyProject的 密钥库=C:/myproject.keystore keystoreType =BKS SSLEnabled =真 clientAuth =假 协议=HTTP / 1.1 计划=htt​​ps开头 安全=真 sslProtocol =TLS sslImplementationName =org.bouncycastle.jce.provider.BouncyCastleProvider/&GT;
    • 这些更改后重新启动服务器。

  • 配置BouncyCastle的Andr​​oid版客户端
    • 在没有必要,因为Android的配置支持充气城堡1.46版本在​​内部的规定的android.jar。
    • 只实现你的HTTP客户端版本(MyHttpClient.java可以在下面找到),并设置在code以下
      • SSLSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    • 如果你不这样做,它给出了一个例外,如下
      • javax.net.ssl​​.SSLException:主机名的证书不匹配:&LT; 192.168.104.66> =
    • 在生产模式下,改变上述code到
      • SSLSocketFactory.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);

MyHttpClient.java

 包com.arisglobal.aglite.network;

进口的java.io.InputStream;
进口java.security.KeyStore中;

进口org.apache.http.conn.ClientConnectionManager;
进口org.apache.http.conn.scheme.PlainSocketFactory;
进口org.apache.http.conn.scheme.Scheme;
进口org.apache.http.conn.scheme.SchemeRegistry;
进口org.apache.http.conn.ssl.SSLSocketFactory;
进口org.apache.http.impl.client.DefaultHttpClient;
进口org.apache.http.impl.conn.SingleClientConnManager;

进口com.arisglobal.aglite.activity.R;

进口android.content.Context;

公共类MyHttpClient扩展DefaultHttpClient {

    最后上下文的背景下;

    公共MyHttpClient(上下文的背景下){
        this.context =背景;
    }

    @覆盖
    保护ClientConnectionManager createClientConnectionManager(){
        SchemeRegistry注册表=新SchemeRegistry();

        registry.register(新计划(HTTP,PlainSocketFactory.getSocketFactory(),80));

        //注册端口443我们的SSLSocketFactory与我们的密钥存储到的ConnectionManager
        registry.register(新计划(https开头,newSslSocketFactory(),443));
        返回新SingleClientConnManager(getParams()方法,登记);
    }

    私人的SSLSocketFactory newSslSocketFactory(){
        尝试 {
            //获取充气城堡密钥库格式的一个实例
            密钥仓库中可信任= KeyStore.getInstance(BKS);

            //获取原料资源,其中包含密钥库与你信任的证书(根和任何中间证书)
            InputStream的时间= context.getResources()openRawResource(R.raw.aglite)。
            尝试 {
                //初始化与所提供的可信证书密钥存储。
                //还提供密钥库的密码
                trusted.load(在aglite.toCharArray());
            } 最后 {
                附寄();
            }

            //传递密钥库的SSLSocketFactory的。工厂负责服务器证书的验证。
            SSLSocketFactory的SF =新的SSLSocketFactory(信任);

            //主机名的证书验证
            // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            返回SF;
        }赶上(例外五){
            抛出新的AssertionError(E);
        }
    }
}
 

如何调用上面code。在您的活动类:

  DefaultHttpClient客户端=新MyHttpClient(getApplicationContext());
HTT presponse响应= client.execute(...);
 

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

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 dekstop, so that's making this much more difficult than it should be.

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


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

解决方案

Detailed Step by Step instructions I followed to achieve this

  • 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:\tools\jdk1.5.0_09\jre\lib\ext (JDK (bundled JRE)
        • D:\tools\jre1.5.0_09\lib\ext (JRE)
        • C:\ (location to be used in env variable)
      • Modify the java.security file under
        • D:\tools\jdk1.5.0_09\jre\lib\security
        • D:\tools\jre1.5.0_09\lib\security
        • and add the following entry
          • security.provider.7=org.bouncycastle.jce.provider.BouncyCastleProvider
      • Add the following environment variable in "User Variables" section
        • CLASSPATH=%CLASSPATH%;c:\bcprov-ext-jdk15on-1.46.jar
    • Add bcprov-ext-jdk15on-1.46.jar to CLASSPATH of your project and Add the following line in your code
      • Security.addProvider(new BouncyCastleProvider());
  • Generate the Keystore using Bouncy Castle
    • Run the following command
      • keytool -genkey -alias myproject -keystore C:/myproject.keystore -storepass myproject -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
    • This generates the file C:\myproject.keystore
    • Run the following command to check if it is properly generated or not
      • keytool -list -keystore C:\myproject.keystore -storetype BKS
  • Configure BouncyCastle for TOMCAT

    • Open D:\tools\apache-tomcat-6.0.35\conf\server.xml and add the following entry

      • <Connector port="8443" keystorePass="myproject" alias="myproject" keystore="c:/myproject.keystore" keystoreType="BKS" SSLEnabled="true" clientAuth="false" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS" sslImplementationName="org.bouncycastle.jce.provider.BouncyCastleProvider"/>
    • Restart the server after these changes.

  • Configure BouncyCastle for Android Client
    • No need to configure since Android supports Bouncy Castle Version 1.46 internally in the provided "android.jar".
    • Just implement your version of HTTP Client (MyHttpClient.java can be found below) and set the following in code
      • SSLSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    • If you don't do this, it gives an exception as below
      • javax.net.ssl.SSLException: hostname in certificate didn't match: <192.168.104.66> !=
    • In production mode, change the above code to
      • 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);
        }
    }
}

How to invoke the above code in your Activity class:

DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpResponse response = client.execute(...);

这篇关于如何创建一个BKS(BouncyCastle的)格式的Java密钥库,其中包含客户端证书链的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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