第4章:密码学基础回顾——对称/非对称加密、哈希、数字签名
做密码改造审计,你绕不开密码学。这几类基础算法就像工具箱里的扳手、螺丝刀和扭矩仪——你得知道什么时候用哪个,怎么用,更要知道它们各自的死穴在哪。我在做合规审计时看过太多代码,明明用了AES,密钥却硬编码在源码里;明明上了数字签名,摘要算法却是MD5。嗯,这章咱们就捋一遍基础,把坑都标记出来。
4.1 对称加密:又快又痛
对称加密,说白了就是加密和解密用同一个密钥。像你家大门,锁和钥匙是一对一配好的。优点就一个字——快。大数据量、实时通信、磁盘加解密,基本都是对称算法的活儿。
常见的有AES、SM4。AES支持128/192/256位密钥,我一般推荐AES-256-GCM——带认证加密,密文被篡改能立刻发现。SM4是国标,接口参数跟AES差不多,但算法轮数、S盒设计不一样。
核心指标对照
| 算法 | 密钥长度 | 分组模式 | 审计要点 |
|---|---|---|---|
| AES | 128/192/256位 | ECB/CBC/CTR/GCM | 禁止ECB模式;必须使用随机IV |
| SM4 | 128位 | ECB/CBC/CTR/GCM | 检查是否使用国密规范填充(PKCS7) |
避坑指南
我曾经审计过一个互联网支付系统,日志里赫然出现了ECB模式加密的银行账号——相同明文块产生相同密文块,看你一眼就知道你转账了多少钱。ECB一定是安检红线,日志中出现就要标记为高危。
记得检查IV(初始化向量)是否随机生成且每次不同。我在项目中看到有人把IV写死成全零,加密结果成了“伪随机”,密钥猜测难度直接降低。好的习惯:IV必须是加密引擎产生的随机数,且至少12字节(GCM模式)或16字节(CBC模式)。
4.2 非对称加密:慢但安全
非对称加密有两个密钥——公钥和私钥。公钥可以公开,私钥只有自己持有。RSA、ECC、SM2是典型代表。非对称加密速度慢,一般不直接加密大数据,而是用来加密对称密钥(密钥交换)或数字签名。
// 示例:公钥加密对称密钥,对称密钥加密海量日志
byte[] sessionKey = AES.generateKey();
byte[] encryptedKey = RSA.encrypt(sessionKey, rsaPublicKey);
byte[] ciphertext = AES.encrypt(logData, sessionKey);
// 审计日志只需要记录:公钥指纹、加密后的sessionKey、ciphertext
RSA 2048位是目前合规底线, SM2 256位对标RSA 3072。我个人习惯把密钥长度作为合规检查第一项——低于2048位的RSA直接打回。
经验之谈
公钥必须经过证书链验证,不能直接信任代码里硬编码的字符串。我在某云平台的日志里见过直接写死的base64公钥,连证书都没——万一私钥泄露,整个系统的信任链就断了。
4.3 哈希函数:不是加密,是指纹
哈希函数把任意长度的输入变成固定长度的摘要。它不是加密——你不可能从哈希值反推出原文。审计里哈希最常用的场景是完整性校验:存哈希,然后验哈希。
现在MD5 / SHA-1必须禁用。我见过一个遗留系统还在用SHA-1校验日志完整性,被审计老师直接标注为「严重违规」。SHA-256是底线,国密SM3同等强度。
- SHA-256:输出256位,抗碰撞性满足一般合规要求
- SM3:输出256位,国密系列,很多政府/金融系统强制要求
- HMAC:带密钥的哈希,用于消息认证码(MAC)
哈希函数遇到冲突怎么办?概率极低,但不能完全忽略。对于重要日志,建议结合HMAC + 时间戳 + 随机数做防重放。
4.4 数字签名:防抵赖的定海神针
数字签名 = 哈希 + 非对称加密。先对原文哈希,再用私钥加密哈希值。接收方用公钥解密哈希值,再自己算一次原文哈希——两个对上,说明原文没被改过,且签名确实来自私钥持有者。
合规审计里,数字签名是日志防篡改、防抵赖的基石。我审核改造方案时,第一个问题总是:“签名算法是什么?密钥怎么管理的?”
| 签名算法 | 哈希搭配 | 合规状态 | 审计建议 |
|---|---|---|---|
| RSA-PSS | SHA-256 | 推荐 | 参数必须指定salt长度 |
| ECDSA | SHA-256 / SM3 | 推荐 | 曲线必须使用NIST P-256或SM2曲线 |
| SM2 | SM3 | 国密强制 | 检查签名值与公钥曲线一致性 |
| RSA-PKCS1v1.5 | SHA-1 | 禁用 | 迁移到RSA-PSS或ECDSA |
4.5 知识结构图:四类算法在审计中的位置
4.6 实战中的组合拳
密码改造不是单一算法的事。一套日志合规记录方案,通常这样配:
- 用AES-256-GCM加密日志原始内容
- 用SM2签名(如果客户要求国密)或ECDSA签名
- 对关键字段(时间、MAC地址、用户ID)用SM3或SHA-256计算哈希,作为防篡改指纹
- 整个日志链路的随机数(IV、nonce、盐值)全部使用硬件真随机数发生器生成
为什么要这么做?我遇到过一家公司,日志加密用了AES-256-CBC,签名却用了RSA-1024-PKCS1v1.5(SHA-1)。这就好比你给金库装了最厚的门,结果钥匙是纸糊的——攻击者只要哈希碰撞就能伪造签名。安全强度永远取决于最弱的一环。
4.7 审计日志里这些字段必须记录
| 字段 | 说明 | 示例值 |
|---|---|---|
| cipher_algorithm | 加密算法全称 | AES-256-GCM |
| key_id | 密钥标识(非明文) | key-v1-2024-001 |
| signature_algorithm | 签名算法 | ECDSA-P256SHA256 |
| hash_algorithm | 摘要算法 | SHA-256 |
| random_source | 随机数来源 | hw-rng / kernel-random |
| iv_nonce | IV或Nonce值(base64) | A8v3k... |
| session_key_enc | 加密后的会话密钥 | (base64长串) |
我个人习惯在记录里同时保存算法参数——比如AES的填充模式、GCM的tag长度、ECDSA的曲线名称。这些信息在事后验证时能救命,不会出现“我记得当时用的GCM,但审计人员查出来你日志里只写了AES”这种尴尬。
小技巧
检查日志里是否记录了「算法版本」。我曾经审计时发现同一系统不同模块用了不同AES密钥长度——日志里只写了AES,没写128还是256。后来加了个版本字段,以后一看就明白,合规检查也省力。
4.8 完整性保护链条
为什么哈希和数字签名要配合?单用哈希,攻击者可以同时篡改原文和哈希值。单用数字签名,没有哈希做摘要,签名数据量太大。所以日志记录链条一般是:
- 原文 → SHA-256摘要 → 对摘要做SM2签名 → 存(原文 + 签名值 + 算法信息)
- 校验时:重新计算摘要 → 用公钥验证签名 → 比对
嗯,绕了这几步,就是要确保日志不可否认、不可篡改。密码改造审计中,如果某个系统跳过了签名环节,直接用对称加密+哈希——那就是典型的不合规,直接扣分。
好了,这一章的基础回顾就到这。记住一句话:算法选对、密钥管好、随机数不瞎编——审计就能过八成。剩下的两成是流程和证据链,后面几章慢慢聊。