安全基石:加密算法选型(AES、RSA、ECC)、哈希函数与数字签名在SDK中的应用

加密算法选型,说白了就是在给SDK打地基。地基不稳,上面功能再花哨也是白搭。我这些年看过的密钥泄漏案例,十有八九不是算法被攻破,而是选型或使用姿势不对。今天我们就聊聊对称加密、非对称加密、哈希和数字签名,在SDK里到底该怎么落地。

对称加密:AES 仍然是首选

AES 目前是行业标准,NIST 认证过,硬件加速也普遍支持。我个人习惯在 SDK 的本地缓存加密、会话密钥派生等场景里固定用 AES-256-GCM。为什么?

  • 安全性:GCM 模式提供认证加密,同时防篡改。
  • 性能:相比 Cipher Block Chaining (CBC) 模式,GCM 能并行处理,现代 CPU 有 AES-NI 指令集,速度很快。
  • 推荐参数:密钥长度 256 位,Nonce 12 字节,Tag 16 字节。
我曾在一个项目中,同事用 AES-128-CBC 配合固定 IV 做文件加密。结果密文前16字节一模一样,攻击者一看就知道是同一份文件。后来全改成 AES-256-GCM + 随机 Nonce,问题才解决。

非对称加密:RSA 还是 ECC?

RSA 和 ECC 都是主流,但适用场景不同。你想想看,RSA 的密钥对生成慢,签名验签也慢,但兼容性最好,很多老旧系统只认 RSA。ECC(椭圆曲线)呢?相同安全强度下密钥短、速度快,更适合移动端和 IoT 设备。

特性RSA-2048ECC-P256
密钥长度2048 bits256 bits
签名速度(相对)慢快
验签速度(相对)较快快
安全强度112 bits128 bits
兼容性极高中
推荐场景服务端签名、老旧系统移动端、密钥交换

在 SDK 里,我建议用 ECC 做密钥交换和数字签名,除非有强制合规要求。注意曲线选择要规范,例如 NIST P-256 或 Curve25519,别自己定义。我曾经见过有人用 secp256k1(比特币曲线)做通用签名,结果标准接口不兼容,导致验签失败。

哈希函数:别只记得 SHA-256

哈希不只是摘要计算。它在 SDK 里至少有三个用途:

  1. 完整性校验:验证数据在传输、存储中是否被篡改。
  2. 密钥派生:配合 HKDF 或 PBKDF2 从主密钥派生子密钥。
  3. 数字签名的基础:先哈希再签名,避免直接对大块数据签名。

常用的哈希族是 SHA-2(SHA-256/384/512),SHA-1 已经废弃 不要用。对于密码存储,要用专门的慢哈希如 bcrypt、scrypt 或 Argon2,别用 SHA-256 裸算。

哈希碰撞概率极低,但实际工程里遇到过因为哈希截断导致的签名验证绕过。例如有人用 MD5 的前 64 位做签名摘要,攻击者可以在 2^32 次尝试内找到碰撞。所以 数字签名用的哈希必须输出完整长度,且使用 SHA-256 以上。

数字签名:签名 ≠ 加密

很多新人容易把签名和加密搞混。签名是用私钥对消息摘要加密,任何人可以用公钥验证。它保证的是 不可否认性 和 完整性,不是机密性。

在 SDK 中,数字签名常见的场景:

  • 代码包签名(防止分发过程中被植入后门)
  • 令牌签名(JWT、Session )
  • 日志审计签名(确保审计记录不被篡改)

具体做法:先对数据做 SHA-256 哈希,再用私钥对哈希值签名,输出签名值。验签时计算同样的哈希,用公钥验证签名是否匹配。

// Go 示例:使用 ECDSA P256 签名
import (
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    "crypto/sha256"
    "crypto/x509"
)

func sign(data []byte, privateKeyPEM []byte) ([]byte, error) {
    // 1. 解析私钥
    block, _ := pem.Decode(privateKeyPEM)
    priv, err := x509.ParseECPrivateKey(block.Bytes)
    // 2. 哈希
    hash := sha256.Sum256(data)
    // 3. 签名
    r, s, _ := ecdsa.Sign(rand.Reader, priv, hash[:])
    signature := append(r.Bytes(), s.Bytes()...)
    return signature, nil
}

整个加密体系长什么样?

我把对称加密、非对称加密、哈希和签名之间的协作关系画成了下面这张图。你看一眼就明白了。

密钥权限审计SDK · 加密体系知识图谱 对称加密 (AES-GCM) 密钥 = 对称密钥 非对称加密 (RSA/ECC) 公钥 + 私钥 哈希函数 (SHA-256) 摘要 / 指纹 数字签名 (ECDSA / RSA-PSS) 完整性 + 不可否认 密钥管理 (KMS / HSM) 生成 / 存储 / 轮换 密钥加密 签名/验签 摘要输入 提供密钥 核心原则 • 哈希做完整性,签名做源认证,对称加密做机密性,非对称加密做密钥协商。 • 密钥永不离代码:使用 KMS 或 HSM 管理密钥,SDK 只引用标识。 • 定期轮换:对称密钥最长 1 年,签名密钥对最长 2 年。

避坑指南:实战中的三个教训

教训一:混淆密钥用途

我曾经见过一个 SDK,用同一对 RSA 密钥既做加密又做签名。攻击者拿到密文后,利用签名接口间接解密。一定要严格隔离密钥用途:加密密钥和签名密钥分开管理。

教训二:哈希+签名顺序错误

有人先签名后哈希,结果验签效率极低且容易被中间人绕过。正确顺序是:数据 → 哈希 → 签名。验签时先对收到的数据做同样哈希,再用公钥验证签名。

教训三:硬编码密钥

这是最蠢的错误,但也是最常见的。SDK 里绝不能把私钥写在配置或代码里。我曾审计一个项目,密钥直接 base64 编码嵌在 Android APK 里,反编译一下就能提取。正确的做法是用 KMS API 或密钥链(Keychain)按需获取。

总结:选型决策矩阵

算法用途SDK 内典型实现我的推荐
AES-256-GCM数据加密、会话密钥加密crypto/aes + crypto/cipher (Go)首选对称加密方案
ECC P-256数字签名、密钥交换crypto/ecdsa (Go)移动端/低功耗设备
RSA-3072兼容场景、证书签名crypto/rsa (Go)企业合规场景
SHA-256完整性校验、摘要crypto/sha256基础哈希标配
ECDSA / Ed25519签名与验签crypto/ed25519 (Go)性能敏感场景推荐

好了,这一章先到这里。选对算法只是第一步,后面我们还要聊密钥生命周期管理和权限模型。希望刚才那些踩过的坑能帮你少走弯路。