美文网首页程序员
使用keytool、portecle完成ssl双向认证证书生成,

使用keytool、portecle完成ssl双向认证证书生成,

作者: 旻璿 | 来源:发表于2020-11-02 11:34 被阅读0次

    Springboot版本:2.1.9RELEASE
    portecle下载地址:链接: https://pan.baidu.com/s/1UL6SX1utsZg-Vc6QYtyK9A 密码: 0tmg

    脚本如下,密码123456需自行修改,dname需自行修改,alias也可根据需要自行修改:

    #1、生成服务器证书库
    keytool -validity 3650 -genkeypair -v -alias server -keyalg RSA  -keystore server.keystore -dname "CN=127.0.0.1,OU=V,O=V,L=FZ,ST=FJ,c=CN" -storepass 123456 -keypass 123456
    #2、生成客户端证书库
    keytool -validity 3650 -genkeypair -v -alias client -keyalg RSA  -keystore client.keystore -dname "CN=client,OU=V,O=V,L=FZ,ST=FJ,c=CN" -storepass 123456 -keypass 123456
    #3、从客户端证书库中导出客户端证书
    keytool -export -v -alias client -keystore client.keystore  -storepass 123456 -rfc -file client.cer
    #4、从服务器证书库中导出服务器证书
    keytool -export -v -alias server -keystore server.keystore -storepass 123456  -rfc -file server.cer
    #5、生成客户端信任证书库(由服务端证书生成的证书库)
    keytool -import -v -alias server -file server.cer -keystore client.truststore -storepass 123456
    #6、将客户端证书导入到服务器证书库(使得服务器信任客户端证书)
    keytool -import -v -alias client -file client.cer -keystore server.keystore -storepass 123456
    #7、生成服务端信任证书库(由客户端证书生成的证书库)
    keytool -import -v -alias client -file client.cer -keystore server.truststore -storepass 123456
    #8、将服务端证书导入到客户端证书库(使得客户端信任服务端证书)
    keytool -import -v -alias server -file server.cer -keystore client.keystore -storepass 123456
    #9、查看服务端证书库中的全部证书
    keytool -list -keystore server.keystore -storepass 123456
    #10、查看客户端证书库中的全部证书
    keytool -list -keystore server.keystore -storepass 123456
    
    # 以下Springboot使用
    keytool -importkeystore -srckeystore server.keystore -destkeystore server.p12 -srcalias server -destalias server -srcstoretype jks -deststoretype pkcs12 -noprompt
    
    keytool -importkeystore -srckeystore server.truststore -destkeystore server_truststore.p12 -srcalias client -destalias server_truststore -srcstoretype jks -deststoretype pkcs12 -noprompt
    

    Springboot里application.yml配置如下(节选)

    server:
      port: 8443
      http:
        port: 8082
      ssl:
        key-store: classpath:server.p12
        key-alias: server
        key-store-type: PKCS12
        key-store-password: 123456
    
        trust-store: classpath:server_truststore.p12
        trust-store-password: 123456
        client-auth: need
        trust-store-type: PKCS12
      ...
    

    需要在WebConfig里增加一些代码支持http访问

        // 同时支持http、https ---start---
        @Value("${server.http.port}")
        private int httpPort;
    
        @Bean
        public ServletWebServerFactory servletContainer() {
            TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
            tomcat.addAdditionalTomcatConnectors(createStandardConnector()); // 添加http
            return tomcat;
        }
    
        private Connector createStandardConnector() {
            Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
            connector.setPort(httpPort);
            return connector;
        }
        // 同时支持http、https ---end---
    
    # 以下nginx用
    openssl pkcs12 -clcerts -nokeys -out client_cert.pem -in client.p12
    openssl pkcs12 -nocerts -out key.pem -in client.p12
    # 处理导出的私钥,将pkcs#8格式的密钥文件转换为pkcs#1格式,这样apache/nginx才能识别。如果使用pkcs#8格式的密钥,apache启动的时候会报(missing or encrypted private key?)。另外如果是nginx,使用pkcs#8格式的密钥重启的时候要输入密码,报错cannot load certificate key "/etc/nginx/cert/client_key.pem": PEM_read_bio_PrivateKey() failed (SSL: error:0906406D:PEM routines:PEM_def_callback:problems getting password error:0907B068:PEM routines:PEM_READ_BIO_PRIVATEKEY:bad password read)而导出成pkcs#1格式则不需要。
    openssl rsa -in key.pem -out client_key.pem
    cat client_cert.pem key_new.pem >client.pem
    
    # 以下供android及本机浏览器使用,android通过portecle生成bks文件
    keytool -importkeystore -srckeystore client.keystore -destkeystore client.p12 -srcalias client -destalias client -srcstoretype jks -deststoretype pkcs12 -noprompt
    

    生成的client.p12,可双击打开导入系统,以便能在浏览器测试访问https。
    运行protecle.jar--》打开文件选中client.p12,选择tools-->change keystore type-->选择BKS,最后关闭保存为client.bks
    运行protecle.jar--》打开文件选中client.truststore,选择tools-->change keystore type-->选择BKS,最后关闭保存为ca.bks
    安卓需要在build.gradle里增加:

    //retrofit
        implementation "com.squareup.retrofit2:retrofit:2.3.0"
        implementation "com.squareup.retrofit2:converter-scalars:2.3.0"
        implementation "com.squareup.retrofit2:converter-gson:2.3.0"
        implementation "com.squareup.okhttp3:logging-interceptor:3.8.1"
    

    然后在Android Studio的Android视图下,将client.bks和ca.bks导入assets里。
    代码如下,使用Retrofit2,

        public interface GetAppList {
            @GET("getAppList")
            Call<AppListBean> get();
        }
    
                //创建日志拦截器,用于日志打印
                HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
                interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                //创建okhttp
                OkHttpClient httpClient = new OkHttpClient().newBuilder()
                        .addInterceptor(interceptor)
                        .sslSocketFactory(SSLHelper.getSSLCertifcation(this), new HttpsUtil.UnSafeTrustManager())
                        .hostnameVerifier(new HttpsUtil.UnSafeHostnameVerifier())//由于还没有域名,此处设置忽略掉域名校验
                        .build();
                //创建retrofit
                String baseUrl = "https://10.0.2.2:8443/";
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(baseUrl)
                        .client(httpClient)
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
    
                // 创建 网络请求接口 的实例
                GetAppList request = retrofit.create(GetAppList.class);
                //创建请求,传入参数
                Call<AppListBean> call = request.get();
                //异步请求
                call.enqueue(new Callback<AppListBean>() {
                    @Override
                    public void onResponse(Call<AppListBean> call, Response<AppListBean> response) {
                        System.out.println("response.toString():" + response.toString());
                    }
                    @Override
                    public void onFailure(Call<AppListBean> call, Throwable t) {
                        t.printStackTrace();
                    }
                });
    

    参考了这些文章,感谢!
    https://www.jianshu.com/p/661c0459b375
    https://blog.csdn.net/anshi4203351518/article/details/101966682
    https://www.cnblogs.com/nhdlb/archive/2004/01/13/12258225.html
    https://blog.csdn.net/huweijian5/article/details/79365439
    https://blog.csdn.net/mingjie1212/article/details/51908174
    https://blog.csdn.net/lhc_makefunny/article/details/89528517
    https://blog.csdn.net/qq_39403545/article/details/88832473
    https://blog.csdn.net/weixin_41917987/article/details/80988197

    相关文章

      网友评论

        本文标题:使用keytool、portecle完成ssl双向认证证书生成,

        本文链接:https://www.haomeiwen.com/subject/ffapvktx.html