← 返回

密码学基础:Hash、对称加密、非对称加密

作者:林 | 系列:密码学 | 适合读者:后端开发 / 对密码学感兴趣的工程师


一、为什么要懂密码学

作为开发者,你可能每天都在用密码学而不自知:

  • HTTPS 连接 → TLS 握手(非对称 + 对称加密)
  • 用户密码存储 → BCrypt/Argon2(散列函数)
  • JWT Token → HMAC-SHA256(消息认证码)
  • 支付接口签名 → RSA/SM2(数字签名)
  • 数据库敏感字段 → AES/SM4(对称加密)

密码学并非安全团队的专属,重点是每个后端工程师的基本功。本文用下限的篇幅把三大支柱讲清楚,后续每篇深入一个方向。


二、三大分类总览

能力散列函数对称密码公钥密码
主要用途完整性、派生、消息认证的组成部分数据机密性与认证加密密钥协商、签名,部分算法支持加密
是否可逆不可逆持有密钥可解密取决于具体算法与用途
密钥普通散列无密钥,HMAC 有密钥双方共享密钥公钥与私钥成对
常见算法SHA-2、SHA-3、SM3AES、SM4、ChaCha20RSA、ECC、SM2

核心区别一句话:

  • Hash:单向压缩,不能解密,用于验证完整性
  • 对称加密:一把钥匙,能加能解,用于加密数据
  • 非对称加密:两把钥匙,公私配对,用于密钥交换和签名

三、散列函数(Hash)

3.1 特征

特征说明
单向性从哈希值无法反推出原文
固定长度无论输入多长,输出长度固定
雪崩效应输入改一个 bit,输出变化超过 50%
抗碰撞找到两个不同输入产生相同输出,计算上不可行

3.2 常见算法

算法输出长度状态用途
MD5128 bit❌ 已破解仅用于文件校验(非安全场景)
SHA-1160 bit❌ 已破解不应再使用
SHA-256256 bit✅ 安全数字签名、证书、区块链
SHA-3可变✅ 安全SHA-2 的备选方案
SM3256 bit✅ 安全国密体系,对标 SHA-256

3.3 代码示例

import java.security.MessageDigest;

// SHA-256
byte[] hash = MessageDigest.getInstance("SHA-256")
    .digest("hello".getBytes());

// SM3(需要 BouncyCastle)
byte[] sm3Hash = MessageDigest.getInstance("SM3")
    .digest("hello".getBytes());

3.4 典型应用

场景做法
密码存储BCrypt/Argon2(带盐的慢哈希)
文件完整性校验SHA-256 摘要比对
消息认证(HMAC)HMAC-SHA256(key, message)
数字签名先 Hash 再用私钥签 Hash 值
区块链SHA-256 链式哈希
别用 MD5/SHA-1 做安全用途
MD5 碰撞攻击成本已低至几秒,SHA-1 也在 2017 年被 Google 实际碰撞。密码存储、签名验证等安全场景,必须用 SHA-256+ 或 SM3。

四、对称加密(Symmetric Encryption)

4.1 原理

加密和解密使用同一把密钥

明文 + 密钥 → 加密算法 → 密文
密文 + 密钥 → 解密算法 → 明文

4.2 常见算法

算法密钥长度分组长度状态
DES56 bit64 bit❌ 已淘汰
3DES168 bit64 bit⚠️ 遗留系统
AES-128128 bit128 bit✅ 主流
AES-256256 bit128 bit✅ 高安全场景
SM4128 bit128 bit✅ 国密,对标 AES-128
ChaCha20256 bit流密码✅ 移动端/TLS

4.3 加密模式(关键)

算法本身只处理一个分组(16 字节),多个分组怎么处理由模式决定:

模式特点是否推荐
ECB每块独立加密,相同明文块→相同密文块❌ 不安全
CBC前一块密文参与下一块加密,需要 IV⚠️ 可用但有 padding oracle 风险
CTR计数器模式,可并行✅ 推荐
GCMCTR + 认证标签(AEAD)✅ 首选
// AES-GCM 加密示例
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(128, nonce); // 12字节 nonce
cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec);
byte[] ciphertext = cipher.doFinal(plaintext);

4.4 核心问题:密钥怎么给对方?

对称加密速度快,但有一个核心问题:通信双方怎么安全地共享同一把密钥?

  • 线下交换?不现实
  • 明文传输?等于没加密
  • 解决方案 → 非对称加密(密钥交换)或预共享密钥

这就引出了非对称加密。


五、非对称加密(Asymmetric Encryption)

5.1 原理

使用一对密钥:公钥(public key)和私钥(private key)。

加密场景:
  明文 + 对方公钥 → 加密 → 密文
  密文 + 自己私钥 → 解密 → 明文

签名场景:
  消息 + 自己私钥 → 签名 → 签名值
  消息 + 对方公钥 → 验签 → 通过/不通过

5.2 常见算法

