揭开银行U盾的秘密---签发CA证书:单向认证+双向认证(含java代码)

目录

开发前的环境准备:

客户端: win10+火狐浏览器/谷歌
服务端: COS7+Tomcat9
Tomcat9的文件路径: /usr/local/tomcat9

单向认证:

一、生成CA根证书

  1. 新建一个目录,用于存放证书

mkdir -p /srv/ftp/cas

  1. 生成CA密钥对

openssl genrsa -out /srv/ftp/cas/cakey.pem 2048 RSA

  1. 生成根证书签发申请

openssl req -new -key /srv/ftp/cas/cakey.pem -out /srv/ftp/cas/cacert.csr -subj /CN=cas.com

  1. 根证书签发

openssl x509 -req -days 3650 -sha1 -extensions v3_ca -signkey /srv/ftp/cas/cakey.pem -in /srv/ftp/cas/cacert.csr -out /srv/ftp/cas/ca.cer

二、生成服务器的证书

  1. 新建一个目录,用于存放证书

mkdir -p /srv/ftp/cas/server

  1. 生成服务器私钥

openssl genrsa -aes256 -out /srv/ftp/cas/server/server-key.pem 2048
设置密码:mldnjava

  1. 生成服务器证书签发申请

openssl req -new -key /srv/ftp/cas/server/server-key.pem -out /srv/ftp/cas/server/server.csr -subj /CN=cas.com

  1. 服务端证书签发

openssl x509 -req -days 3650 -sha1 -extensions v3_req -CA /srv/ftp/cas/ca.cer -CAkey /srv/ftp/cas/cakey.pem -CAserial /srv/ftp/cas/server/ca.srl -CAcreateserial -in /srv/ftp/cas/server/server.csr -out /srv/ftp/cas/server/server.cer

三、生成客户端的证书

  1. 新建一个目录,用于存放证书

mkdir -p /srv/ftp/cas/client

  1. 生成客户端私钥

openssl genrsa -aes256 -out /srv/ftp/cas/client/client-key.pem 2048
设置密码:mldnjava

  1. 生成客户端证书签发申请

openssl req -new -key /srv/ftp/cas/client/client-key.pem -out /srv/ftp/cas/client/client.csr -subj /CN=cas.com

  1. 客户端证书签发

openssl x509 -req -days 365 -sha1 -CA /srv/ftp/cas/ca.cer -CAkey /srv/ftp/cas/cakey.pem -CAserial /srv/ftp/cas/server/ca.srl -in /srv/ftp/cas/client/client.csr -out /srv/ftp/cas/client/client.cer

四、转换为java可以使用的证书

  1. 生成客户端证书

openssl pkcs12 -export -clcerts -name cas-client -inkey /srv/ftp/cas/client/client-key.pem -in /srv/ftp/cas/client/client.cer -out /srv/ftp/cas/client/client.p12

  1. 生成服务器端证书

openssl pkcs12 -export -clcerts -name cas-server -inkey /srv/ftp/cas/server/server-key.pem -in /srv/ftp/cas/server/server.cer -out /srv/ftp/cas/server/server.p12
设置密码:mldnjava

  1. 在本机系统中导入信任证书,随后会在"/usr/local/tomcat" 目录下生成"ca-trust.p12" 证书文件

keytool -importcert -trustcacerts -alias cas.com -file /srv/ftp/cas/ca.cer -keystore /usr/local/tomcat/ca-trust.p12

  1. 使用keytool工具查看证书信息

keytool -list -keystore /srv/ftp/cas/client/client.p12 -storetype pkcs12 -v

五、配置和启动tomcat

  1. 进入tomcat配置文件

/usr/local/tomcat9/conf/server.xml

<Connector port="443" protocol="HTTP/1.1" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" sslPortocol="TLS" keystoreFile="/srv/ftp/cas/server/server.p12" keystoreType="pkcs12" keystorePass="mldnjava" />
  1. 启动tomcat服务器

/usr/local/tomcat9/bin/catalina.sh start

此时可以使用http请求访问,但并不支持https访问
1.3配置本地的hosts文件
C:\Windows\System32\drivers\etc\hosts
增加配置:10.200.1.87 cas.com
再次重启浏览器输入https://cas.com,成功访问!

