证书认证
证书认证是指客户端和服务器端之间的认证。主要用来提供对用户和服务器的认证;对传送的数据进行加密和隐藏;确保数据在传送中不被改变,即数据的完整性。
证书包括一个公钥和一个私钥。公钥用于加密信息,私钥解译加密的信息。公钥公之于众,谁都可以使用,私钥只有自己知道。
单向认证:
- 客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务器端;
- 服务器端将本机的公钥证书(server.crt)发送给客户端;
- 客户端使用<CA公钥>对公钥证书的数字签名进行验证,验证通过的场合,证明公钥值得信赖,公钥已经被CA机构认证
(CA公钥,CA机构公开在网络上的公钥, 为了防止被获得CA公钥在网络获得的过程中被中间人替换,一般实现存放在浏览器中)
(验证过程:客户端利用服务器传过来的信息验证服务器的合法性,服务器的合法性包括:证书是否过期,发行服务器证书的CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过,通讯将断开;如果合法性验证通过,将继续进行。)
- 客户端读取公钥证书(server.crt),取出了服务端公钥
- 客户端生成一个<共享密钥>,使用认证过的<服务器公钥>进行加密,将<共享密钥>发送到服务器
- 服务器通过<服务器私钥>(server.key)解密,得到<共享密钥>,此时客户端和服务器都保存了同一个<共享密钥>,并且可以有效保证是安全的,以后的http传输的主体部分,通过<共享密钥>进行加密来确保通信过程的安全,报文没有没篡改。
双向认证
- 客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务端;
- 服务器端将本机的公钥证书(server.crt)发送给客户端;
- 客户端读取公钥证书(server.crt),取出了服务端公钥;
- 客户端将客户端公钥证书(client.crt)发送给服务器端;
- 服务器端使用根证书(root.crt)解密客户端公钥证书,拿到客户端公钥;
- 客户端发送自己支持的加密方案给服务器端;
- 服务器端根据自己和客户端的能力,选择一个双方都能接受的加密方案,使用客户端的公钥加密8. 后发送给客户端;
- 客户端使用自己的私钥解密加密方案,生成一个随机数R,使用服务器公钥加密后传给服务器端;
- 服务端用自己的私钥去解密这个密文,得到了密钥R
- 服务端和客户端在后续通讯过程中就使用这个密钥R进行通信了。
CA证书生成(OpenSSL)
(1)创建根证书私钥:
openssl genrsa -out root.key
(2)创建根证书请求文件:
openssl req -new -out root.csr
(3)创建根证书:
openssl x509 -req -in root.csr -out root.crt
根据CA证书生成服务端或客户端证书(OpenSSL)
(1)生成服务器端证书私钥:
openssl genrsa -out server.key
(2) 生成服务器证书请求文件:
openssl req -new -out server.csr
(3) 生成服务器端公钥证书:
openssl x509 -req -in server.csr -out server.crt
keytool使用
- 生成keystore:
keytool -genkey -v -alias tomcat -keyalg RSA –keystool /tomcat.keystore
- 查看keystore,需要输入密码:
keytool -list -keystore /tomcat.keystore
- 导入证书,需要输入密码:
keytool -import -alias Alias -keystore /tomcat.keystore -file your.crt
tomcat配置双向认证
打开Tomcat根目录下的/conf/server.xml,修改为如下:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true" maxThreads="150" scheme="https"
clientAuth="true"
keystoreFile="tomcat.keystore" keystorePass="pass"
truststoreFile="tomcat.keystore" truststorePass="pass" />
属性说明:
clientAuth:设置是否双向验证,默认为false,设置为true代表双向验证
keystoreFile:服务器证书文件路径
keystorePass:服务器证书密码
truststoreFile:用来验证客户端证书的根证书,此例中就是服务器证书
truststorePass:根证书密码
tomcat证书密码加密
- 创建一个协议处理类,替换掉默认的org.apache.coyote.http1Http11Protocol,如:
public class Http11NioProtocol extends org.apache.coyote.http11.Http11NioProtocol {
public Http11NioProtocol() {
}
public void setKeystorePass(String s) {
String pass = decryptKey(s);
super.setKeystorePass(pass);
}
public void setKeyPass(String s) {
String pass = decryptKey(s);
super.setKeyPass(pass);
}
public void setTruststorePass(String p) {
String pass = decryptKey(p);
super.setTruststorePass(pass));
}
private String decryptKey(String encryptKey) {
// decrypt key
return "";
}
}
- 修改Tomcat配置文件server.xml中protocol为新建的协议处理类:
<Connector port="8443" protocol="com.test.http11.Http11NioProtocol"
SSLEnabled="true" maxThreads="150" scheme="https"
secure="true" clientAuth="true" sslProtocol="TLS"
keystoreFile="tomcat.keystore" keystorePass="pass"
truststoreFile="tomcat.keystore" truststorePass="pass" />
java校验通过CA证书,校验客户端证书
- 获取CA证书:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
java.security.cert.Certificate cac = cf.generateCertificate(in);
// 获取CA的公钥
PublicKey pbk = cac.getPublicKey();
- 从request中获取证书:
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
- 校验证书有效期:
Date now = new Date();
X509Certificate certificate.checkValidity(now);
- 验证证书签名的有效性
certificate.verify(pbk); // pbk为第一步中得到的CA公钥
curl携带证书调用
curl --key private.key –cert cert.crt --cacert ca.crt -X GET https://www.test.com
参数说明:
--key <key> 私钥文件名
--cert <cer> 客户端证书文件
--cacert <file> CA证书