4、OpenSSL实战:安装、密钥生成与自签名证书
说实话,搞设备证书注入,OpenSSL 是绕不过去的工具。我见过不少团队,买昂贵的 HSM,用商业 CA,结果底层连 OpenSSL 的基本操作都跑不通——证书链一乱,设备全变砖。这一章,咱们就把 OpenSSL 的看家本领练扎实。
4.1 安装 OpenSSL:别小看这一步
不同平台安装方式不一样。我个人的习惯是,在开发机上用最新稳定版,在产线工控机上用 LTS 版。为什么呢?因为产线环境一跑就是三五年,升级 OpenSSL 可能牵连整个系统库。
| 平台 | 安装命令 | 备注 |
|---|---|---|
| Ubuntu/Debian | sudo apt install openssl libssl-dev |
记得装 dev 包,编译工具链需要头文件 |
| CentOS/RHEL | sudo yum install openssl openssl-devel |
老版本可能默认 1.0.2,建议升级 |
| macOS | brew install openssl |
系统自带的是 LibreSSL,别混用 |
| Windows | 下载 Win64 OpenSSL 安装包 | 建议选 Light 版,够用 |
openssl version 看看输出。我遇到过有人装了 1.1.1 却以为自己在用 3.0,结果 ECDSA 签名死活对不上——版本号一定要确认。
4.2 生成 RSA 密钥对
RSA 是目前兼容性最好的算法。设备端芯片大多内置 RSA 硬件加速器,2048 位是行业标配。我建议别用 1024 位,NIST 早就弃用了。
4.2.1 生成私钥
# 生成 2048 位 RSA 私钥,输出为 PEM 格式
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out device_rsa_priv.pem
# 查看私钥详情
openssl pkey -in device_rsa_priv.pem -text -noout
这里有个细节:genpkey 是推荐的新命令,老式的 genrsa 也能用,但新工具链更统一。我在项目中见过有人用 genrsa 生成的密钥,在 ARM 交叉编译环境里解析失败——因为 OpenSSL 版本差异导致 PEM 头信息格式不同。
4.2.2 提取公钥
# 从私钥提取公钥
openssl pkey -in device_rsa_priv.pem -pubout -out device_rsa_pub.pem
# 查看公钥
openssl pkey -pubin -in device_rsa_pub.pem -text -noout
私钥文件权限必须设为 600 或 400。我曾经在客户产线看到私钥是 644 权限,任何用户都能读——这等于把设备大门钥匙挂在门外。生产环境建议用 HSM 或 TEE 保护私钥,文件系统只存公钥。
4.3 生成 ECC 密钥对
ECC 的优势是密钥短、性能好。IoT 设备资源受限,ECC 256 位等效 RSA 3072 位安全强度。我个人更倾向 ECC,尤其是新设计的设备。
4.3.1 选择曲线
主流曲线就两条:prime256v1(也叫 secp256r1)和 secp384r1。NIST 推荐前者,国密标准用 SM2(曲线参数不同)。我建议 IoT 设备统一用 prime256v1,兼容性最好。
# 列出所有支持的曲线
openssl ecparam -list_curves
# 生成 prime256v1 私钥
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1 -out device_ecc_priv.pem
# 查看私钥
openssl pkey -in device_ecc_priv.pem -text -noout
4.3.2 提取公钥
# 提取 ECC 公钥
openssl pkey -in device_ecc_priv.pem -pubout -out device_ecc_pub.pem
嗯,这里要注意:ECC 公钥比 RSA 短很多,256 位 ECC 公钥只有 65 字节(未压缩格式)。这对设备存储和传输都是利好。
4.4 创建自签名证书
自签名证书,说白了就是自己给自己当 CA。开发阶段、内部测试、设备初始身份凭证,都用得上。但生产环境千万别拿自签名证书当 CA 证书用——设备无法验证上级 CA 的合法性。
4.4.1 生成证书签名请求(CSR)
# 使用 RSA 私钥生成 CSR
openssl req -new -key device_rsa_priv.pem -out device.csr -subj "/CN=MyDevice001/O=MyCompany/C=CN"
# 查看 CSR 内容
openssl req -in device.csr -text -noout
-subj 参数直接指定 DN(Distinguished Name),避免交互式输入。产线批量注入时,脚本里必须用这种方式。我见过有人手动输入 DN,结果 1000 台设备有 3 台 CN 拼写错误——排查起来想哭。
4.4.2 自签名证书
# 使用 CSR 和私钥生成自签名证书,有效期 10 年
openssl x509 -req -days 3650 -in device.csr -signkey device_rsa_priv.pem -out device_cert.pem
# 直接一步到位(跳过 CSR)
openssl req -x509 -days 3650 -key device_rsa_priv.pem -out device_cert.pem -subj "/CN=MyDevice001/O=MyCompany/C=CN"
第二种方式更简洁,产线脚本常用。但如果你需要保留 CSR 用于审计,就分开做。
4.4.3 验证证书
# 查看证书详情
openssl x509 -in device_cert.pem -text -noout
# 验证证书与私钥是否匹配
openssl x509 -in device_cert.pem -noout -modulus | openssl md5
openssl pkey -in device_rsa_priv.pem -noout -modulus | openssl md5
# 两个 md5 值必须一致
自签名证书的 Issuer 和 Subject 是同一个实体。它没有上级 CA 背书,所以浏览器会报“不安全”。但在设备内部,只要预置了该证书的指纹(fingerprint),设备之间就能建立信任。
4.5 知识体系总览
下面这张图把本章的核心逻辑串起来了。你想想看,从密钥生成到证书签发,每一步都有坑。
4.6 常见问题与避坑
- PEM 与 DER 混淆:PEM 是 Base64 编码的文本格式,DER 是二进制。设备端解析时,有些 SDK 只支持 DER。转换命令:
openssl x509 -in cert.pem -outform DER -out cert.der - 证书有效期:开发测试用 3650 天(约 10 年)没问题。但产线设备证书建议 2-3 年,配合证书轮换策略。我见过有人设了 20 年有效期,结果设备退役了证书还没过期——管理上很尴尬。
- 密钥格式兼容:有些嵌入式库(如 mbedTLS)要求 PKCS#1 格式的 RSA 私钥,而 OpenSSL 默认输出 PKCS#8。转换:
openssl rsa -in key.pem -out key_pkcs1.pem - 随机数质量:OpenSSL 默认使用 /dev/urandom,够用。但嵌入式设备如果缺乏硬件熵源,生成密钥可能卡住。我建议在产线脚本里加
-rand参数指定熵源文件。
写一个 Makefile 或 shell 脚本,把密钥生成、CSR 创建、证书签发串起来。参数化设备序列号、有效期、算法类型。这样每次跑脚本,输出都是标准化的。产线工人只需要插上设备、执行脚本、拿走证书文件——零出错。