2、签名算法基础(上):对称加密与非对称加密、哈希函数(MD5、SHA-256)、HMAC原理

聊签名服务,绕不开加密和哈希。很多新手一上来就纠结「到底用哪种算法」,其实没那么玄乎。我做了这么多年后端,总结下来就一句话:对称加密管传输,非对称加密管身份,哈希函数管完整性。咱们一个一个拆开说。

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

对称加密,说白了就是加密和解密用同一把密钥。你想想看,就像你家里的大门,用一把钥匙锁上,也用同一把钥匙打开。简单、快,这是它的优点。

常见的对称加密算法有 AES、DES、3DES。现在业界主流是 AES-256,我个人习惯只要涉及敏感数据传输,优先选它。

核心特点:

  • 加密速度快,适合大数据量
  • 密钥长度短(128/192/256位)
  • 最大痛点:密钥分发困难

我在项目中遇到过一个问题:两个微服务之间需要加密通信,密钥写死在配置文件里。结果运维不小心把配置库权限设成了公开,密钥直接裸奔。嗯,这里要注意——对称加密的密钥管理,比算法本身难十倍。

算法 密钥长度 安全性 速度
DES 56位 已淘汰 快
3DES 112/168位 中等 慢
AES 128/192/256位 高 快

实战建议:签名服务内部通信,我推荐用 AES-256-GCM 模式。它自带认证标签,能防篡改,省掉你额外算 HMAC 的麻烦。

2.2 非对称加密:公钥私钥两把锁

非对称加密就很有意思了。它有一对密钥:公钥公开,私钥自留。公钥加密的数据只有私钥能解,私钥签名的数据只有公钥能验。这解决了对称加密「密钥分发」的痛点。

常见的算法有 RSA、ECC(椭圆曲线)。RSA 最经典,但密钥越长性能越差。ECC 用更短的密钥达到同等安全强度,现在越来越流行。

核心应用场景:

  • 加密通信:客户端用服务器公钥加密数据,只有服务器私钥能解
  • 数字签名:服务器用私钥签名,客户端用公钥验签

我曾经踩过一个坑:用 RSA 加密大文件,结果直接报错。为什么?因为 RSA 有长度限制,1024位密钥最多加密117字节。所以实际项目中,非对称加密通常只用来加密对称密钥,真正的数据用 AES 加密。这叫「混合加密」,HTTPS 就是这么干的。

对比项 对称加密 非对称加密
密钥数量 1个 2个(公钥+私钥)
速度 快 慢(慢100-1000倍)
密钥分发 困难 容易(公钥可公开)
典型算法 AES RSA、ECC

2.3 哈希函数:数据的指纹

哈希函数,你可以把它理解成给数据算一个「指纹」。不管输入多大,输出固定长度。而且有个重要特性:不可逆——从哈希值推不出原始数据。

签名服务里,哈希函数主要用来做两件事:

  • 数据完整性校验:对比哈希值就知道数据有没有被改过
  • 签名预处理:先哈希再签名,提高效率

MD5:老将退役

MD5 输出128位(32个十六进制字符)。以前很流行,但现在已经被攻破了。2004年就有学者找到了碰撞——两个不同文件算出相同 MD5。我建议:新系统绝对不要用 MD5,除非你只是做文件去重这种非安全场景。

避坑指南:我曾经接手过一个老项目,用 MD5 做支付签名。结果被黑客伪造了请求,直接导致线上事故。从那以后,我对 MD5 彻底拉黑。

SHA-256:当前主力

SHA-256 输出256位(64个十六进制字符),属于 SHA-2 家族。目前没有已知的有效碰撞攻击,是签名服务的标配。

// 一个简单的 SHA-256 示例(伪代码)
输入: "hello"
输出: "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

// 哪怕只改一个字符
输入: "hellp"
输出: "6f8db599de30fab0b6f12c8b5b5b1c8f1c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c"

你看,输入只差一个字母,输出完全不一样。这就是哈希函数的「雪崩效应」。

2.4 HMAC:带密钥的哈希

HMAC(Hash-based Message Authentication Code)是哈希函数的进阶版。它给哈希加了一把「密钥」,只有知道密钥的人才能验证消息的完整性。

普通哈希有个问题:攻击者可以同时篡改数据和哈希值。但 HMAC 不一样,它把密钥混进哈希计算,攻击者没有密钥就伪造不了合法的 HMAC。

HMAC 的计算过程(简化版):

  1. 把密钥填充到哈希块长度
  2. 密钥与 ipad(内部填充)异或,再拼接消息,做第一次哈希
  3. 密钥与 opad(外部填充)异或,再拼接第一次哈希结果,做第二次哈希
// HMAC-SHA256 示例(伪代码)
HMAC-SHA256(key, message) = 
  SHA256((key ⊕ opad) || SHA256((key ⊕ ipad) || message))

// 实际使用
key = "my-secret-key"
message = "amount=100×tamp=1700000000"
result = HMAC-SHA256(key, message)
// 输出: "a1b2c3d4..."

我个人的习惯是:API 签名首选 HMAC-SHA256。它比直接 RSA 签名快得多,而且密钥管理比对称加密简单。很多大厂的开放平台,比如阿里云、腾讯云,用的就是 HMAC 签名方案。

2.5 知识体系总览

下面这张图把本章的核心逻辑串起来了。你看一遍,应该能对签名算法的全貌有个清晰认识。

签名算法基础:知识体系总览 对称加密 非对称加密 哈希函数 AES-256 / DES RSA / ECC MD5 / SHA-256 特点 速度快,密钥分发困难 适合大数据量加密 特点 速度慢,密钥分发容易 适合数字签名/密钥交换 特点 不可逆,固定长度输出 适合完整性校验 HMAC = 哈希函数 + 密钥 兼具哈希的效率和密钥的安全性 实战推荐 API 签名首选 HMAC-SHA256

2.6 实战选型建议

说了这么多,到底怎么选?我总结了一个简单的决策树:

  • 要加密大量数据? → 用 AES-256-GCM
  • 要安全分发密钥? → 用 RSA/ECC 做密钥交换
  • 要校验数据完整性? → 用 SHA-256
  • 要做 API 签名? → 用 HMAC-SHA256

一个小技巧:HMAC 的密钥不要直接用字符串。我习惯先对密钥做一次 SHA-256 哈希,再用哈希结果做 HMAC 密钥。这样能保证密钥长度正好是 32 字节,避免填充带来的性能损耗。

好了,这一章的基础知识就到这里。你把这些概念吃透了,后面讲具体签名流程的时候,理解起来会轻松很多。