2. OpenSSL入门:安装、编译与核心配置
说实话,做PKI这一行,OpenSSL就是你的瑞士军刀。我入行那会儿,第一个任务就是编译OpenSSL——当时踩了不少坑,今天我把这些经验都摊开来讲。
2.1 安装与编译:别小看这一步
大部分Linux发行版都预装了OpenSSL,但版本往往偏旧。我个人习惯从源码编译,这样能精确控制功能开关和补丁。
2.1.1 快速安装(包管理器)
如果你只是测试或学习,用包管理器最省事:
# Debian/Ubuntu
sudo apt-get install openssl libssl-dev
# CentOS/RHEL
sudo yum install openssl openssl-devel
# macOS (Homebrew)
brew install openssl
小提示: 开发环境记得装
libssl-dev 或 openssl-devel,否则编译其他依赖OpenSSL的程序时会报错。我吃过这个亏。
2.1.2 源码编译(生产环境推荐)
为什么要自己编译?因为你可以选择是否支持SM2/SM3/SM4国密算法,也可以禁用掉不安全的旧协议。我曾经在客户现场遇到过因为OpenSSL版本太旧导致TLS 1.3握手失败的案例——从那以后,我坚持用源码编译。
# 下载源码(以1.1.1k为例)
wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
tar -xzf openssl-1.1.1k.tar.gz
cd openssl-1.1.1k
# 配置(启用国密、禁用旧协议)
./config --prefix=/usr/local/openssl \
--openssldir=/usr/local/openssl \
enable-sm2 enable-sm3 enable-sm4 \
no-ssl2 no-ssl3 no-rc5 no-md2
# 编译与安装
make -j$(nproc)
sudo make install
# 更新动态链接库
sudo ldconfig
注意: 编译前务必确认系统已安装
perl 和 make。另外,--prefix 和 --openssldir 最好保持一致,否则后续找配置文件会很痛苦。
2.2 常用命令概览:每天都会用到的那些
OpenSSL的命令行工具功能极其丰富,但日常工作中高频使用的其实就十几个。我把它们分成三类:
| 类别 | 命令 | 典型用途 |
|---|---|---|
| 密钥与证书 | genrsa / ecparam |
生成RSA或ECC私钥 |
req |
生成CSR或自签名证书 | |
x509 |
查看、转换、签名证书 | |
| 验证与调试 | verify |
验证证书链 |
s_client |
测试TLS握手(类似curl的调试版) | |
| 格式转换 | pkcs12 |
PKCS#12(.p12/.pfx)与PEM互转 |
rsa / ec |
私钥格式转换与加密 |
举个例子,查看一个证书的详细信息:
openssl x509 -in server.crt -text -noout
这个命令我每天至少用十次。你想想看,拿到一个证书,第一件事就是看它的签发者、有效期、SAN(主题备用名称)对不对。
避坑指南: 我曾经因为没加
-noout 参数,结果终端刷出了两屏的BASE64编码,差点以为证书坏了。记住,-text 输出人类可读信息,-noout 隐藏原始编码。
2.3 配置文件 openssl.cnf 解析
这是OpenSSL的灵魂。没有它,你连一个像样的CSR都生成不出来。我见过太多人直接跳过配置,结果生成的证书要么缺SAN,要么扩展字段全是错的。
2.3.1 配置文件结构
openssl.cnf 采用INI风格,分为几个核心段落:
[ req ] # 请求相关默认值
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ] # DN字段定义
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = State or Province Name
localityName = Locality Name
organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
[ req_ext ] # 请求扩展(SAN等)
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = example.com
DNS.2 = www.example.com
嗯,这里要注意:distinguished_name 指向的段落定义了证书主题(DN)的各个字段,而 req_extensions 指向的段落则定义了扩展属性——SAN就是放在这里的。
2.3.2 核心参数详解
| 参数 | 所在段落 | 作用 | 我的建议 |
|---|---|---|---|
default_bits |
[ req ] | 默认密钥长度 | 2048起步,敏感系统用4096 |
distinguished_name |
[ req ] | 指定DN模板段落 | 保持与组织规范一致 |
req_extensions |
[ req ] | 指定扩展模板段落 | 必须配置,否则没有SAN |
subjectAltName |
[ req_ext ] | 定义SAN列表 | 浏览器强制要求,不配就报错 |
basicConstraints |
[ v3_ca ] | 标记是否为CA证书 | CA证书必须配 CA:TRUE |
重要: 从Chrome 58开始,所有未包含
subjectAltName 的证书都会被标记为不安全。我去年帮一个客户排查问题,他们内部系统突然打不开,最后发现就是证书缺SAN。这个坑,千万别踩。
2.3.3 实战:生成一个带SAN的CSR
假设你有一个配置文件 my.cnf,内容如上。生成CSR的命令:
openssl req -new -key server.key -out server.csr -config my.cnf
验证CSR中的SAN:
openssl req -in server.csr -text -noout | grep -A 1 "Subject Alternative Name"
如果输出为空,说明你的配置没生效。我建议你检查一下 req_extensions 是否指向了正确的段落。
2.4 本章知识体系
下面这张图帮你理清OpenSSL的核心脉络:
核心要点: OpenSSL的安装决定了你能用什么算法,命令决定了你干活快不快,而配置文件决定了证书能不能用。我建议你先把 openssl.cnf 吃透,后面所有章节都离不开它。