服务器开发程序员必须搞清HTTPS通讯之证书
zhezhongyun 2025-05-03 17:49 35 浏览
一、构建HTTPS网站
1. 获取证书和密钥对
1.1.1 自签名证书
当浏览器发现证书是自签名的,会提示用户是否信任该证书。一般企业内部应用可以选择自签名证书。
第1步 生成私钥对和CSR
CSR用来请求证书,其中包含了服务器的密钥对,CA机构收到请求后会验证CSR请求的签名。
openssl req -newkey rsa:1024 -nodes -keyout my_key.pem -out mykey_csr.pem
提示输入中最重要的是输入域名信息:Common Name。
第2步 生成自签名证书
就是模拟CA机构对盲目签名:
openssl x509 -signkey my_key.pem -in mykey_csr.pem -req -days 365 -out my_cert.pem
生成my_cert.pem即签名后的证书:
1.1.2 向CA机构申请证书
- 向专门的CA机构申请;
- 向代理机构申请,如一些云厂商。
证书申请的方式:
- 向CA发送CSR;
- CA统一生成证书和密钥对,但泄露了自己的私钥。
申请时,CA机构通过DNS TXT记录或服务器上一个特殊的txt文件来校验域名所有者。
1.1.3 使用Let’s Encrypt证书
Let’s Encrypt可以申请免费的证书,作为一个CA机构得到了很多大公司的支持,它定义了ACME协议,将管理证书的流程进行了标准化。
可以使用基于ACME协议的客户端在Let’s Encrypt管理证书,官方推荐Certbot客户端。
# 下载Certbot客户端
git clone https://github.com/certbot/certbot
cd certbot
# 生成证书,-w表示代码根目录,-d要申请证书的域名,--webroot表示安装插件。
./certbot-auto certonly --webroot -w /usr/nginx/web -d www.mydomain.com
运行结束在/etc/letsencrypt/live/www.mydomain.com下生成4个文件,最重要的是:
- fullchain.pem 完整证书链
- privkey.pem 私钥
另外还有: - cert.pem
- chain.pem
webroot 插件用来校验申请者身份,该命令需要在mydomain主机上运行,主机web在/usr/nginx/web下。
2. 部署证书和密钥对
1.2.1 Nginx 下部署
http{
#http节点中可以添加多个server节点
server{
#监听443端口
listen 443;
#对应的域名,把mydomain.com改成自己的域名
server_name mydomain.com;
ssl on;
# 证书路径
ssl_certificate /etc/cert/fullchain.pem;
# 密钥对路径
ssl_certificate_key /etc/cert/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
#文件夹
root /usr/local/service/ROOT;
#主页文件
index index.html;
}
}
server{
listen 80;
server_name mydomain.com;
rewrite ^/(.*)$ https://mydomain.com:443/$1 permanent;
}
}
1.2.2 Apache
vim /etc/apache2/sites-available/default-ssl.conf
<VirtualHost _default_:443>
DocumentRoot /var/www/html
ServerName www.mydomain.com
# 开启SSL
SSLEngine on
SSLCertificateFile /etc/cert/fullchain.pem;
SSLCertificateKeyFile /etc/cert/privkey.pem
</VirtualHost>
3. 测试https
1.3.1 使用curl
curl "https://www.csdn.net" --verbose | head
1.3.2 使用Chrome开发者工具
1.3.3 301重定向
在迁移老的网站,为了让http页面能访问到,可以设置301重定向,将http转向https。POST请求不支持301重定向。
1.3.4 HSTS
一种新的Web安全协议HTTP Strict Transport Security(HSTS),在server的http的head里加:
Strict-Transport-Security: max-age=31536000; includeSubDomains
在接下来的31536000秒内,浏览器向域名和子域名的http请求强制转成https。当发现自签名证书时,浏览器会强上停止访问,不会出现让用户选择信任或不信任的弹出窗口。
1.3.5 CSP
CSP指的是内容安全策略,为了缓解很大一部分潜在的跨站脚本问题,浏览器的扩展程序系统引入了内容安全策略(CSP)的一般概念。CSP主要以白名单机制对网站加载或执行的资源起作用。
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
二、PKI
Public Key Infrastructure(PKI),中文公钥基础设施,由一系列实体组成的集合体,用于向客户端提供可信的服务器身份认证。
X.509
PKI的标准规定PKI的设计、实施和运营,PKI事实上的标准是X.509。
X.509来自于国际电信联盟电信标准(ITU-T)的X.500标准,发展主要历史:
- X.209 1988
- X.500 1993,ISO组织接受的目录服务系统标准,定义了一个机构如何在全局范围内共享其名字和与之相关的对象。X.500是分层次的,其中的管理域(机构、分支、部门和工作组)可以提供这些域内的用户和资源信息。在PKI体系中,X.500被用来惟一标识一个实体,该实体可以是机构、组织、个人或一台服务器。X.500被认为是实现目录服务的最佳途径,但X.500的实现需要较大的投资,并且比其他方式速度慢;而其优势具有信息模型、多功能和开放性。
- X.509 1993 由国际电信联盟(ITU-T)制定的数字证书标准,最初版本公布于1988年。X.509证书由用户公共密钥和用户标识符组成。此外还包括版本号、证书序列号、CA标识符、签名算法标识、签发者名称、证书有效期等信息。这一标准的最新版本是X.509 v3。
三、证书
对HTTPS通讯来说,核心是理解证书。证书主要包括:签名、服务器实体信息、CA机构信息。
1. ASN.1
ASN.1是数据结构描述语言,由ITU-T定义的标准,用来结构化描述证书。它有两部分:
- ISO 8824/ITU X.208 描述信息内的数据、数据类型及序列格式,也就是数据的语法;
- ISO 8825/ITU X.209 描述如何将各部分数据组成消息,也就是数据的基本编码规则。
X.509定义了证书应该包含的内容,而ASN.1是具体的数据结构。
ASN.1 原来是X.409的一部分,后来独立出来成为一个标准 ,广泛应用于计算机通讯领域。
2. 证书结构
3.2.1 证书的主要结构:
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier, # 签名算法
signature BIT STRING # 签名值
}
SEQUENCE是ASN.1中的一个结构体,包括多个属性。属性还可以嵌套其它的ASN.1结构。TBSCertificate就是一个SEQUENCE结构。
3.2.2. TBSCertificate结构:
TBSCertificate ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1, -- 证书版本号
serialNumber CertificateSerialNumber, -- 证书序列号,对同一CA所颁发的证书,序列号唯一标识证书
signature AlgorithmIdentifier, --证书签名算法标识
issuer Name, --证书发行者名称,简称DN
validity Validity, --证书有效期
subject Name, --证书主体名称
subjectPublicKeyInfo SubjectPublicKeyInfo,--证书公钥
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, -- 证书发行者ID(可选),只在证书版本2、3中才有
subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, -- 证书主体ID(可选),只在证书版本2、3中才有
extensions [3] EXPLICIT Extensions OPTIONAL -- 证书扩展段(可选),只在证书版本3中才有
}
3.2.3 签名算法
签名算法标识符AlgorithmIdentifier类型也是一个SEQUENCE结构,由两个属性构成:
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
3.2.4 issuer 示例
Let’s Encrypt:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
3.2.5 validity
有效期,结构:
Validity ::= SEQUENCE{
notBefore Time,
notAfter Time
}
3. CSR
服务器实体为了证明自己的身份,要向CA机构申请证书。在申请之前,先生成一个CSR(Certificate Signing Request)文件,即证书签名请求文件,把这个CSR文件发给CA机构。CA机构使用其根证书私钥签名就生成了证书公钥文件,也就是颁发给用户的证书。
CSR文件包括两部分:
- 生成证书必须的信息,如域名、公钥
- 服务器实体的证明材料
3.3.1 CSR也采用ASN.1标准描述,整体格式是:
CertificationRequest ::= SEQUENCE {
certificationRequestInfo CertificationRequestInfo, # 证书的请求信息
signatureAlgorithm AlgorithmIdentifier, # 签名算法
signature BIT STRING # 签名信息
}
3.3.2 CertificationRequestInfo结构:
CertificationRequestInfo ::= SEQUENCE{
version INTEGER { v1(0) } (v1,...),
subject Name,
subjectPKInfo SubjectPublicKeyInfo,
attributes [0] Attributes
}
- version: 表示 PKCS#10 标准的版本号;
- subject : 表示服务器主体的可分辨名称DN,最重要的是CN值,表示证书需要包含的域名,可以包含多个;
- subjectPKInfo: 服务器密钥对的公钥,可以是RSA公钥或ECDSA公钥。服务器主体使用该密钥对的私钥对certificationRequestInfo进行数字签名最终生成CSR文件。
3.3.3 CSR生成过程
- 服务器主体生成一对密钥对,如RSA密钥对;
- 生成CertificationRequestInfo结构体,主要包含域名、公钥;
- 使用私钥对CertificationRequestInfo进行数字签名得到签名值;
- 组合CertificationRequestInfo信息和签名得到最终的CSR文件。
3.3.4 证书扩展
扩展有标准和非标准两种,每个扩展都是一个OLD ASN.1结构。每个扩展都有一个critical属性,如果该属性值为true,CA必须严格处理。
3.3.5 证书分类
根据验证模式分类
- DV(Domain Validated)证书:最常见的一种证书类型,CSR包含域名信息,CA检验域名所有权,如果通过审核,申请者就有权申请该域名的证书。校验方式有DNS TXT记录方式、服务器放置特殊文件方式。
- OV(Organization Validated)证书:CA机构对申请者的身份进行严格的审核,确保申请者的身份是真实的。申请时间比DV证书要长。
- EV(Extended Validation)证书:对申请者进行更严格的审核。
根据域名分类
- 单域名证书
- 泛域名证书
- SAN(Subject Alternative Names)证书,可以把多个不同的注册域名合并到一张证书。
- SAN泛域名证书。
四、 证书链
1. 证书类型
如在Chrome中看CSDN的证书:
- 服务器实体在配置HTTPS的时候,不只是配置服务器实体证书,还涉及其它证书;
- 证书链的理解:
- DigiCert信任了GeoTrust RSA CA 2018
- GeoTrust RSA CA 2018信任了*.csdn.net
上面证书类型分为了:
- 服务器实体证书
- 中间证书
- 根证书:自签名证书,位于证书链中的最顶端。
在使用Certbot客户端工具生成的证书中,fullchain.pem包含了cert.pem和chain.pem文件的内容,构成了完整的证书链。cert.pem在fullchain.pem文件的最顶端。根证书预嵌入到了浏览器中,配置Nginx和Apache的时候,只需要fullchain.pem,不需要包含根证书。
2. 信任链校验
- 浏览器连接至一个https网站
- 服务器发完整证书给浏览器,如fullchain.pem。对X.509标准来说,服务器应该发送完整的证书链(不包含根证书)。如果发送的证书不完整,客户端可以找到所有的证书链,但有的浏览器可能不会这样做,造成不兼容。
通过服务器实体证书找到完整证书链的方法,从中解析CA密钥标识符,进而获取上一级中间证书文件,通过中间证书的CA密钥标识符继续向上找到根证书。 - 校验证书链关系
浏览器要信任每张证书,必须确保每个证书(除了根证书)的签发者都是它的上一级证书的使用者(subject)。如果不符合,证书校验就会失败。
3. 根证书
Linux各个发行版中,OpenSSL库会集成根证书
openssl version -a
windows
在HKEY_CURRENT_USER注册表管理根证书
Mozilla
在NSS底层独立维护了可信任的根证书库。
五、CRL 证书吊销列表
CRL(Certificate Revocation List),是PKI技术的重要组成部分。CRL是TLS/SSL协议的一部分,X.509 V2 标准定义了CRL的语法和语义信息,CRL结构类似于证书,也使用ASN.1 结构来解释其含义。
六、OCSP
CRL正逐步被OCSP替代(在线证书状态协议,Online Certificate Status Protocol),定义在RF6960文档中,主要目的是为了替换CRL,更好地核实证书的使用。
七、证书格式
1. DER
ASN.1是一种抽象的数据结构,描述了复杂的对象。证书本质是一个文件,要通过一个规则把ASN.1转换为二进制文件。 在X.509证书中,使用的编码方式是 Distinguished Encoding Rules(DER)。
2. BER
Basic Encoding Rules(BER)是DER的一个子集。
3. CER
CER是另一种编码标准,用来编码ASN.1结构
4. PEM
DER是个二进制文件,为了方便传输,可以将DER转换为PEM(Privacy enhanced Electronic mail)格式。 PEM是Base64编码方式,以:-----BEGIN CERTIFICATE----- 开头,-----END CERTIFICATE----- 结尾。
5. 编码转换
PEM转为DER
openssl x509 -in cert.pem -out cert.der -outform DER
DER转为PEM
openssl x509 -incert.der -inform DER -out cert.pem -outform PEM
1
6. 其它的证书格式
7.6.1 PKCS#12(后缀.pkcs12 .pfx .p12)
非对称加密的一种格式,微软推出。PKCS#12把证书和密钥对打包成一个文件,还可以再对文件进行加密保护。通过OpenSSL pkcs12子命令将密钥对(privkey.pem)、服务器实体证书(cert.pem)、中间证书(chain.pem)转换成一个文件:
openssl pkcs12 -export -out cert.pfx \
-inkey privkey.pem -in cert.pem -certfile chain.pem
生成 cert.pfx时会提示进行口令保护。可以再使用命令从pfx中再导出密钥对和证书:
# 导出密钥对
openssl pkcs12 -in cert.pfx -nodes -nocerts -out new_privkey.pem
# 导出服务器实体证书
openssl pkcs12 -in cert.pfx -nodes -clcerts -out new_cert.pem
# 导出中间证书
openssl pkcs12 -in cert.pfx -nodes -cacerts -out new_chain.pem
7.6.2 PKCS#7
主要用来进行数字签名和数据加密,文件后缀一般是.p7b或.p7c,使用OpenSSL crl2pkcs7进行操作。
# 生成 cert.p7b
openssl crl2pkcs7 -nocrl -certfile cert.pem -certfile chain.pem -out cert.p7b
# 导出完整证书链文件,服务器实体证书在文件顶部,中间证书在文件底部
openssl pkcs7 -print_certs -in cert.p7b -out fullchain.cer
7.6.3 BKS
BouncyCastleProvider,它使用的也是TripleDES来保护密钥库中的Key,它能够防止证书库被不小心修改(Keystore的keyentry改掉1个bit都会产生错误),BKS能够跟JKS互操作。由于安卓无法直接支持jks的证书库,在安卓下一般需要使用BKS类型证书。
7. CSR管理
7.7.1 查看CSR
前面使用OpenSSL命令生成了CSR文件 , 下面使用命令查看CSR文件内容:
openssl req -in mykey_csr.pem -noout -text
其中:
- Subject Public Key Info : 生成的公钥,包含了e和n等RSA信息
- Signature Algorithm 表示签名算法和签名值。
7.7.2 校验CSR签名
openssl req -in myreq.pem -noout -verify -key mykey_csr.pem
八、导入根证书
更新根证书库,一般原因:
- 有新成立了一个CA机构,要导入到根证书库中
- 自签名了一个证书,要导入根证书库
- 系统根证书库太旧
Linux下 命令行update-ca-certificates可以用来同步证书。
windows下可以双击.cer文件弹出安装证书界面。
本文没有使用keytool工具,后面会使用keytool工具进行测试。本文学习资源来源:《深入浅出HTTPS从原理到实战》 电子工业出版社 虞卫东著。感谢原作者。
相关推荐
- Go语言标准库中5个被低估的强大package
-
在Go语言的世界里,开发者们往往对fmt、net/http这些“明星包”耳熟能详,却忽略了标准库里藏着的一批“宝藏工具”。它们功能强大却低调内敛,能解决并发控制、内存优化、日志管理等核心问题。今天就带...
- 作为测试人,如何优雅地查看Log日志?
-
作为一名测试工程师,测试工作中和Linux打交道的地方有很多。比如查看日志、定位Bug、修改文件、部署环境等。项目部署在Linux上,如果某个功能发生错误,就需要我们去排查出错的原因,所以熟练地掌握查...
- Java 从底层与接口实现了解String、StringBuffer、StringBuilder
-
String、StringBuffer和StringBuilder的接口实现关系:String:字符串常量,字符串长度不可变。Java中String是immutable(不可变)的。用于存放字符...
- FluentData 从入门到精通:C#.NET 数据访问最佳实践
-
简介FluentData是一个微型ORM(micro-ORM),主打「FluentAPI」风格,让开发者在保持对原生SQL完全控制的同时,享受链式调用的便捷性。它与Dapper、Massi...
- 团队协作-代码格式化工具clang-format
-
环境:clang-format:10.0.0前言统一的代码规范对于整个团队来说十分重要,通过git/svn在提交前进行统一的ClangFormat格式化,可以有效避免由于人工操作带来的代码格式问题。C...
- C# 数据操作系列 - 15 SqlSugar 增删改查详解(超长篇)
-
0.前言继上一篇,以及上上篇,我们对SqlSugar有了一个大概的认识,但是这并不完美,因为那些都是理论知识,无法描述我们工程开发中实际情况。而这一篇,将带领小伙伴们一起试着写一个能在工程中使用的模...
- Mac OS 下 Unix 使用最多的100条命令(收藏级)
-
MacOS内置基于Unix的强大终端(Terminal),对开发者、运维工程师和日常用户来说,掌握常用的Unix命令是提升效率的关键。本文整理了100条在MacOS下最常用的U...
- C语言字符串操作总结大全(超详细)
-
C语言字符串操作总结大全(超详细)1)字符串操作strcpy(p,p1)复制字符串strncpy(p,p1,n)复制指定长度字符串strcat(p,p1)附加字符串strncat...
- 经常使用到开源的MySQL,今天我们就来系统地认识一下
-
作为程序员,我们在项目中会使用到许多种类的数据库,根据业务类型、并发量和数据要求等选择不同类型的数据库,比如MySQL、Oracle、SQLServer、SQLite、MongoDB和Redis等。今...
- 电脑蓝屏代码大全_电脑蓝屏代码大全及解决方案
-
0X0000000操作完成0X0000001不正确的函数0X0000002系统找不到指定的文件0X0000003系统找不到指定的路径0X0000004系统无法打开文件0X0000005拒绝...
- 8个增强PHP程序安全的函数_php性能优化及安全策略
-
安全是编程非常重要的一个方面。在任何一种编程语言中,都提供了许多的函数或者模块来确保程序的安全性。在现代网站应用中,经常要获取来自世界各地用户的输入,但是,我们都知道“永远不能相信那些用户输入的数据”...
- css优化都有哪些优化方案_css性能优化技巧
-
CSS优化其实可以分成几个层面:性能优化、可维护性优化、兼容性优化以及用户体验优化。这里我帮你梳理一份比较系统的CSS优化方案清单,方便你参考:一、加载性能优化减少CSS文件体积压缩CSS...
- 筹划20年,他终于拍成了这部电影_筹划20年,他终于拍成了这部电影英语
-
如果提名好莱坞最难搞影星,你第一时间会联想到谁?是坏脾气的西恩·潘,还是曾因吸毒锒铛入狱的小罗伯特·唐尼,亦或是沉迷酒精影响工作的罗素·克劳?上述大咖,往往都有着这样或那样的瑕疵。可即便如此,却都仍旧...
- Keycloak Servlet Filter Adapter使用
-
KeycloakClientAdapters简介Keycloakclientadaptersarelibrariesthatmakeitveryeasytosecurea...
- 一些常用的linux常用的命令_linux常用命令有哪些?
-
在Linux的世界里,命令是与系统交互的基础。掌握常用命令不仅能让你高效地管理文件、进程和网络,还能为你进一步学习系统管理和自动化打下坚实的基础。本文将深入探讨一些最常用且功能强大的Linux...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)
- HTML button formtarget 属性 (30)
- opacity 属性 (32)
- transition 属性 (33)