如何创建一个BKS(BouncyCastle的)格式的Java密钥库,其中包含客户端证书链密钥、创建一个、客户端、其中包含

由网友(凹+凸=日)分享简介:我正在写一个Android应用程序,需要SSL客户端身份验证。我知道如何创建一个JKS密钥库为桌面Java应用程序,而Android仅支持BKS格式。每一个方式,我一直在努力,创建密钥库导致以下错误:处理异常:javax.net.ssl​​.SSLHandshakeException:空证书链 因此​​,它看起来就像...

我正在写一个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
 
软帝学院Java语言基础之构建Java开发环境 Day01

解决方案

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

下载BouncyCastle的从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中,添加以下项

<连接器 端口=8443 keystorePass =MyProject的 别名为MyProject的 密钥库=C:/myproject.keystore keystoreType =BKS SSLEnabled =真 clientAuth =假 协议=HTTP / 1.1 计划=htt​​ps开头 安全=真 sslProtocol =TLS sslImplementationName =org.bouncycastle.jce.provider.BouncyCastleProvider/>

这些更改后重新启动服务器。

配置BouncyCastle的Andr​​oid版客户端 在没有必要,因为Android的配置支持充气城堡1.46版本在​​内部的规定的android.jar。 只实现你的HTTP客户端版本(MyHttpClient.java可以在下面找到),并设置在code以下 SSLSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 如果你不这样做,它给出了一个例外,如下 javax.net.ssl​​.SSLException:主机名的证书不匹配:< 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:toolsjdk1.5.0_09jrelibext (JDK (bundled JRE) D:toolsjre1.5.0_09libext (JRE) C: (location to be used in env variable) Modify the java.security file under D:toolsjdk1.5.0_09jrelibsecurity D:toolsjre1.5.0_09libsecurity 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:toolsapache-tomcat-6.0.35confserver.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(...);

阅读全文

相关推荐

最新文章