自建CA中心,为公司不同应用签发证书

制作过程使用
WINDOWS 7, JDK 1.7

首先在生成2个目录,一个存放CA中心根证书,另一个存放CA签发的应用证书
D:\CA
D:\CA\appserver

进入D;\CA目录

1. 生成 CA 根证书库
keytool -genkey -alias CA -keypass CA123 -keyalg RSA -validity 36500 -keystore .\CA.keystore -storepass CASTORE123 -dname "CN=My CA, C=CN"

注意,dname可以根据需要,自己填写其他项。

2. 导出 CA 根证书(实际上是个自签名过程,不过低版本的keytool -selfcert命令已经废弃了)
keytool -exportcert -alias CA -file CA.cer -keystore CA.keystore -storepass CASTORE123


进入D:\CA\appserver目录

3. 生成appserver证书库
keytool -genkey -alias appserver -keypass APPSERVER123 -keyalg RSA -validity 3650 -keystore .\appserver.keystore -storepass APPSERVERSTORE123 -dname "CN=app.myname.com, OU=My company name, O=My company name, C=CN"

4. 生成请求CA签名的文件
keytool -certreq -alias appserver -keystore .\appserver.keystore -storepass APPSERVERSTORE123 -file appserver.certreq

5. 用CA根证书为appserver证书签名
keytool -gencert -infile appserver.certreq -outfile appserver.cer -validity 3650 -alias CA -keypass CA123 -keystore ..\CA.keystore -storepass CASTORE123

6. 把CA根证书导入appserver证书库
keytool -importcert -alias CA -file ../CA.cer -keystore appserver.keystore -storepass APPSERVERSTORE123

提示:是否信任此证书? [否]: 
键盘输入:y
提示:证书已添加到密钥库中


7. 导入CA签发的证书到appserver证书库(实际上是更新证书,在更新被签发证书之前,一定要先将相应的 CA 证书,导入进 appserver证书库 文件)
keytool -importcert -alias appserver -file appserver.cer -keystore appserver.keystore -storepass APPSERVERSTORE123

再把得到的appserver.keystore配置到tomcat里,这样,在浏览器上上浏览tomcat的应用,就可以看到证书颁发者是:My CA,而使用者是:app.myname.com。并且,两个证书也形成了一个证书链了(这个可以在证书路径中查看到),看上去像模像样些了。


在android客户端的开发中,需要用到BKS类型的证书库(上面的是JKS类型证书库),那上面的tomcat部署的服务,如何在android中访问呢?

假设上面的已经执行完成了,得到了应用证书appserver.cer,那么接下来这样做。

1. 下载必须的bcprov-jdk15on-146.jar,并放到D:\CA\appserver目录下,下载地址 http://www.bouncycastle.org/download/bcprov-jdk15on-146.jar,注意版本号。

2. 进入D:\CA\appserver目录,输入如下命令:
keytool -import -alias appserver -file .\appserver.cer -keystore .\appserver.bks -storetype BKS -storepass bks123  -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath .\bcprov-jdk15on-146.jar

这样就得到BKS证书了,交给android开发同学即可。

android开发环境:
android studio 1.5
Android API 23
OkHttp 3.0.1

把得到的appserver.bks,放入:src/assets路径下,当然放在其他路径比如下也可以,只要能方便读到即可。

示例代码如下:
引用

private void byOkHttps(String url, String json) throws Exception {

//读取bks证书库
    KeyStore keyStore = readKeyStore();
   
    //初始化SSLContext
    SSLContext sslContext = SSLContext.getInstance("TLS");
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(keyStore);
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    keyManagerFactory.init(keyStore, "bks123".toCharArray());
    sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());

//初始化OkHttpClient
    OkHttpClient client= new OkHttpClient.Builder()
            .sslSocketFactory(sslContext.getSocketFactory())
            .build();

//jons请求数据
RequestBody body = RequestBody.create(JSON, json);

    Request request = new Request.Builder()
            .url(url)
            .post(body)
            .headers(getHeaders())
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            //NOT UI Thread
            if (response.isSuccessful()) {
                Log.d("RESPONSE:", response.body().string());
            } else {
                throw new IOException("Unexpected code " + response);
            }
        }
    });
}


private KeyStore readKeyStore() throws Exception {
    KeyStore ks = KeyStore.getInstance("BKS");
    char[] password = "bks123".toCharArray();

    java.io.InputStream is = null;
    try {
        is = getAssets().open("appserver.bks");
        ks.load(is, password);
    } finally {
        if (is != null) {
            is.close();
        }
    }
    return ks;
}



后记:

1. 在生成BKS证书库时,开始我是下载的bcprov-jdk15on-154.jar,也可以用,但是需要在android开发中做些修改,

1. 要把bcprov-jdk15on-154.jar引入到android项目中
2. 修改上面的readKeyStore代码
private KeyStore readKeyStore() throws Exception {
    KeyStore ks = KeyStore.getInstance("BKS", new BouncyCastleProvider());
    char[] password = "bks123".toCharArray();

    java.io.InputStream is = null;
    try {
        is = getAssets().open("appserver.bks");
        ks.load(is, password);
    } finally {
        if (is != null) {
            is.close();
        }
    }
    return ks;
}


2. 当用HTTPS访问部署有证书的应用服务器时,有时候是用IP来访问的,比如访问内网测试服务器时,一般都不会用域名,而是直接用IP来访问,这时候可能会出现类似hostname wrong的错误,这其实是我们的证书有问题造成的,解决方法是在最早的生成证书/签发证书的步骤中的:

3. 生成appserver证书库
keytool -genkey,这个命令加上:-ext san=ip:192.168.1.123
5. 用CA根证书为appserver证书签名
keytool -gencert,这个命令加上:-ext san=ip:192.168.1.123

不要用网上介绍的所谓信任所有域的方法,这样不安全。

猜你喜欢

转载自bglmmz.iteye.com/blog/2278198
今日推荐