使用JDK自带工具keytool生成ssl证书
HTTPS简介
超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,常称为HTTP over TLS,HTTP over SSL或HTTP Secure)是一种网络安全传输协议。具体介绍以前先来介绍一下以前常见的HTTP,HTTP就是我们平时浏览网页时候使用的一种协议。HTTP协议传输的数据都是未加密的,也就是明文,因此使用HTTP协议传输隐私信息非常不安全。HTTP使用80端口通讯,而HTTPS占用443端口通讯。在计算机网络上,HTTPS经由超文本传输协议(HTTP)进行通信,但利用SSL/TLS来加密数据包。HTTPS开发的主要目的,是提供对网络服务器的身份认证,保护交换数据的隐私与完整性。
HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块,并且会进行身份的验证。
SSL(Secure Sockets Layer 安全套接层)是为网络通信提供安全及数据完整性的一种安全协议,SSL在网络传输层对网络连接进行加密,SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通信提供安全支持。SSL协议分为两层,SSL记录协议建立在TCP之上,为高层协议提供数据封装、压缩、加密等基本功能支持。SSL握手协议建立在SSL记录协议之上,用户实际数据传输开始前进行身份验证、协商加密算法、交换加密秘钥。
问题:Firebug和postman之类的浏览器调试工具,为什么获取到的是明文?
解答:
SSL是对传输的数据进行加密,针对的是传输过程的安全。
firebug之类的浏览器调试工具,因为他们得到的是客户端加密之前/解密之后的数据,因此是明文的。
HTTPS工作原理
HTTPS 工作原理
HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL协议不仅仅是一套加密传输的协议,更是一件经过艺术家精心设计的艺术品,TLS/SSL中使用了非对称加密,对称加密以及HASH算法。握手过程的具体描述如下:- 浏览器将自己支持的一套加密规则发送给网站。
- 网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。
- 浏览器获得网站证书之后浏览器要做以下工作:
- 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示
- 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。
- 使用约定好的HASH算法计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站。
- 网站接收浏览器发来的数据之后要做以下的操作:
- 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。
- 使用密码加密一段握手消息,发送给浏览器。
- 浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
这里浏览器与网站互相发送加密的握手消息并验证,目的是为了保证双方都获得了一致的密码,并且可以正常的加密解密数据,为后续真正数据的传输做一次测试。另外,HTTPS一般使用的加密与HASH算法如下:
- 非对称加密算法:RSA,DSA/DSS
- 对称加密算法:AES,RC4,3DES
- HASH算法:MD5,SHA1,SHA256
HTTPS对应通讯时序图如下:
自签名证书简介
JDK中keytool是一个证书管理工具,可以生成自签名证书。 就是自己生成的证书,并不是官方生成的证书。除非是很正式的项目,否则使用自己签发的证书即可,因为官方生成证书是要花钱滴。
其他描述
1. 客户端发起HTTPS请求
这个没什么好说的,就是用户在浏览器里输入一个https网址,然后连接到server的443端口。
2. 服务端的配置
采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl就是个不错的选择,有1年的免费服务)。这套证书其实就是一对公钥和私钥。如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。
3. 传送证书
这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。
4. 客户端解析证书
这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随即值。然后用证书对该随机值进行加密。就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。
5. 传送加密信息
这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。
6. 服务段解密信息
服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密。所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。
7. 传输加密后的信息
这部分信息是服务段用私钥加密后的信息,可以在客户端被还原
8. 客户端解密信息
客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策。
生成ssl证书步骤
步骤一:为服务器生成证书
- 进入jdk的bin目录下面,打开CMD命令行工具
- 相关命令:
keytool
-genkey
-alias tomcat(别名)
-keypass 123456(别名密码)
-keyalg RSA(生证书的算法名称,RSA是一种非对称加密算法)
-keysize 1024(密钥长度,证书大小)
-validity 365(证书有效期,天单位)
-keystore W:/tomcat.keystore(指定生成证书的位置和证书名称)
-storepass 123456(获取keystore信息的密码)
- storetype (指定密钥仓库类型)
- 使用keytool命令生成证书:
方便复制版: keytool -genkey -alias tomcat -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -keystore W:/tomcat.keystore -storepass 123456
返回:
W:\sys_toos\jdk8\jdk1.8.0_73\bin>keytool -genkey -alias tomcat -keypass 123456 -
keyalg RSA -keysize 1024 -validity 365 -keystore W:/tomcat.keystore -storepass 1
23456
您的名字与姓氏是什么?
[Unknown]: www.seeker.com
您的组织单位名称是什么?
[Unknown]: seeker
您的组织名称是什么?
[Unknown]: seeker
您所在的城市或区域名称是什么?
[Unknown]: beijing
您所在的省/市/自治区名称是什么?
[Unknown]: beijing
该单位的双字母国家/地区代码是什么?
[Unknown]: zh
CN=www.seeker.com, OU=seeker, O=seeker, L=beijing, ST=beijing, C=zh是否正确?
[否]: y
点击回车:W:/目录下面生成tomcat.keystore的文件。
步骤二:为客户端生成证书
- 为浏览器生成证书,以便让服务器来验证它。为了能将证书顺利导入至IE和Firefox,证书格式应该是PKCS12
关于.jks,.pkcs12,.keystore.cer文件,可以百度其区别
方便复制版: keytool -genkey -alias client -keypass 123456 -keyalg RSA -storetype PKCS12 -keypass 123456 -storepass 123456 -keystore W:/client.p12
返回:
W:\sys_toos\jdk8\jdk1.8.0_73\bin>keytool -genkey -alias client -keypass 123456 -
keyalg RSA -storetype PKCS12 -keypass 123456 -storepass 123456 -keystore W:/clie
nt.p12
您的名字与姓氏是什么?
[Unknown]: www.seeker.com
您的组织单位名称是什么?
[Unknown]: seeker
您的组织名称是什么?
[Unknown]: seeker
您所在的城市或区域名称是什么?
[Unknown]: beijing
您所在的省/市/自治区名称是什么?
[Unknown]: beijing
该单位的双字母国家/地区代码是什么?
[Unknown]: zh
CN=www.seeker.com, OU=seeker, O=seeker, L=beijing, ST=beijing, C=zh是否正确?
[否]: y
点击回车:W:/目录下面生成client.p12的文件。
步骤三:让服务器信任客户端证书
由于不能直接将PKCS12格式的证书库导入,必须先把客户端证书导出为一个单独的CER文件,使用如下命令:
keytool -export -alias client -keystore W:/client.p12 -storetype PKCS12 -keypass 123456 -file W:/client.cer
点击回车:W:/目录下面生成client.cer的文件。
将该文件导入到服务器的证书库,添加为一个信任证书:
keytool -import -v -file W:/client.cer -keystore W:/tomcat.keystor
返回:
W:\sys_toos\jdk8\jdk1.8.0_73\bin>keytool -import -v -file W:/client.cer -keystor
e W:/tomcat.keystor
输入密钥库口令:
所有者: CN=www.seeker.com, OU=seeker, O=seeker, L=beijing, ST=beijing, C=zh
发布者: CN=www.seeker.com, OU=seeker, O=seeker, L=beijing, ST=beijing, C=zh
序列号: 40e67ca9
有效期开始日期: Thu May 17 11:35:09 CST 2018, 截止日期: Wed Aug 15 11:35:09 CST
2018
证书指纹:
MD5: 2E:B4:0D:A0:51:97:FF:FF:C2:78:26:8C:F7:9A:B0:E7
SHA1: 3B:2D:FC:F8:40:0B:A2:56:24:AA:FB:85:35:93:7C:08:4F:4D:D7:33
SHA256: A7:1E:53:28:0F:96:85:B8:59:10:99:7B:0F:FD:46:57:DA:29:EA:94:1A:
07:A2:48:B8:70:6F:AA:BC:9B:34:31
签名算法名称: SHA256withRSA
版本: 3
扩展:
#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 1A 52 82 28 D9 AC 3E 03 E5 12 91 98 56 11 C0 49 .R.(..>.....V..I
0010: 88 53 2D 09 .S-.
]
]
是否信任此证书? [否]: Y
证书已添加到密钥库中
[正在存储W:/tomcat.keystor]
完成之后通过list命令查看服务器的证书库,可以看到两个证书,一个是服务器证书,一个是受信任的客户端证书:
keytool -list -v -keystore W:/tomcat.keystore
步骤四:让客户端信任服务器证书
由于是双向SSL认证,客户端也要验证服务器证书,因此,必须把服务器证书添加到浏览器的“受信任的根证书颁发机构”。
由于不能直接将keystore格式的证书库导入,必须先把服务器证书导出为一个单独的CER文件,使用如下命令:
keytool -keystore W:/tomcat.keystore -export -alias tomcat -file W:/server.cer
返回:
W:\sys_toos\jdk8\jdk1.8.0_73\bin>keytool -keystore W:/tomcat.keystore -export -alias tomcat -file W:/server.cer
输入密钥库口令:
存储在文件 <W:/server.cer> 中的证书
双击server.cer文件,按照提示安装证书
将证书填入到“受信任的根证书颁发机构”。具体方法:(我用的谷歌浏览器):
- 打开谷歌浏览器 --> 设置--> 高级 --> 管理证书 --> 中级证书颁发机构 --> 选择www.seeker.com,点击导出到桌面SEEKER.cer
- 打开谷歌浏览器 --> 设置--> 高级 --> 管理证书 --> 受信任的根证书颁发机构 --> 导入SEEKER.cer
其他浏览器将证书填入到“受信任的根证书颁发机构”:
- 打开浏览器 - 工具 - internet选项-内容- 证书-把中级证书颁发机构里的www.seeker.com(该名称即时你前面生成证书时填写的名字与姓氏)证书导出来-再把导出来的证书导入 受信任的根颁发机构 就OK了。
步骤五:配置Tomcat服务器
server.xml配置:
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
maxThreads="150"
scheme="https"
secure="true"
clientAuth="true"
sslProtocol="TLS"
keystoreFile="W:/tomcat.keystore"
keystorePass="123456"
truststoreFile="W:/tomcat.keystore"
truststorePass="123456" />
属性说明:
clientAuth:设置是否双向验证,默认为false,设置为true代表双向验证
keystoreFile:服务器证书文件路径
keystorePass:服务器证书密码
truststoreFile:用来验证客户端证书的根证书,此例中就是服务器证书
truststorePass:根证书密码
注意:
① 设置clientAuth属性为True时,需要手动导入客户端证书才能访问。
② 要访问https请求 需要访问8443端口,访问http请求则访问Tomcat默认端口(你自己设置的端口,默认8080)即可。
小知识:
强制 https 访问
在 tomcat /conf/web.xml 中的 </welcome- file-list> 后面加上这
<login-config>
<!-- Authorization setting for SSL -->
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Client Cert Users-only Area</realm-name>
</login-config>
<security-constraint>
<!-- Authorization setting for SSL -->
<web-resource-collection >
<web-resource-name >SSL</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
完成以上步骤后,在浏览器中输入http的访问地址也会自动转换为https
springboot配置ssl(证书为JKS格式,或者.keystore文件)
- 将tomcat.keystore拷贝到项目根目录下(跟pom文件同级目录)
- 配置application.properties
#端口号
server.port=8443
#你生成的证书名字
server.ssl.key-store=tomcat.keystore
#密钥库密码
server.ssl.key-store-password=123456
server.ssl.keyStoreType=JKS
server.ssl.keyAlias:tomcat
- 修改springboot运行主类:实现http自动跳转https
package seeker1.seeker1;
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
public class Seeker1Application {
public static void main(String[] args) {
SpringApplication.run(Seeker1Application.class, args);
}
/**
* it's for set http url auto change to https
*/
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");// confidential
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(httpConnector());
return tomcat;
}
@Bean
public Connector httpConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(8080);
connector.setSecure(false);
connector.setRedirectPort(8443);
return connector;
}
}
springboot配置ssl(方案二)
- 生成自签名证书(keyStoreType=PKCS12),命令:
keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore W:/keystore.p12 -validity 3650
执行命令后,在你的系统的W:/目录下会生成一个keystore.p12文件,将这个文件拷贝到我们项目resoruces目录下(和application.properties同级目录)
- 修改application.properties文件
server.port:8443
# classpath就是指目录 src/main/resources/
server.ssl.key-store: classpath:keystore.p12
server.ssl.key-store-password: 123456
server.ssl.keyStoreType: PKCS12
server.ssl.keyAlias: tomcat
直接在springboot里面配置是为了应对简单的服务,真正的系统会在nginx上配置证书。