OpenSSL 学习笔记
传输层安全
- 安全通信
- 避免窃听
- 确认另一端连接者的身份
名词解释
CA (Certificate Authority)
证书授权中心,是数字证书颁发和管理的机构。DN (Distinguished Name)
标识名,指定实体身份的字段。CSR (Certificate Signing Request)
数字证书签名请求,其中包含了公钥和DN
。
证书机制
根证书:是 CA 机构颁发 SSL 证书的核心,是信任链的起始点。受信任的根证书是属于证书颁发机构(CA),而 CA 机构是验证和颁发 SSL 证书的组织机构。
证书链:由两个环节组成,信任锚证书环节 和 已签名证书环节。信任锚证书环节可以对中间证书签名;中间证书的所有者可以用自己的私钥对另一个证书签名,两者结合就构成证书链。
用户获取 SSL 证书之前,首先生成 证书签名请求 和 私钥,然后将生成的签名请求发送到证书颁发机构,再使用证书颁发机构的根证书的私钥签署用户的 SSL 证书,并将 SSL 证书发回给用户。
中间证书:证书颁发机构不会直接从根目录颁发 SSL 证书,一旦发生错误,颁发者或需求者需要撤销根证书,则使用根证书签名的每个证书都会被撤销信任。为了避免这种风险发生,CA 机构一般会引用中间根。CA 机构使用中间根的私钥来签署用户申请的 SSL 证书。这种中间根的形式可以重复多次,即使用中间根签署另一个中间证书。
根证书CA 和 中间根CA 的区别:
根证书CA是拥有一个或多个受信任的根证书颁发机构,即CA机构已经扎根在主要浏览器的信任库中,而中间根CA或子CA是颁发中间根的证书颁发机构,他们不一定在浏览器的信任库中有根证书,而是将他们的中间根链接到手信任的第三方根,被称为交叉签名。
链式根 和 单一根 之间的区别:
单一根是由CA拥有的,可直接颁发证书。链式根是SubCA用于颁发证书的内容,是一个中间证书,必须链接到第三方受信任的CA。
链式根需要复杂的安装方法,因为中间根需要加载到托管证书的每个服务器和应用程序。
链式根需要受到链接的 CA 支配,无法控制 root 用户,一旦root CA 停业,就会受到巨大的牵连。
证书格式
x509 证书常见扩展名:DER
、PEM
、CRT
、CER
。
- .DER
用于二进制 DER 编码证书。 - .PEM
用于不同类型的 x509v3 文件,以“-BEGIN”为前缀的 ASCII(或 Base64)数据。 - .CRT
用于证书,可被编码为二进制 DER 或 ASCII PEM,常见于类 Unix 系统。 - .CER
CRT 的替代形式(Microsoft Convention),Windows 环境下 .crt 可转为 .cer。
证书中只包含公钥,没有私钥。 - .KEY
用于公钥和私钥 PKCS#8,可被编码为二进制 DER 或 ASCII PEM。 - .PFX
带私钥的证书(包含公钥和私钥)。
由 Public Key Cryptography Standards #12,PKCS#12标准定义,包含了公钥和私钥的二进制格式的证书形式,以 pfx 或 p12 作为证书文件后缀名。
颁发实战
配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60[ca]
default_ca=CA_default
[CA_default]
policy=policy_match
new_certs_dir=newcerts
database=index.txt
default_md=default
serial=serial.txt
default_days=3650
[policy_match]
countryName=match
stateOrProvinceName=match
organizationName=match
organizationalUnitName=optional
commonName=supplied
emailAddress=optional
[policy_anything]
countryName=optional
stateOrProvinceName=optional
localityName=optional
organizationName=optional
organizationalUnitName=optional
commonName=supplied
emailAddress=optional
[test]
countryName=CN
stateOrProvinceName=GuangDong
organizationName=BGI
organizationalUnitName=MGIUS
commonName=MGIUSDICOM
emailAddress=jiangchuanbiao@genomics.cn
[req]
default_bits=1024
default_keyfile=private_key.pem
distinguished_name=req_distinguished_name
attributtes=req_attributes
[req_distinguished_name]
countryName=Country Name (2 letter code)
countryName_min=2
countryName_max=2
stateOrProvinceName=State or Province Name (full name)
localityName=Locality Name (eg, city)
organizationName=Organization Name (eg, company)
organizationalUnitName=Organizational Unit Name (eg, section)
commonName=Common Name (eg. YOUR name)
commonName_max=64
emailAddress=Email Address
emailAddress_max=40
[req_attributes]
challengePassword=A challenge password
challengePassword_min=4
challengePassword_max=20
unstructuredName=An optional company name自签名
1
2
3
4
5
6
7
8# 1.生成私钥
$ openssl genrsa -out server.key 2048
# 2.生成 CSR (Certificate Signing Request)
$ openssl req -subj "/C=CN/ST=GD/L=Shenzhen/O=Self/OU=ShuanglongTest/CN=Shuanglong/emailAddress=xjshuanglong@126.com" -new -key server.key -out server.csr
# 3.生成自签名证书
$ openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt私有 CA 签名
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 1.创建 CA 私钥
$ openssl genrsa -out ca.key 2048
# 2.生成 CA 的自签名证书
$ openssl req -subj "/C=CN/ST=Tianjin/L=Tianjin/O=Mocha/OU=Mocha Software/CN=Server CA/emailAddress=test@mochasoft.com.cn" -new -x509 -days 3650 -key ca.key -out ca.crt
# 3.生成需要颁发证书的私钥
$ openssl genrsa -out server.key 2048
# 4.生成要颁发证书的证书签名请求,证书签名请求当中的 Common Name 必须区别于 CA 的证书里面的 Common Name
$ openssl req -subj "/C=CN/ST=Tianjin/L=Tianjin/O=Mocha/OU=Mocha Software/CN=test2.sslpoc.com/emailAddress=test@mochasoft.com.cn" -new -key server.key -out server.csr
# 5.用 2 创建的 CA 证书给 4 生成的 签名请求 进行签名
$ openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
编程模式
- 建立 SSL 上下文环境后使用 BIO 进行通信
- 基于已建立的 Socket 连接创建 SSL 上下文环境
接口调用步骤: 参考 https://www.cnblogs.com/LittleHann/p/3741907.html
经验总结
类封装思想
参考自 DCMTK,环境上下文与连接分开封装:
DcmTLSTransportLayer 用于 SSL 上下文环境初始化、加载秘钥、加载证书、设置验证类型、设置加密套件;
DcmTLSConnection 用于 SSL 连接握手、重协商、请求认证、读写数据、关闭连接。思考结果:为确保 SSL 上下文环境只初始化一次,要么使全局/静态用标志位,要么干脆将上下文换件封装成静态方法,可与 SSL 通信环境同处一个类,也可分开各自为政。
命令行卡死 (Windows + GitBash)
执行命令openssl genrsa -des3 -out test.key 2048
后,进程假死,无法执行后续操作,只有结束当前进程。
在 windows 命令行中执行,会提示输入密码。
此时可通过传入参数传递密码,而不是通过标准输入传入密码。openssl genrsa -des3 -passout pass:mima -out test.key 2048
验证密码正确性:openssl rsa -in test.key -check
,根据提示输入密码短语。
注:使用 CMD,GitBash 似乎无效即使加入-passout pass:mima
。GitBash 执行 DCMTK 测试程序时出现卡死
通过任务管理器杀死 DCMTK 测试程序,GitBash 恢复命令行模式,即可继续操作。Conquest DICOM Server 添加 SSL 双向认证后,出现 SSL_read 阻塞现象,整个线程卡死且端口长时间占用无法释放。
服务器采用 select + block socket 模型,通常情况下不会阻塞,抓包发现服务端发出的应答包丢失,客户端超时重发仍无法收到确认包的情况下发送 RST 报文,但服务端阻塞线程依然无法退出,线程僵死且处于半连接状态。
初步确认为,OpenSSL 记录协议,需要读取到完整的记录才能解密,才认为 socket 读取完毕,否则一致阻塞。OpenSSL 自签名证书在 Chrome 下报告 Subject Alternative Name Missing 错误
1
2
3
4Certificate - Subject Alternative Name missing
The certificate for this site does not contain a Subject Alternative Name extension containing a domain name or IP address.
Certificate - missing
This site is missing a valid, trusted certificate (net::ERR_CERT_COMMON_NAME_INVALID).处理方法:生成证书时加入参数 -sha256 -extfile v3.ext。
v3.ext 内容如下: (DOMAIN 替换为域名)1
2
3
4
5
6
7
8
9
10authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = %%DOMAIN%%
DNS.2 = %%DOMAIN%%
IP.1 = %%IP%%
IP.2 = %%IP%%OpenSSL 的扩展用途:
1
2
3
4
5
6Client Authentication --- 1.3.6.1.5.5.7.3.2
Server Authentication --- 1.3.6.1.5.5.7.3.1
Secure Email ------------ 1.3.6.1.5.5.7.3.4
Code Signing ------------ 1.3.6.1.5.5.7.3.3
Timestamp Signing ------- 1.3.6.1.5.5.7.3.8
// 更多参考:https://oidref.com/1.3.6.1.5.5.7.3.2关于本地调试遇到的问题:
net::ERR_CERT_COMMON_NAME_INVALID
net::ERR_CERT_DATE_INVALID
处理方法:COMMON_NAME 代表证书中的服务器域名,使用正确的域名(生成签名请求时指定 Common Name 或者在 extfile 中添加 Subject Alternative Name, 本地环境建议加入 localhost);DATE INVALID 是指证书过期了,openssl x509 检查日期,注意,-days 参数值竟然可以是负数(时间往前推)。OpenSSL 查看代码签名文件信息
windows 代码签名文件扩展名为 .cer,属于 DER 编码格式:openssl.exe x509 -inform DER -text -noout -in sign.cer
参考网址
基于 OpenSSL 自建 CA 和颁发 SSL 证书
google-chrome – Chrome:无效的自签名SSL证书 – “Subject Alternative Name Missing”
OpenSSL自签发配置有多域名或ip地址的证书
https wireshark抓包——要解密出原始数据光有ssl 证书还不行,还要有浏览器内的pre-master-secret(内存里)
RSA与 Diffie-Hellman密钥交换 的区别
SSL/TLS协议详解(下)——TLS握手协议