对称密钥 vs 非对称密钥:选哪个?怎么选?

好,这一章咱们来聊聊 KMS 里最核心的基础概念——对称密钥和非对称密钥。说实话,很多刚接触 KMS 的同学会问:“不都是加密吗?分这么细干嘛?”嗯,我当时刚学 AWS KMS 时也这么想,直到有一次在生产环境上踩了坑……

密钥的类型决定了你能用它做什么、不能做什么,尤其是在跨账号共享的场景下。咱们先理清两者的本质区别,再聊怎么选。

对称密钥:一把钥匙开一把锁

对称密钥,顾名思义——加密和解密用的是同一个密钥。你想想看,就像你家大门钥匙,锁门和开门是同一把。

在 KMS 中,默认创建的 Customer Managed Key(CMK)就是对称密钥。使用流程很简单:

  1. 调用 GenerateDataKey 或 Encrypt API,传入密钥 ID
  2. KMS 用你指定的密钥进行加密,返回密文
  3. 解密时调用 Decrypt API,传入同样的密文
  4. KMS 用同一份密钥材料解密

它的优势是速度快、性能好。我去年帮一个金融客户做数据湖加密,每天处理 TB 级数据,用对称密钥加密,延迟几乎可以忽略。但痛点也很明显——密钥必须安全传递,一旦泄露,所有数据都危险。

⚠️ 特别注意:对称密钥不支持跨账号直接授权解密。如果你要让另一个账号解密,只能用密钥策略 + 授权(Grant)的方式,或者轮换密钥材料。我曾经见过一个团队直接把对称密钥的访问权限配到了其他账号的 IAM Role 上,结果死活解不开——因为 KMS 的对称密钥只能用于当前账号的 kms:Decrypt。

非对称密钥:公钥加密,私钥解密

非对称密钥是一对密钥:公钥(Public Key)和私钥(Private Key)。公钥可以公开分发,私钥必须保密。说白了,你用我的公钥加密,只有我能用私钥解密。

KMS 支持创建 RSA 和 ECC 类型的非对称密钥。你创建时选择密钥用途:ENCRYPT_DECRYPT 或 SIGN_VERIFY。

💡 我的习惯:如果只是单纯的数据加密解密,我会优先用对称密钥。非对称密钥我主要用于签名验签,或者跨账号的场景——因为公钥可以直接导出,不用走复杂的授权流程。

非对称密钥在跨账号共享时的优势很明显:你把公钥给目标账号,对方可以直接用公钥加密数据,然后把密文发回来,你再用自己的私钥解密。整个过程中,你的私钥从未离开过你的 AWS 账号,安全边界清晰。

关键差异对比

为了让你一目了然,我把最核心的差异整理成了一张表:

对比维度 对称密钥 非对称密钥
密钥数量 1 个(加解密共用) 2 个(公钥 + 私钥)
性能 极快(硬件加速可达 Gbps 级别) 慢(RSA 2048 解密约 1-2ms)
密钥分发 需要安全通道 公钥可明文公开
跨账号使用 只能通过 Grant/策略,且对方不能直接调用 Decrypt 对方用公钥加密,你解密;也可以你签名,对方验签
典型用途 大量数据加密、S3 服务端加密、RDS 加密 数字签名、证书管理、跨账号加密传输
KMS API 示例 Encrypt / Decrypt Encrypt / Decrypt + GetPublicKey / Sign / Verify
密钥轮换 自动轮换(每年一次)或手动 仅手动创建新密钥对

什么时候该用哪种?

我个人的判断原则很简单——

  • 如果数据量很大,且加密解密都在一个账号内完成:无脑用对称密钥。性能好,编程接口简单。
  • 如果需要在不同账号之间加密传输数据:非对称密钥更合适。你想想看,你不用给对方任何敏感权限,只需要导出公钥。
  • 如果是数字签名/验签场景:必须用非对称密钥。对称密钥没法做签名,因为只有一把钥匙,你无法证明签名一定来自特定的人。

还有一个容易被忽略的点——密钥长度和算法。对称密钥现在 AWS 默认是 256 位 AES-GCM;非对称密钥支持 RSA 2048、3072、4096,以及 ECC P-256、P-384、P-521 和 secp256k1。ECC 的密钥更短但同样安全,性能也更好。

整体选择框架

下面这张图是我自己总结的决策流程,帮你快速定位:

对称密钥 vs 非对称密钥 · 选择决策树 需要加密/解密还是签名? 纯加密/解密 数字签名/验签 数据量大?同一账号内使用? 必须用非对称密钥 选对称密钥 AES-256-GCM 选非对称密钥 RSA 或 ECC 📌 实用建议 • 跨账号加密传输数据:优先非对称密钥(公钥给对方) • 同账号大量数据加密:始终选对称密钥,性能碾压 • 密钥轮换需求高:对称密钥支持自动轮换,省心省力 • 记住:对称密钥不能做签名,非对称密钥做签名更灵活

实际案例:跨账号数据加密的两种姿势

场景一:用对称密钥 + Grant

你有一个对称密钥在账号 A,希望账号 B 能用它加密 S3 文件。我之前就是这么做的:

  • 账号 A 创建 Grant,授权账号 B 的 IAM Role 使用 Encrypt
  • 账号 B 调用 kms:Encrypt 时带上 Grant
  • 弊端:账号 B 不能解密,只能加密。解密必须由账号 A 来干

当时客户想实现“B 加密后,A 解密”的流程,用对称密钥的 Grant 方式确实可行,但每次调用都得传 Grant ,代码稍显啰嗦。

场景二:用非对称密钥 + 公钥导出

后来我换成了非对称密钥方案:

  1. 账号 A 创建 RSA 非对称密钥(用途:ENCRYPT_DECRYPT)
  2. 调用 GetPublicKey 导出公钥(公钥本身是公开的)
  3. 把公钥给账号 B(随便放 S3、Parameter Store 都行)
  4. 账号 B 用公钥加密敏感数据,得到 base64 密文
  5. 账号 B 把密文传给账号 A,账号 A 调用 Decrypt 解密

这样账号 B 根本不需要任何 KMS 权限,完全不用配置密钥策略。代码也更清爽。

🔑 核心区别一句话总结:对称密钥像你的日记本锁——自己写自己看。非对称密钥像信箱——别人投信(用公钥),只有你能取信(用私钥)。

避坑指南

最后分享几个我在项目中踩过的坑:

  • 坑一:我曾经以为对称密钥也能跨账号直接解密。结果发现 KMS 的 Decrypt 只能在密钥所属账号内调用。跨账号解密必须用授权(Grant)或者让目标账号先调用 ReEncrypt 到自己账号的 CMK。
  • 坑二:非对称密钥的公钥虽然可以导出,但注意公钥格式是 DER 编码的 SubjectPublicKeyInfo。如果你需要用 OpenSSL 加工,记得先转 PEM 格式。我的做法是用 openssl pkey -pubin -inform DER -outform PEM 转换。
  • 坑三:非对称密钥只支持 ENCRYPT_DECRYPT 和 SIGN_VERIFY 两种用途,不能混用。创建时就选好,后面改不了。我见过有人创建了 RSA 签名密钥,然后想拿它加密,结果 API 直接报错。