ssl证书与java keytool工具

ssl协议

SSL(Secure Sockets Layer 安全套接字协议),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层与应用层之间对网络连接进行加密。

https = http + ssl  ,https 的安全基础即是ssl协议。

ssl证书

SSL 证书就是遵守 SSL协议,由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能。

申请与安装ssl证书

1.制作CSR文件

CSR就是Certificate Signing Request证书请求文件。这个文件是由申请人制作,在制作的同时,系统会产生2个密钥,一个是公钥就是这个CSR文件,另外一个是私钥,存放在服务器上。

一般来说,主流的Web服务软件,通常都基于OpenSSL和Java两种基础密码库。

所以要制作CSR文件,一般APACHE、Nginx等,使用OPENSSL命令行来生成KEY+CSR2个文件;Tomcat,JBoss,Weblogic等使用Java Development Kit (JDK)工具包中的Keytool工具来生成JKS和CSR文件。

2.CA认证

将CSR提交给CA,CA一般有2种认证方式:

  • 域名认证,一般通过对管理员邮箱认证的方式,这种方式认证速度快,但是签发的证书中没有企业的名称;
  • 企业文档认证,需要提供企业的营业执照。一般需要3-5个工作日。 也有需要同时认证以上2种方式的证书,叫EV证书,这种证书可以使IE7以上的浏览器地址栏变成绿色,所以认证也最严格。

3.证书的安装

在收到CA的证书后,可以将证书部署上服务器,一般nginx将KEY+CER文件复制到服务器上,然后修改nginx配置文件;TOMCAT等,需要将CA签发的证书CER文件导入JKS文件后,复制上服务器,然后修改SERVER.XML。

ssl身份认证

具体过程如下:

1.客户端发起 SSL 握手消息给服务端要求连接。
2.服务端将证书发送给客户端。
3.客户端检查服务端证书,确认是否由自己信任的证书签发机构签发。 如果不是,将是否继续通讯的决定权交给用户选择 ;如果检查无误或者用户选择继续,则客户端认可服务端的身份。

客户端是如何检查服务端证书

先确定一点,所有访问https的资源都是需要ssl证书的;但实际上我们会发现,大多数https网站可以直接访问,而一些网站需要通过在浏览器的设置中导入证书,把该证书加入到信任列表中。

所以,客户端认证ssl证书的方式,就是基于客户端的各种证书信任列表。

1.操作系统:都有自己的证书管理器,操作系统已经自动添加了这些https网站访问时需要的证书到证书管理器中。

在windows机器上,命令行输入certmgr.msc,就打开了证书管理器:

在linux机器上(以centos6为例),/etc/pki/tls/certs下有两个文件,ca-bundle.crt和ca-bundle.trust.crt,即linux的证书库。

2.浏览器:安装在操作系统中的浏览器默认的导入证书是操作系统证书管理器的证书列表+特定浏览器自己添加的少许证书。

以谷歌浏览器为例:

举一个例子,我们访问Atlassian的网站,则可以看到 * .atlassian.com 证书已由中间证书DigiCert High Assurance EV Root CA 和 DigiCert High Assurance CA-3签署,这些中间证书已由根证书Entrust.net签名:

 这三个证书组合在一起称为证书链,虽然我们并没有手动导入* .atlassian.com的证书,但是在操作系统和浏览器的证书信任列表中都能找到这三本证书:

windows操作系统的:

浏览器的:

因此客户端将信任由它们签名的任何证书,本例中即 * .atlassian.com

反之,如果某网站的ssl证书,或其根证书与中间证书,均不在客户端的证书信任列表中,那么必须手动添加该证书后,客服端才会信任该站点。

JAVA中信任证书的交互问题

问题背景:

使用 ssl 连接时,遇到不信任的证书,java应用程序一般都会拒绝连接。

浏览网站时,我们可以通过在浏览器的设置中导入证书,把证书加入到信任列表中。

而在 java 直接进行 SSL 连接应用时,默认没有一个界面来导入证书。JAVA 进行不信任的 ssl 连接时,会报如下异常:

诊断方式:

参照链接: https://confluence.atlassian.com/kb/unable-to-connect-to-ssl-services-due-to-pkix-path-building-failed-779355358.html

以上链接中提供了一种方式,用于诊断你的 Java 环境中是否包含了相应的信任证书。

1.下载 https://confluence.atlassian.com/kb/files/779355358/779355357/1/1441897666313/SSLPoke.class

2.将SSLPoke.class文件上传至服务器,运行如下命令诊断连接

[localadmin@11111 nick]$ java SSLPoke www.google.cn 443
Successfully connected

测试成功,说明当前java环境包含了谷歌的ssl信任证书。

解决方式:

若测试不成功,如下support.adyen.com的证书不被信任

[localadmin@111111 nick]$ java SSLPoke support.adyen.com 443
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
        at sun.security.validator.Validator.validate(Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1488)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
        at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:138)
        at SSLPoke.main(SSLPoke.java:31)
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:146)
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
        ... 15 more

这时候,就要找到一种方式,在 JAVA 的运行环境中导入信任证书。

同样Java也有一个统一管理信任证书的地方, 是一个叫 keystore 的文件 (默认是位于 $JAVA_HOME/lib/security/cacerts ) 。

该文件使用 keytool 工具去管理 (该工具默认位于 $JAVA_HOME/bin/keytool )。

导入证书:

keytool -import -alias <证书别名> -keystore $JAVA_HOME/jre/lib/security/cacerts -file your.crt -storepass changeit

参数说明:
-keystore  执行后添加证书的位置
-file      要跑的证书的位置
-alias     证书的名字

两个注意事项:

1.keystore文件都受密码保护,访问一个已有的 keystore 文件时,会要求你验证密码,默认密码为 changeit,所以keytool命令要加上-storepass changeit

2.需用root用户执行。

查看证书:

导入证书后可以通过以下命令查看证书是否已导入:
keytool -list -keystore "/usr/java/jdk1.8.0_60/jre/lib/security/cacerts" -storepass changeit |grep "证书的别名"

删除证书:

将证书从keystore移除:

keytool -delete -storepass changeit -keystore $JAVA_HOME/jre/lib/security/cacerts -alias "证书的别名"

参考:https://blog.csdn.net/ljskr/article/details/84570573

https://yq.aliyun.com/articles/427197

原文地址:https://www.cnblogs.com/xulan0922/p/13822062.html