4、非对称密钥生成:RSA与ECC,以及PEM/DER那些事
说到设备证书签发,第一步就是生成密钥对。这一步要是没做好,后面全是白搭。我个人习惯把密钥生成比作「给设备办身份证」——你得先造一张独一无二的底卡,才能往上写信息。
这一章我们重点聊两件事:RSA vs ECC 怎么选,以及PEM 和 DER 这两种格式到底有什么区别。嗯,都是实战中绕不开的坑。
4.1 RSA 密钥对生成
RSA 是目前最通用的非对称算法。它的安全性基于大整数分解的难度。说白了,你选 2048 位还是 4096 位,直接决定了破解它需要多少年。
我在项目中遇到过不少客户,为了「省性能」选了 1024 位。结果呢?几年后等保测评直接不通过,全部重签。所以我现在建议:新系统至少 2048 位起,能上 4096 就别犹豫。
生成 RSA 私钥的命令很简单:
openssl genrsa -out device_rsa_private.pem 2048
从私钥中提取公钥:
openssl rsa -in device_rsa_private.pem -pubout -out device_rsa_public.pem
-aes256 参数可以给私钥加密。但注意,设备端如果每次重启都要输密码,那就尴尬了。我一般只在备份私钥时加密,生产环境用硬件安全模块(HSM)保护。
4.2 ECC 密钥对生成
ECC 是后起之秀。同样的安全强度,ECC 的密钥长度只有 RSA 的十分之一左右。举个例子:256 位的 ECC 密钥 ≈ 3072 位的 RSA 密钥。你想想看,这对 IoT 设备、嵌入式系统来说有多香。
但 ECC 有个坑——曲线选择。不是所有曲线都靠谱。我曾经见过一个项目用了 SECP160R1,结果被安全审计直接打回。现在业界公认的推荐曲线是 P-256(prime256v1) 和 P-384(secp384r1)。
生成 ECC 私钥:
openssl ecparam -genkey -name prime256v1 -out device_ecc_private.pem
提取公钥:
openssl ec -in device_ecc_private.pem -pubout -out device_ecc_public.pem
openssl ecparam -genkey 生成的密钥直接做签名。我踩过这个坑——某些 OpenSSL 版本生成的密钥不带参数集,导致验签失败。正确的做法是先生成参数文件,再基于参数生成密钥,或者用上面我给的命令。
4.3 RSA vs ECC:怎么选?
这个问题没有标准答案。我整理了一张对比表,你可以根据场景来选:
| 对比维度 | RSA | ECC |
|---|---|---|
| 安全强度(等效) | 2048 位 ≈ 112 位安全 | 256 位 ≈ 128 位安全 |
| 密钥生成速度 | 慢(尤其 4096 位) | 快 |
| 签名/验签性能 | 验签快,签名慢 | 签名快,验签稍慢 |
| 密钥长度 | 2048~4096 位 | 256~521 位 |
| 兼容性 | 最好,几乎所有系统支持 | 较好,但老旧系统可能不支持 |
| 推荐场景 | 服务端证书、CA 根证书 | IoT 设备、移动端、高性能场景 |
我个人习惯:CA 根证书用 RSA 4096,设备证书用 ECC P-256。这样既保证了根的安全冗余,又兼顾了设备的性能。
4.4 密钥格式:PEM vs DER
生成完密钥,你看到的文件可能是这样的:
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...
-----END PRIVATE KEY-----
这就是 PEM 格式。它本质上是 Base64 编码的 DER 数据,加上头和尾的标识行。而 DER 是纯二进制格式,肉眼看不懂。
为什么会有两种格式?说白了:PEM 方便人看和传输,DER 方便机器解析。
4.4.1 PEM 格式
- 文本格式,可以用记事本打开
- 以
-----BEGIN XXX-----开头,-----END XXX-----结尾 - 内容经过 Base64 编码,每行 64 个字符
- 支持注释行(以
-----BEGIN开头的不算注释) - 常用于 OpenSSL、Nginx、Apache 等
4.4.2 DER 格式
- 二进制格式,不可读
- 使用 ASN.1 编码规则(BER/DER)
- 文件体积比 PEM 小约 30%
- 常用于 Java 平台、Windows 证书存储、智能卡
4.5 格式转换实战
工作中经常需要在两种格式之间切换。我整理了几个最常用的转换命令:
4.5.1 PEM → DER
# 私钥转换
openssl rsa -in key.pem -outform DER -out key.der
# 公钥转换
openssl rsa -in key.pem -pubout -outform DER -out pub.der
# ECC 私钥转换
openssl ec -in ecc_key.pem -outform DER -out ecc_key.der
4.5.2 DER → PEM
# 私钥转换
openssl rsa -in key.der -inform DER -out key.pem
# 公钥转换
openssl rsa -in key.der -inform DER -pubout -out pub.pem
# ECC 私钥转换
openssl ec -in ecc_key.der -inform DER -out ecc_key.pem
4.6 密钥格式知识图谱
为了让你更直观地理解整个密钥生成与格式转换的脉络,我画了一张图:
4.7 验证密钥是否生成正确
生成完密钥,别急着用。先验证一下:
# 检查私钥是否完整
openssl rsa -in device_private.pem -check -noout
# 检查公钥是否匹配私钥
openssl rsa -in device_private.pem -pubout | openssl rsa -pubin -check -noout
# 查看密钥详细信息
openssl rsa -in device_private.pem -text -noout
对于 ECC:
# 检查 ECC 私钥
openssl ec -in ecc_private.pem -check -noout
# 查看曲线信息
openssl ec -in ecc_private.pem -text -noout | head -10
好了,密钥对生成和格式转换就聊到这里。记住一句话:选对算法、用对格式、做好备份,密钥管理就成功了一大半。