密码学入门:对称加密与非对称加密、哈希函数、数字签名、数字证书
说实话,很多做身份认证的同学,一上来就撸代码,结果被密钥管理、签名验签搞得焦头烂额。我当年也踩过这个坑——有一次项目上线前,发现签名算法用错了,差点导致整个启动校验流程重做。所以这一章,咱们把密码学的几个核心概念彻底捋清楚。
对称加密:一把钥匙开一把锁
对称加密,说白了就是加密和解密用同一个密钥。你想想看,就像你家的门锁,用同一把钥匙锁门和开门。
常见的对称加密算法有:
- AES(Advanced Encryption Standard)—— 目前最主流,密钥长度支持128、192、256位
- DES —— 老古董了,56位密钥,现在基本被弃用
- 3DES —— DES的加强版,但效率低,逐渐被AES取代
- SM4 —— 国密标准,国内项目常见
核心特点:速度快、效率高,适合加密大量数据。但密钥分发是个大问题——你怎么安全地把密钥告诉对方?
我在项目中遇到过这样一个场景:设备固件升级包需要加密传输,用AES-256加密,密钥预置在设备中。但问题来了,如果密钥被逆向工程提取出来,整个批次设备都不安全了。这就是对称加密的天然短板。
非对称加密:公钥私钥,各司其职
非对称加密解决了密钥分发难题。它有一对密钥:公钥公开给所有人,私钥只有自己持有。
举个栗子:你把公钥发给全世界,大家用你的公钥加密消息,只有你能用私钥解密。反过来,你用私钥签名,大家用你的公钥验证签名。
常见算法:
- RSA —— 应用最广,密钥长度通常2048位或4096位
- ECC(椭圆曲线密码)—— 更短的密钥达到同等安全强度,适合嵌入式设备
- SM2 —— 国密椭圆曲线算法
| 特性 | 对称加密 | 非对称加密 |
|---|---|---|
| 密钥数量 | 1个 | 2个(公钥+私钥) |
| 速度 | 快(硬件加速友好) | 慢(比对称加密慢100-1000倍) |
| 密钥分发 | 困难 | 公钥可公开分发 |
| 典型用途 | 数据加密 | 密钥交换、数字签名 |
| 安全基础 | 密钥保密 | 私钥保密 |
实际工程中的做法:混合使用。用非对称加密传输对称密钥,再用对称密钥加密实际数据。既解决了密钥分发,又保证了加解密效率。
哈希函数:不可逆的指纹
哈希函数,也叫散列函数。它能把任意长度的数据,压缩成固定长度的摘要。而且这个过程是单向的——从摘要反推原始数据,理论上不可能。
我习惯把哈希函数比作「数字指纹」。你无法从指纹还原出一个人,但可以通过指纹唯一标识一个人。
常见哈希算法:
- MD5 —— 128位输出,已被证明不安全,别再用了
- SHA-1 —— 160位输出,也已不安全
- SHA-256 —— 256位输出,目前安全,推荐使用
- SM3 —— 国密哈希算法,256位输出
我曾经踩过的坑:早期一个项目用MD5做固件完整性校验,结果被碰撞攻击绕过了校验。从那以后,我所有项目强制要求SHA-256或以上。
哈希函数在身份认证中的典型用途:
- 密码存储 —— 不存明文密码,存密码的哈希值(加盐更安全)
- 数据完整性校验 —— 对比哈希值,判断数据是否被篡改
- 消息认证 —— 结合密钥做HMAC,验证消息来源和完整性
数字签名:电子世界的盖章
数字签名解决了三个问题:
- 身份认证 —— 确认签名者身份
- 不可否认性 —— 签名者不能抵赖
- 完整性 —— 签名后数据未被篡改
流程其实很简单:
- 发送方对消息做哈希,得到摘要
- 用私钥加密摘要,生成签名
- 接收方用公钥解密签名,得到摘要A
- 接收方对消息做哈希,得到摘要B
- 对比A和B,一致则验证通过
// 伪代码示例:签名与验签
// 签名
digest = SHA256(message)
signature = RSA_Encrypt(digest, privateKey)
// 验签
digestFromSig = RSA_Decrypt(signature, publicKey)
digestFromMsg = SHA256(message)
if digestFromSig == digestFromMsg:
print("签名验证通过")
else:
print("签名无效或数据被篡改")
注意:实际工程中不要自己实现签名算法,直接用OpenSSL、mbedTLS等成熟库。我见过有人手写RSA签名,结果填充方式搞错了,导致验签失败。
数字证书:把公钥和身份绑在一起
数字证书,说白了就是权威机构对公钥的背书。它解决了「你怎么确定这个公钥就是对方的?」的问题。
证书的核心结构(X.509标准):
- 证书持有者的身份信息(域名、组织名等)
- 证书持有者的公钥
- 证书颁发机构(CA)的数字签名
- 有效期、序列号等元数据
验证证书的流程:
- 拿到对方证书
- 用CA的公钥验证证书上的签名
- 签名有效,说明证书中的公钥确实属于证书中声明的实体
- 用这个公钥去验证对方的签名或加密通信
个人经验:在嵌入式启动校验中,我们通常把CA证书烧死在芯片ROM里。这样任何外部传入的证书,只要CA签名验证不通过,直接拒绝。这招能防住大部分证书伪造攻击。
知识体系总览
下面这张图,把本章的核心概念串起来了。你仔细看一遍,应该能理解它们之间的关系。
实际项目中的选择建议
嗯,这里我根据多年经验,给几个实用建议:
- 数据量大时:用AES-256加密,用RSA/ECC加密AES密钥
- 固件签名:用ECC签名(密钥短,适合嵌入式),哈希用SHA-256
- 密码存储:用bcrypt或Argon2,别直接用SHA-256(容易被彩虹表攻击)
- 证书验证:一定要校验证书有效期、吊销状态、域名匹配
我曾经犯过的错:有个项目为了省性能,把RSA密钥长度设成了1024位。结果一年后,安全审计直接判定不合规。现在我的底线是:RSA至少2048位,ECC至少256位。
密码学是身份认证的基石。这些概念搞懂了,后面讲启动校验、安全启动、证书链验证的时候,你就能快速上手。别急,咱们一步一步来。