加密算法指南

常用加密算法介绍、使用场景和代码示例

算法对比总结
类型 算法 可逆性 速度 主要用途 操作
对称加密 AES 可逆 数据加密 去试试
SM4 可逆 国密数据加密 去试试
非对称加密 RSA 可逆 密钥交换、签名 去试试
SM2 可逆 中等 国密加密签名 去试试
哈希 SHA-256 不可逆 数据校验 去试试
SM3 不可逆 国密哈希 去试试
密码哈希 BCrypt 不可逆 慢(故意) 密码存储 去试试
Argon2 不可逆 慢(故意) 密码存储 去试试
对称加密
什么是 AES?

AES(Advanced Encryption Standard)是目前最流行的对称加密算法,使用相同的密钥进行加密和解密。

特点
  • 加密解密速度快
  • 密钥长度:128/192/256 位
  • 适合大数据量加密
  • 需要安全传输密钥
使用场景
  • 文件加密
  • 数据库字段加密
  • HTTPS 会话加密
  • 敏感数据传输
Java 示例(Hutool)
// AES 加密
String content = "需要加密的内容";
String key = "1234567890123456"; // 16位密钥

// 加密
String encrypt = SecureUtil.aes(key.getBytes()).encryptBase64(content);

// 解密
String decrypt = SecureUtil.aes(key.getBytes()).decryptStr(encrypt);

其他对称加密算法
算法 密钥长度 安全性 说明
DES 56位 已淘汰,不建议使用
3DES 168位 DES 的改进版,速度较慢
SM4 128位 国密算法,国内推荐使用
ChaCha20 256位 新兴算法,移动端性能更好
非对称加密
什么是 RSA?

RSA 是最经典的非对称加密算法,使用公钥加密、私钥解密,解决了密钥传输的安全问题。

特点
  • 公钥公开,私钥保密
  • 密钥长度:1024/2048/4096 位
  • 加密速度慢(比 AES 慢 100 倍)
  • 适合小数据量加密
使用场景
  • 密钥交换(交换 AES 密钥)
  • 数字签名
  • 身份认证
  • 证书体系(SSL/TLS)
Java 示例(Hutool)
// 生成 RSA 密钥对
RSA rsa = SecureUtil.rsa();
String privateKey = rsa.getPrivateKeyBase64();
String publicKey = rsa.getPublicKeyBase64();

// 公钥加密
String encrypt = rsa.encryptBase64(content, CharsetUtil.CHARSET_UTF_8, KeyType.PublicKey);

// 私钥解密
String decrypt = rsa.decryptStr(encrypt, KeyType.PrivateKey);

国密 SM2

SM2 是国家密码管理局发布的椭圆曲线公钥密码算法,对标 RSA/ECDSA。

优势
  • 密钥更短(256位 = RSA 3072位安全性)
  • 速度更快
  • 国密合规要求
Java 示例
// SM2 加密
SM2 sm2 = SmUtil.sm2();
String encrypt = sm2.encryptBcd(content, KeyType.PublicKey);
String decrypt = sm2.decryptStr(encrypt, KeyType.PrivateKey);
哈希算法(摘要)
什么是哈希?

哈希算法将任意长度数据转换为固定长度的摘要,具有不可逆特性,常用于数据完整性校验。

重要:哈希不是加密!哈希是单向的,无法从摘要还原原始数据。
算法 输出长度 安全性 用途
MD5 128位 已破解 文件校验(不用于安全)
SHA-1 160位 不推荐 逐渐淘汰中
SHA-256 256位 安全 目前最常用
SHA-512 512位 更安全 高安全场景
SM3 256位 安全 国密哈希算法
Java 示例(Hutool)
// SHA-256 哈希
String hash = SecureUtil.sha256(content);

// MD5(不推荐用于安全场景)
String md5 = SecureUtil.md5(content);

// SM3 国密哈希
String sm3 = SmUtil.sm3(content);

HMAC(带密钥的哈希)

HMAC 在哈希基础上增加了密钥,可以验证数据来源和完整性。

Java 示例
// HMAC-SHA256
String key = "secretKey";
String hmac = SecureUtil.hmac(HmacAlgorithm.HmacSHA256, key).digestBase64(content);
密码存储
为什么不能直接存密码?
绝对不要:明文存储密码、简单 MD5/SHA256 存储密码!
密码哈希 vs 普通哈希
特性 普通哈希(SHA-256/SM3) 密码哈希(BCrypt/Argon2)
设计目标 快速计算,验证数据完整性 故意慢速,防止暴力破解
计算速度 每秒数百万次 ⚡ 每秒几百次 🐢
盐值 无(相同输入相同输出) 自动随机盐值
适用场景 文件校验、数字签名 用户密码存储
安全性 易被彩虹表/暴力破解 抗彩虹表、抗 GPU 加速
简单理解:普通哈希追求"快"(效率),密码哈希追求"慢"(安全)。用 SHA-256 存密码,黑客每秒能试几十亿个密码;用 BCrypt,每秒只能试几百个。
正确做法:慢哈希 + 盐值

密码哈希需要(防暴力破解)+随机盐值(防彩虹表)。

