RSA 是什么
RSA 是 1977 年提出的公钥算法,安全性建立在大整数分解难题上,同一对密钥既能做签名也能做加密。工程上它运算慢、密文长,所以几乎不直接加密业务数据,而是用于签名,或用「RSA 加密对称密钥、对称算法加密正文」的混合加密。当前实现规范是 RFC 8017(PKCS #1 v2.2):加密推荐 OAEP 填充,签名推荐 PSS 填充。
基本信息
| 标准 | RFC 8017 / FIPS 186-5 |
|---|---|
| 数学基础 | 大整数分解难题,运算为模幂 |
| 常用密钥长度 | 2048(约 112 位强度)/ 3072(约 128 位)/ 4096 位 |
| 加密填充 | RSAES-OAEP(推荐);PKCS#1 v1.5 属遗留 |
| 签名填充 | RSASSA-PSS(推荐);RSASSA-PKCS1-v1.5 仍广泛兼容 |
| 典型用途 | 证书签名、代码签名、JWT RS256/PS256、密钥封装 |
典型使用场景
- TLS 证书签名:CA 用 RSA 私钥签服务器证书,握手时客户端验签
- SSH 登录密钥:rsa 2048/4096 密钥对仍是存量环境的主流形式
- 代码与固件签名:发布物签名后由安装端用公钥验签
- JWT 与开放平台接口:RS256/PS256 用于第三方校验令牌来源
- 接口字段加密:RSA 加密一次性对称密钥,正文交给 AES-GCM 处理
- 邮件与文档签名:S/MIME、PDF 签章的底层签名算法之一
生成与签名验签
生成与签名验签
# 生成 3072 位密钥(新系统推荐,2048 位用于兼容存量)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out rsa.key
# 导出公钥,交付对方验签用;私钥始终留在本机并 chmod 600
openssl rsa -in rsa.key -pubout -out rsa.pub
# 确认密钥长度与格式:BEGIN PRIVATE KEY 是 PKCS#8,BEGIN RSA PRIVATE KEY 是 PKCS#1
openssl rsa -in rsa.key -noout -text | head -2
# 私钥签名、公钥验签(先哈希再签名,SHA-256)
openssl dgst -sha256 -sign rsa.key -out sig.bin data.bin
openssl dgst -sha256 -verify rsa.pub -signature sig.bin data.bin填充方案对照
| 方案 | 用途 | 最小消息/上限 | 评价 |
|---|---|---|---|
| RSAES-OAEP | 加密 | 明文上限 k-2hLen-2 字节 | 新系统首选,可抵御 Bleichenbacher 类攻击 |
| RSAES-PKCS1-v1.5 | 加密 | 明文上限 k-11 字节 | 遗留兼容,解密端错误分类必须统一 |
| RSASSA-PSS | 签名 | 随哈希与盐长度固定 | 推荐,具备可证明安全性 |
| RSASSA-PKCS1-v1.5 | 签名 | 同上 | 兼容性最好,新系统若可用优先 PSS |
RSA 加密有严格长度上限:2048 位密钥配 SHA-256 的 OAEP 只能加密约 190 字节。超过上限必须走混合加密,不要试图分段裸加密(分段会带来顺序与重排问题)。
签名与加密应使用不同的密钥对,并在证书里通过 KeyUsage 标明用途。同一对密钥兼作两种用途会扩大暴露面,也让密钥轮换更困难。2048 位目前仍可用,但新签发材料建议直接上 3072 位;后量子迁移需要提前清点算法与数据留存周期。
混合加密流程(示意)
混合加密流程(示意)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.asymmetric import padding # OAEP
import os
# 发送方:随机生成数据密钥,用接收方 RSA 公钥只封装这把密钥
key = AESGCM.generate_key(bit_length=256)
nonce = os.urandom(12)
wrapped = peer_public.encrypt(key, padding.OAEP(mgf=padding.MGF1(hashes.SHA256()),
algorithm=hashes.SHA256(), label=None))
body = AESGCM(key).encrypt(nonce, payload, None) # 正文走 AEAD,快且防篡改
# 接收方:先用自己私钥解出数据密钥(失败统一报错),再解正文与校验标签密钥与格式常见组合
| 形式 | 典型文件 | 用途与注意点 |
|---|---|---|
| PKCS#8 私钥 | BEGIN PRIVATE KEY | 新工具链默认格式,OpenSSL 1.0 起推荐 |
| PKCS#1 私钥 | BEGIN RSA PRIVATE KEY | 老系统与部分 Java 库要求,需要时显式转换 |
| X.509 公钥 | BEGIN PUBLIC KEY | 交付对方验签或加密,不含任何私密信息 |
| SSH 公钥 | ssh-rsa AAAA... | 仅用于 SSH 登录,与 TLS 证书格式不能直接混用 |
| 证书内公钥 | openssl x509 -pubkey | 以证书为信任载体的场景,验签方只需信任证书 |
跨系统对接签名时,先对齐三件事:填充方案(PSS 还是 v1.5)、哈希算法、以及签名字节的编码方式。这三项任一处不一致都会表现为验签失败,而报错信息往往只写「签名无效」,排错成本很高。