HTTPS通信过程
客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。
- 客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
- Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
- 客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
- 客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
- Web服务器利用自己的私钥解密出会话密钥。
- Web服务器利用会话密钥加密与客户端之间的通信。
什么是HTTPS/SSL证书
HTTPS/SSL证书是由权威CA(Certificate Authority)机构颁发
,主要用于服务器(应用)数据传输链路加密
和身份认证
,以及绑定网站域名
,主要有如下几种证书
- EV SSL证书(Extended Validation SSL)
- OV SSL证书(Organization Validation SSL)
- DV SSL证书(Domain Validation SSL)
不同的证书类型在浏览器标识上会享受不同的待遇,例如EV、OV证书在浏览器地址栏上会显示企业名称,当然也意味着你在向CA机构申请证书时要付更多的钱,走更多的审核流程,通常DV证书就足够用了,审核流程简单,并且很便宜
如何验证证书的有效性
HTTPS/SSL证书其实是一个证书链,这条链上的所有证书均合法才能表明证书本身的合法性
。
关于证书链
Web 浏览器已预先配置了一组浏览器自动信任的根 CA 证书。来自其他证书授权机构的所有证书都必须附带证书链,以检验这些证书的有效性。证书链是由一系列 CA 证书发出的证书序列,最终以根 CA 证书结束
证书最初生成时是一个自签名证书。
- 自签名证书是其签发者(签名者)与主题(其公钥由该证书进行验证的实体)相同的证书。
- 如果拥有者向 CA 发送证书签名请求 (CSR),然后输入响应,自签名证书将被证书链替换。
- 链的底部是由 CA 发布的、用于验证主题的公钥的证书(回复)。
- 链中的下一个证书是验证 CA 的公钥的证书。通常,这是一个自签名证书(即,来自 CA、用于验证其自身的公钥的证书)并且是链中的最后一个证书。
在其他情况下,CA 可能会返回一个证书链。
- 在此情况下,链的底部证书是相同的(由 CA 签发的证书,用于验证密钥条目的公钥),
- 但是链中的第二个证书是由其他 CA 签发的证书,用于验证您向其发送了 CSR 的 CA 的公钥。
- 然后,链中的下一个证书是用于验证第二个 CA 的密钥的证书,
- 依此类推,直至到达自签名的根证书。
- 因此,链中的每个证书(第一个证书之后的证书)都需要验证链中前一个证书的签名者的公钥。
用java代码实现一下获取远程服务端证书
package org.test;
import java.net.URL;
import java.security.MessageDigest;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
public class Application {
public static void main(String[] args) throws Exception {
URL url = new URL("https://baidu.com");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.connect();
Certificate[] certs = conn.getServerCertificates(); //会拿到完整的证书链
X509Certificate cert = (X509Certificate)certs[0]; //cert[0]是证书链的最下层
System.out.println("序号:" + cert.getSerialNumber());
System.out.println("颁发给:" + cert.getSubjectDN().getName());
System.out.println("颁发者:" + cert.getIssuerDN().getName());
System.out.println("起始:" + cert.getNotBefore());
System.out.println("过期:" + cert.getNotAfter());
System.out.println("算法:" + cert.getSigAlgName());
System.out.println("指纹:" + getThumbPrint(cert));
conn.disconnect();
}
private static String getThumbPrint(X509Certificate cert) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] der = cert.getEncoded();
md.update(der);
byte[] digest = md.digest();
return bytesToHexString(digest);
}
private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
}
结果
序号:26585094245224241434632730821
颁发给:CN=baidu.com, O="Beijing Baidu Netcom Science Technology Co., Ltd", L=beijing, ST=beijing, C=CN
颁发者:CN=GlobalSign RSA OV SSL CA 2018, O=GlobalSign nv-sa, C=BE
起始:Thu Jul 06 09:51:06 CST 2023
过期:Tue Aug 06 09:51:05 CST 2024
算法:SHA256withRSA
指纹:9742d59827d62288cf59c3ff75868dd5d312a0af