算法密钥长度安全强度性能状态
RSA-20482048 bit112 bit慢(密钥生成特别慢)✅ 广泛使用
RSA-40964096 bit128 bit更慢✅ 高安全场景
ECDSA P-256256 bit128 bit✅ 主流趋势
Ed25519256 bit128 bit很快✅ 现代首选
SM2256 bit128 bit✅ 国密,对标 ECC

5.3 RSA vs ECC 直观对比

在约 128 位经典安全强度下,常见比较会使用 RSA-3072 与 256 位素数域椭圆曲线。RSA 签名长度等于模数长度,ECDSA 的原始 r || s 长度由曲线参数决定,DER 编码还会变化。性能受算法方向、实现、硬件加速和提供者影响,需要在目标密码库中分别测量签名与验签,不能用一组固定毫秒数概括。

5.4 代码示例

// SM2 签名(Hutool)
SM2 sm2 = SmUtil.sm2(privateKeyHex, publicKeyHex);
byte[] sign = sm2.sign("hello".getBytes());
boolean valid = sm2.verify("hello".getBytes(), sign);

// RSA 签名
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(privateKey);
sig.update("hello".getBytes());
byte[] signature = sig.sign();

5.5 典型应用

场景用法
HTTPS/TLS密钥交换(ECDHE)+ 证书验证(签名)
数字信封非对称加密对称密钥,对称密钥加密数据
数字签名接口防篡改、电子合同、代码签名
SSH 登录公钥认证
区块链交易签名(ECDSA/Ed25519)

六、三者的协作关系

实际系统中,三种密码学原语几乎不会单独使用,而是组合协作:

以 TLS 1.3 常见握手为例:客户端和服务端协商参数,服务端发送证书并证明持有对应私钥,双方通过 (EC)DHE 计算共享秘密,再由 HKDF 派生握手与应用流量密钥。应用数据通常由 AES-GCM 或 ChaCha20-Poly1305 这类 AEAD 套件同时提供机密性和完整性,不再额外给每条应用记录附加 HMAC。

支付接口签名流程:

1. 将请求参数按字典序拼接成字符串
2. 对字符串做 SHA-256 哈希(Hash)
3. 用私钥对 Hash 值做 SM2/RSA 签名(非对称)
4. 对方用公钥验签
5. 请求体用 AES/SM4 加密传输(对称)

七、国密算法体系

中国国家密码管理局发布的商用密码算法,在政府、金融、央企项目中逐步替代国际算法:

国密算法类型对标国际算法标准编号
SM2非对称(椭圆曲线)ECDSA/ECIESGM/T 0003
SM3散列函数SHA-256GM/T 0004
SM4对称加密(分组密码)AES-128GM/T 0002
SM9标识密码IBEGM/T 0044
ZUC流密码3GPP 标准
什么时候必须用国密
  • 政府/央企/军工项目:强制要求
  • 金融行业:逐步推进,2025 年后新系统基本强制
  • 等保三级以上系统:建议使用
  • 普通互联网项目:不强制,AES/RSA 仍然是主流选择

八、选型速查表

我要做什么推荐方案国密方案
存储用户密码BCrypt / Argon2
校验文件完整性SHA-256SM3
接口签名验签ECDSA / Ed25519SM2
加密数据库字段AES-256-GCMSM4-GCM
加密传输数据TLS 1.3 (ECDHE + AES-GCM)TLCP (SM2 + SM4)
密钥交换ECDH / X25519SM2 密钥交换
数字信封RSA/ECDH + AESSM2 + SM4
JWT 签名HMAC-SHA256 / ES256SM2 签名

九、常见误区

误区 1:加密 = 安全

加密只是安全的一环。密钥管理、传输安全、访问控制同样重要。密钥硬编码在代码里,加密等于白做。

误区 2:Hash 可以解密

Hash 是单向函数,不存在"解密"。所谓的"MD5 解密网站"是彩虹表反查,不是解密。

误区 3:RSA 比 AES 更安全

RSA 和 AES 解决的是不同问题。RSA 解决密钥分发,AES 解决数据加密。两者配合使用,不是二选一。

误区 4:密钥越长越好

AES-128 在可预见的未来都足够安全(暴力破解需要 2^128 次运算)。盲目加长密钥只会降低性能,没有实际安全收益。

误区 5:自己实现加密算法

永远不要自己发明加密算法或自己实现已有算法。使用成熟的库(BouncyCastle、OpenSSL、libsodium),它们经过了大量审计和攻击测试。


十、系列导航

本系列共 7 篇,由浅入深:

  1. 密码学基础:Hash、对称加密、非对称加密(本文)
  2. 散列函数:MD5、SHA、SM3 与 HMAC
  3. 对称加密:AES 与 SM4 模式选择指南
  4. 非对称加密与签名:RSA、ECC、SM2
  5. 数字信封与密钥协商:SM2+SM4、ECDH、TLS
  6. 可搜索加密:加密数据的模糊检索方案
  7. 格式保留加密、同态加密与零知识证明

下一篇散列函数:MD5、SHA、SM3 与 HMAC