第1章 密码学基础:对称加密、非对称加密、哈希函数、数字签名概述

说实话,不少做SDK的同学一上来就踩坑——把加密算法随便封装一下就往外抛。结果呢?密钥没管理好,算法选错,签名验证漏掉边界……我在架构评审里看到过太多次这种问题了。所以这一章,咱们先把基础打牢。

你想想看,密码学这个东西,说白了就是“通信双方在不安全的信道上安全地传东西”。那怎么保证安全?主要就靠四样东西:对称加密、非对称加密、哈希函数、数字签名。下面我一个一个说。

1.1 对称加密

对称加密,就是加密和解密用同一个密钥。好比一把钥匙开一把锁。

我的习惯:对称加密适合加密大量数据,速度极快。但密钥分发是个老大难问题。

常见的对称加密算法:

算法 密钥长度 分组模式 安全性
AES 128/192/256 bit ECB, CBC, GCM 等 高(推荐)
DES 56 bit ECB, CBC 已废弃(可暴力破解)
3DES 112/168 bit ECB, CBC 中等(性能差,不推荐新项目用)
SM4 128 bit ECB, CBC 高(国标,国内项目常见)

我刚开始做加密SDK时,犯过一个低级错误——直接用AES-ECB模式。结果密文的相同明文块输出总是相同,安全性大打折扣。所以,我个人建议:如果没特殊需求,优先选AES-GCM。它自带认证,能防篡改,也防重放。

避坑:千万不要在ECB模式下处理图片或结构化数据!相同的前缀会导致可预测的密文块,攻击者很容易从中推断出信息。

1.2 非对称加密

非对称加密,简单来说就是有一对密钥:公钥公开出去,私钥自己藏着。公钥加密的数据只能用私钥解开;反过来,私钥签名的数据可以用公钥验签。

为什么需要它?对称加密的密钥分发是死穴——你怎么把密钥传给对方?非对称加密就解决了这个问题:你只需要拿到对方的公钥,就能给他发密文,他用自己的私钥解密。

常见的非对称算法:

  • RSA:经典,支持加密和签名。密钥长度通常2048/4096 bit。不过加密速度慢,不适合大块数据。
  • ECC(椭圆曲线):同等安全强度下,密钥比RSA短很多。比如256位ECC ≈ 3072位RSA。性能更高,移动端更友好。
  • SM2:国标椭圆曲线,在国内项目里很常见。
  • DH / ECDH:密钥交换协议,不能直接加密,但能安全地协商对称密钥。

实际项目经验:我在做IoT设备SDK时,设备算力弱,RSA握手太慢了。于是改用ECC + ECDH先交换临时密钥,再用AES-GCM传业务数据。这样既安全,速度也ok。

但是注意,非对称加密不是万能的。它有个大毛病:慢。所以实践中,我们通常混合使用:非对称加密只用来协商对称密钥(一次握手),之后大量数据用对称加密。

1.3 哈希函数

哈希函数是一种单向函数。你给它任意长度的输入,它固定输出一个摘要(比如256位)。而且理论上你无法从摘要反推出原始数据。这就叫抗原像性。

哈希函数的作用太多了:

  • 密码存储:存hash不存明文。
  • 数据完整性校验:下载文件后比对hash。
  • 数字签名:先对待签名数据做hash,再对hash签名。因为签名私钥操作太耗时,hash能大大缩短签名数据量。
  • 消息认证码(HMAC):基于hash构造,用于验证消息真实性和完整性。

常见哈希算法:

算法 输出长度 现状
MD5 128 bit 已破解,不推荐
SHA-1 160 bit 已有碰撞攻击,应停用
SHA-256 256 bit 目前安全,推荐
SHA-3 可变 安全性高,逐步推广
SM3 256 bit 国标,国内推荐

我曾经遇到过一个经典bug:某项目用MD5做文件完整性校验,结果被攻击者伪造了相同MD5的文件塞进去了。事后查出来,MD5早被公开碰撞了。所以记住:密码学里不要用任何已被证明有安全缺陷的算法,哪怕它快。

1.4 数字签名

数字签名解决的是身份认证 + 不可否认性。你用自己的私钥对消息(或消息的hash)签名,其他人用你的公钥验证签名。只要公钥可信,就能确认这条消息确实是你发的,而且中途没被篡改。

数字签名的流程:

  1. 发送方对消息做哈希(比如SHA-256)。
  2. 发送方用自己私钥对哈希值签名(比如RSA或ECDSA)。
  3. 接收方收到消息和签名后,对消息做相同的哈希。
  4. 接收方用发送方公钥验证签名是否匹配。

这里有个细节要注意:签名算法不是直接对原始消息签名,而是先hash再签名。为什么?因为非对称加密签名操作很慢,而hash可以大大缩短输入长度。同时,hash还能提供额外的“完整性”保护。

我个人的做法:在SDK抽象层里,我会把“签名”和“验签”拆成两个独立接口。因为实践中签名时你有私钥,验签时有公钥,两者的密钥类型不同,分开接口更清晰。

1.5 四者之间的关系

讲了这么多,你可能有点晕:它们之间到底怎么配合?我画了一张图帮你梳理整个密码学核心知识体系。你看完就明白了。

密码学基础四要素关系图 对称加密 AES, SM4, DES 非对称加密 RSA, ECC, SM2 哈希函数 SHA-256, SM3 数字签名 RSA签名/ECDSA 密钥分发依赖 协商密钥 先hash再签名 使用私钥 说明 • 对称加密和非对称加密混合使用:非对称加密协商对称密钥,对称加密保护大量数据 • 哈希函数为数字签名提供数据摘要,提升签名性能且保证完整性 • 数字签名依赖非对称加密的私钥/公钥体系

1.6 实战中的选择建议

说了这么多理论,你肯定想知道:做SDK抽象层时到底怎么选?我列个快速决策表格,你对照着来。

场景 推荐方案 理由
大量数据加密传输 AES-GCM 高速,自带认证
密钥协商 ECDH + AES 前向安全,性能好
身份认证 / 不可否认 ECDSA (P-256) 或 RSA-PSS 证书链成熟
密码存储 bcrypt / scrypt / Argon2 抗暴力破解,不要直接用SHA-256
消息完整性校验 HMAC-SHA256 带密钥的hash,防篡改

重点提醒:在SDK抽象层设计里,不要假设调用方会正确使用密码学原语。你应该提供更高层的接口,比如encrypt(data, keyId),底层自动选算法、做填充、加随机数。用户只需要关心业务,不需要懂GCM还是CBC。