算法 特点 推荐度
BCrypt 自适应成本,内置盐值,最流行 ⭐⭐⭐ 首选
SCrypt 内存困难型,抗 GPU/ASIC ⭐⭐⭐ 推荐
Argon2 2015 密码哈希大赛冠军 ⭐⭐⭐ 最新标准
PBKDF2 NIST 推荐,老牌标准 ⭐⭐ 可用
Java 示例(BCrypt)
// 注册:生成密码哈希
String password = "userPassword";
String salt = BCrypt.gensalt(12); // cost = 12,约 300ms
String hashed = BCrypt.hashpw(password, salt);
// 存储 hashed 到数据库

// 登录:验证密码
boolean match = BCrypt.checkpw(inputPassword, storedHash);
Java 示例(双重哈希,更安全)
// 先 SHA-256 预处理,再 BCrypt
String sha256Pwd = DigestUtil.sha256Hex(password);
String salt = BCrypt.gensalt(10);
String passwordNew = BCrypt.hashpw(sha256Pwd, salt);
BCrypt 在线生成/验证
生成哈希
数值越大越慢越安全
验证密码
Argon2 在线生成/验证
生成哈希
内存困难型算法,抗 GPU/ASIC
验证密码

密码存储最佳实践
✅ 应该做的
  • 使用 BCrypt/Argon2/SCrypt
  • 每个密码独立盐值
  • 定期升级 cost 参数
  • 限制登录失败次数
  • 使用 HTTPS 传输
❌ 不应该做的
  • 明文存储密码
  • 简单 MD5/SHA1
  • 固定盐值
  • 可逆加密(AES 等)
  • 限制密码长度(如 16 位)
算法选择指南
根据场景选择算法
文件/数据加密

加密大量数据,需要速度快

推荐:AES-256-GCM

去加密
密钥交换

安全传输对称密钥

推荐:RSA + AES

去加密
数据完整性

验证数据未被篡改

推荐:SHA-256

去计算
密码存储

安全存储用户密码

推荐:BCrypt/Argon2

数字签名

证明数据来源和完整性

推荐:RSA-PSS / ECDSA

去签名
国密合规

国内项目合规要求

推荐:SM2/SM3/SM4

查看详情
国密算法(SM系列)
国密算法是中国国家密码管理局发布的密码算法标准,在国内金融、政务等领域有合规要求。
SM2 - 非对称加密/签名

基于椭圆曲线密码学(ECC)的公钥算法,对标 RSA/ECDSA,但性能更优。

优势
  • 密钥更短:256位 SM2 ≈ 3072位 RSA 安全性
  • 速度更快:加密/签名速度优于 RSA
  • 存储更小:证书、签名数据更紧凑
  • 国密合规:满足国内安全审查要求
Java 示例(Hutool)
// 生成 SM2 密钥对
SM2 sm2 = SmUtil.sm2();
String privateKey = sm2.getPrivateKeyBase64();
String publicKey = sm2.getPublicKeyBase64();

// SM2 加密
String encrypt = sm2.encryptBcd(content, KeyType.PublicKey);

// SM2 解密
String decrypt = sm2.decryptStr(encrypt, KeyType.PrivateKey);

// SM2 签名
String sign = sm2.signHex(content);

// SM2 验签
boolean verify = sm2.verifyHex(content, sign);

SM3 - 哈希算法

国密哈希算法,输出 256 位摘要,对标 SHA-256。

  • 输出长度:256 位(32 字节)
  • 安全性:与 SHA-256 相当
  • 用途:数据完整性校验、数字签名
Java 示例
// SM3 哈希
String hash = SmUtil.sm3(content);

// SM3 HMAC
String hmac = SmUtil.sm3Hmac(key, content);

SM4 - 对称加密

国密对称加密算法,对标 AES,分组长度和密钥长度均为 128 位。

  • 分组长度:128 位
  • 密钥长度:128 位
  • 工作模式:ECB、CBC、CTR、GCM 等
  • 性能:与 AES 相当
Java 示例
// SM4 加密
String key = "1234567890123456"; // 16字节密钥
String iv = "1234567890123456";  // 16字节IV

// CBC 模式
SM4 sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding, 
                  key.getBytes(), iv.getBytes());
String encrypt = sm4.encryptBase64(content);

// 解密
String decrypt = sm4.decryptStr(encrypt);

SM9 - 标识加密

基于身份的密码算法(IBC),无需数字证书,直接使用用户标识(如邮箱)作为公钥。

适用场景:大规模用户系统、物联网设备、邮件加密等,省去证书管理开销。
编码方案(不是加密)
重要:编码不是加密!编码是可逆的、无密钥的,任何人都可以解码。
常用编码方案对比
编码 特点 用途 示例
Base64 二进制转文本,体积增加 33% 图片/文件传输、URL 参数 SGVsbG8=
Base58 无 0/O/I/l 混淆,适合人工输入 Bitcoin 地址 3J98t1WpEZ73CNm
Base32 全大写,适合二维码 Google Authenticator JBSWY3DPEHPK3PXP
Hex 十六进制,体积增加 100% 密钥显示、哈希值 48656c6c6f
URL Encode 特殊字符转义 URL 参数、表单提交 Hello%20World
Java 示例(Hutool)
// Base64
String base64 = Base64.encode(content);
String decoded = Base64.decodeStr(base64);

// Base58(Bitcoin)
String base58 = Base58.encode(bytes);

// Hex
String hex = HexUtil.encodeHexStr(content);
byte[] bytes = HexUtil.decodeHex(hex);

// URL Encode
String urlEncoded = URLUtil.encode(content);
String urlDecoded = URLUtil.decode(urlEncoded);