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 证书存储、智能卡
核心区别一句话: PEM 是 DER 的 Base64 封装,加上了头尾标识。两者内容完全等价,可以无损互转。

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
避坑指南: 我曾经在对接某厂商的硬件安全模块时,对方要求 DER 格式,但我传过去的 PEM 文件他们也能解析。后来发现他们的 SDK 内部做了自动识别。但别指望所有系统都这么智能——明确要求什么格式就给什么格式,别偷懒。

4.6 密钥格式知识图谱

为了让你更直观地理解整个密钥生成与格式转换的脉络,我画了一张图:

非对称密钥生成与格式转换流程图 非对称密钥生成与格式转换流程 选择算法 RSA 2048/4096 ECC P-256/P-384 生成私钥 (PEM) 生成私钥 (PEM) 提取公钥 (PEM) 提取公钥 (PEM) PEM ↔ DER 互转 PEM ↔ DER 互转 说明:PEM 是 Base64 编码的 DER,两者内容等价。生产环境建议私钥用 PEM,公钥按对接方要求选择。

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
重要提醒: 私钥文件一旦丢失或损坏,所有已签发的证书都得作废。我见过最惨的一次——某公司运维误删了 CA 私钥,几百台设备的证书全部要重新签发。所以,生成后立即备份,备份要加密,加密的备份要异地存储。

好了,密钥对生成和格式转换就聊到这里。记住一句话:选对算法、用对格式、做好备份,密钥管理就成功了一大半。