创建非对称密钥:RSA/ECC密钥对创建、签名验证场景、密钥用途限制

非对称密钥,说白了就是“一对钥匙”——公钥可以公开,私钥必须保密。在 KMS 里,创建非对称密钥并不是简单的一句 aws kms create-key 就完事了。你选算法、定用途、考虑场景,每一步都有讲究。

我今天跟你聊聊怎么在 KMS 里创建 RSA 和 ECC 密钥对,什么时候用签名,什么时候用加密,以及那些容易踩的坑。

先搞清楚:非对称密钥的两种“人设”

KMS 的非对称密钥有两大用途:

  • 加密/解密 —— 用公钥加密,私钥解密。适合少量数据或作为信封加密的密钥封装。
  • 签名/验证 —— 用私钥签名,公钥验证。适合代码签名、文档验真、身份认证。

关键限制:一个非对称密钥一旦创建,用途就固定了。你不能拿一个加密用的密钥去签名,反过来也不行。

⚠️ 注意:我见过有人为了省事,创建一个密钥又想加密又想签名,结果发现 KMS 不支持。你必须在创建时指定 KeyUsage 为 ENCRYPT_DECRYPT 或 SIGN_VERIFY。选错了只能删除重建。

创建 RSA 密钥对:经典但开销大

RSA 在非对称加密里是元老,兼容性好。但它的私钥运算很慢,密钥越长越慢。

  1. 选择密钥规格:RSA_2048、RSA_3072、RSA_4096。4096 更安全,但性能消耗也翻倍。我一般推荐 RSA_2048 用于加密,RSA_3072 用于签名(因为签名需要更高安全余量)。
  2. 指定用途:若用于加密,KeyUsage=ENCRYPT_DECRYPT;若用于签名,KeyUsage=SIGN_VERIFY。
  3. 执行创建:AWS CLI 示例
# 创建一个RSA_2048加密密钥
aws kms create-key \
    --key-usage ENCRYPT_DECRYPT \
    --key-spec RSA_2048 \
    --description "RSA 2048 for envelope encryption"

# 创建一个RSA_3072签名密钥
aws kms create-key \
    --key-usage SIGN_VERIFY \
    --key-spec RSA_3072 \
    --description "RSA 3072 for code signing"

返回的 KeyId 就是你的非对称密钥 ID。注意:KMS 不会直接给你私钥明文,私钥永远留在 KMS 里。你需要的是公钥,可以通过 get-public-key 拿到。

创建 ECC 密钥对:轻快但算法多

ECC 在同等安全强度下,密钥更短、运算更快。KMS 支持多种椭圆曲线:

密钥规格 安全强度(等效RSA) 典型用途
ECC_NIST_P256 RSA-3072 左右 签名验证
ECC_NIST_P384 RSA-7680 左右 高安全签名
ECC_NIST_P521 RSA-15360 左右 最高安全签名
ECC_SECG_P256K1 与P256相当 区块链/比特币签名
SM2 国密标准 中国合规场景

创建命令和 RSA 类似,只是 --key-spec 换成 ECC 规格:

# 创建P256签名密钥
aws kms create-key \
    --key-usage SIGN_VERIFY \
    --key-spec ECC_NIST_P256 \
    --description "ECC P256 for JWT signing"

# 注意:ECC密钥目前只支持SIGN_VERIFY,不支持加密/解密
# 如果你试图用ECC做加密,KMS会直接报错
💡 我的一点经验:如果你在 IoT 设备场景,ECC 比 RSA 更友好——签名快、公钥短。我曾经在车联网项目里从 RSA 切到 ECC,签名性能提升了将近 5 倍。

密钥用途限制:你选对了吗?

KMS 对非对称密钥的用途限制非常严格。一张表说清楚:

KeyUsage 值 支持的操作 典型密钥规格 注意事项
ENCRYPT_DECRYPT 加密、解密 RSA_2048, RSA_3072, RSA_4096, SM2 数据最大不超过 4096 字节(RSA 密钥长度决定)
SIGN_VERIFY 签名、验证 RSA_2048+, ECC 系列, SM2 ECC 只能签名,不可加密;RSA 签名和加密可以分开创建
ENCRYPT_DECRYPT + SIGN_VERIFY ❌ 不支持 — 不能同时使用,创建时必须二选一

签名验证场景实战:代码签名流程

假设你用 ECC P256 密钥给一段消息签名,外部伙伴用你的公钥验证。我手写一个伪流程:

  1. 创建签名密钥(已完成)
  2. 获取公钥
  3. 客户端签名(消息摘要)
  4. 服务器验证
# 获取公钥并导出
aws kms get-public-key \
    --key-id 1234abcd-12ab-34cd-56ef-1234567890ab \
    --output json | jq -r '.PublicKey' | base64 -d > my_public_key.der

# 签名
aws kms sign \
    --key-id 1234abcd-12ab-34cd-56ef-1234567890ab \
    --message "Hello, KMS!" \
    --message-type RAW \
    --signing-algorithm ECDSA_SHA_256 \
    --output text --query Signature | base64 -d > signature.bin

# 验证(通常由另一方执行)
aws kms verify \
    --key-id 1234abcd-12ab-34cd-56ef-1234567890ab \
    --message "Hello, KMS!" \
    --message-type RAW \
    --signing-algorithm ECDSA_SHA_256 \
    --signature fileb://signature.bin

避坑指南:我曾经犯过一个低级错误——在签名时用了 --message 直接传十六进制值,结果 KMS 认为那是原始字节,验证时怎么都对不上。正确的做法是统一用 raw bytes,或者指定 --message-type DIGEST 并自己计算哈希。建议新手一律用 RAW 模式,让 KMS 帮你处理摘要。

核心逻辑图:非对称密钥从创建到使用

下面这张图把整个流程串起来,你一看就明白。

非对称密钥生命周期(创建 → 用途 → 场景) 创建非对称密钥对 用途:加密/解密 用途:签名/验证 公钥加密(Encrypt) 私钥解密(Decrypt) 私钥签名(Sign) 公钥验证(Verify) ⚠️ 一个密钥只能选一种用途,创建后不可更改 ECC密钥仅支持 SIGN_VERIFY,不支持加密

看到没?创建密钥时你就得想清楚最终场景。加密路径只有 RSA(或 SM2),签名路径 RSA 和 ECC 都行。个人建议:如果是微服务间的令牌签名,选 ECC P256;如果是传统加密数据,选 RSA 2048。

几点额外提醒

  • 密钥轮换:非对称密钥也支持自动轮换(仅对称密钥自动轮换?不对,KMS 非对称密钥不支持自动轮换,需手动创建新密钥并迁移引用)。这个我们在后面章节细讲。
  • 跨区域问题:非对称密钥跨区域使用时,你得在目标区域也创建同名密钥(或使用 AWS KMS Multi-Region Keys)。我曾在一次全球部署中吃了亏——忘了在东京区域创建密钥,结果签名验证全部超时。
  • 成本:非对称密钥比对称密钥贵不少,按调用次数计费。没事别频繁调用 Encrypt 或 Sign,能用对称密钥做信封加密的场景尽量用对称。
💡 我的习惯:每次创建非对称密钥后,我都会把 KeyId、用途、创建日期记在一个安全 note 里。半年后再看,自己都忘了哪个密钥是干嘛用的。人嘛,金鱼记忆。