双向认证:

  1. 停掉tomcat

/usr/local/tomcat9/bin/catalina.sh stop

  1. 配置tomcat server.xml,替换原来配置的单向认证的配置
<Connector port="443" protocol="HTTP/1.1" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="true" sslPortocol="TLS" keystoreFile="/srv/ftp/cas/server/server.p12" keystoreType="pkcs12" keystorePass="mldnjava" truststoreFile="/usr/local/tomcat9/ca-trust.p12" truststoreType="jks" truststorePass="mldnjava" />
  1. 启动tomcat,此时再次访问https://cas.com,提示连接失败。需要在证书里面配置您的证书,把/usr/srv/ftp/cas/client/client.p12 这个证书下载下来导入到浏览器您的证书里,重启浏览器,输入https://cas.com,成功访问!

使用java模拟携带证书请求

  1. 根证书可以使用jdk的keytool工具安装,方式有很多种,这里只选用库文件的模式。
    首先,把根证书ca.crt复制一份,重命名为ca.cer,然后把这个文件复制到jdk的jre\lib\security目录下,在这个目录中进行根证书的安装:
keytool -keystore test.truststore -keypass mldnjava -storepass mldnjava -alias DemoCA -import -trustcacerts -file ca.cer

其中,test.truststore可以自定义名称,密码自定义,DemoCA别名自定义,ca.cer即刚才复制过来的文件,最后需要输入一个y确认信任。
在这里插入图片描述

  1. java客户端代码:
package com.example.demo.Service;

import org.springframework.stereotype.Service;

import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;

@Service
public class SSLService {

    /**
     * 客户端证书路径
     */
    private final static String CLIENT_CERT_FILE = "C:\\Users\\admin\\Desktop\\client.p12";
    /**
     * 客户端证书密码
     */
    private final static String CLIENT_PWD = "mldnjava";
    /**
     * 信任库文件路径
     */
    private final static String TRUST_STRORE_FILE = "C:\\Users\\admin\\Desktop\\test.truststore";
    /**
     * 信任库密码
     */
    private final static String TRUST_STORE_PWD = "mldnjava";
    private static String readResponseBody(InputStream inputStream) throws IOException {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            String buff = null;
            while ((buff = br.readLine()) != null) {
                sb.append(buff).append("\n");
            }
            return sb.toString();
        } finally {
            inputStream.close();
        }
    }
    private static void httpsCall() throws Exception {
        // 初始化密钥库
        KeyManagerFactory keyManagerFactory = KeyManagerFactory
                .getInstance("SunX509");
        KeyStore keyStore = getKeyStore(CLIENT_CERT_FILE, CLIENT_PWD, "PKCS12");
        keyManagerFactory.init(keyStore, CLIENT_PWD.toCharArray());
        // 初始化信任库
        TrustManagerFactory trustManagerFactory = TrustManagerFactory
                .getInstance("SunX509");
        KeyStore trustKeyStore = getKeyStore(TRUST_STRORE_FILE, TRUST_STORE_PWD, "JKS");
        trustManagerFactory.init(trustKeyStore);
        // 初始化SSL上下文
        SSLContext ctx = SSLContext.getInstance("SSL");
        ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory
                .getTrustManagers(), null);
        SSLSocketFactory sf = ctx.getSocketFactory();
        HttpsURLConnection.setDefaultSSLSocketFactory(sf);
        String url = "https://cas.com";
        URL urlObj = new URL(url);
        HttpsURLConnection con = (HttpsURLConnection) urlObj.openConnection();
        con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 " +
                "(KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
        con.setRequestProperty("Accept-Language", "zh-CN;en-US,en;q=0.5");
        con.setRequestMethod("GET");
        String res = readResponseBody(con.getInputStream());
        System.out.println(res);
    }
    /**
     * 获得KeyStore
     */
    private static KeyStore getKeyStore(String keyStorePath, String password, String type)
            throws Exception {
        FileInputStream is = new FileInputStream(keyStorePath);
        KeyStore ks = KeyStore.getInstance(type);
        ks.load(is, password.toCharArray());
        is.close();
        return ks;
    }
   public static void main(String[] args) throws Exception {
    httpsCall();
  }
}
  1. 执行代码,得到结果:
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值