如何选择合适的加密方式?MD5、AES、BCrypt 的区别
今天公司里出了一个需求,原来我们用户的手势密码在数据库里是明文存储的。现在需要改成加密存储,那么用什么加密方式方式就是一个问题。

看到之前代码中很多地方都涉及到了加密,比如:身份证、银行卡号等等。这些都是使用了AES加密。那我可以在密码中也使用AES吗?
答案肯定是不行的
MD5 加密 和 AES 加密 的核心区别
这两个完全不是一类加密,核心区别一句话:MD5 是哈希(不可逆),用来验数据完整性;AES 是对称加密(可逆),用来保护数据隐私。
一、最核心的 4 个区别
1. 是否可逆(最重要)
- MD5:不可逆 明文 → MD5 → 密文无法从密文还原回明文(只能暴力猜)
- AES:可逆 明文 + 密钥 → AES 加密 → 密文 密文 + 密钥 → AES 解密 → 明文可以完美还原
2. 用途完全不同
- MD5:校验数据是否被篡改 如:文件校验、密码存储(加盐)、接口签名
- AES:真正的加密,保护隐私 如:聊天消息、文件加密、数据库敏感字段、传输加密
3. 输出长度
- MD5:固定 128 位(32 位十六进制字符串) 不管输入多长,输出永远是 32 位字符串
- AES:长度不固定,和原文长度接近
4. 密钥
- MD5:不需要密钥
- AES:必须有密钥,没有密钥无法解密
二、简单类比
- MD5 = 把水果榨成汁 你没法把汁还原回水果。
- AES = 把箱子上锁 有钥匙就能打开,没钥匙打不开。
三、简单代码示例(直观感受)
MD5(不可逆)
▼java复制代码import java.security.MessageDigest; public class EncryptDemo { public static void main(String[] args) throws Exception { String data = "hello123"; // MD5 加密 MessageDigest md = MessageDigest.getInstance("MD5"); byte[] bytes = md.digest(data.getBytes()); // 转成 32 位十六进制 StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02x", b)); } System.out.println(sb.toString()); // 固定长度,无法还原 } }
AES(可逆加密)
▼java复制代码import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.util.Base64; public class EncryptDemo { public static void main(String[] args) throws Exception { String data = "hello123"; // 1. 生成 AES 密钥 KeyGenerator keyGen = KeyGenerator.getInstance("AES"); keyGen.init(256); SecretKey key = keyGen.generateKey(); // 2. 加密 Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] encrypted = cipher.doFinal(data.getBytes()); String encryptBase64 = Base64.getEncoder().encodeToString(encrypted); System.out.println("加密后:" + encryptBase64); // 3. 解密 cipher.init(Cipher.DECRYPT_MODE, key); byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptBase64)); System.out.println("解密后:" + new String(decrypted)); // 能还原 } }
| 特性 | MD5 | AES |
|---|---|---|
| 类型 | 哈希算法(摘要) | 对称加密算法 |
| 可逆性 | 不可逆 | 可逆 |
| 密钥 | 不需要 | 必须需要 |
| 输出长度 | 固定 32 位字符串 | 不固定 |
| 主要用途 | 校验完整性、密码存储、签名 | 数据隐私加密、消息加密 |
| 安全性 | 已不安全,不适合直接存密码 | 目前非常安全 |
这里需要强调:使用MD5一定要加盐值
盐值 = 一串随机字符串
作用:给原始密码 “加点料”,让相同密码加密后不一样。
为什么MD5一定要用盐值?
这就要提到了 彩虹表(Rainbow Table)
▼java复制代码123456 → e10adc3949ba59abbe56e057f20f883e 888888 → 665f2d42b5c70004ac01b319998146dc admin → 21232f297a57a5a74f8964177e6efe97 ...(几亿条数据)
只要拿到你数据库里的 MD5 密码, 去彩虹表一秒钟就能查到原始密码!
不用盐 = 等于没加密!
盐值的作用
给每个用户密码加一串唯一随机字符串
例子:
- 用户 A 密码:
123456+ 盐x9s7k2 - 用户 B 密码:
123456+ 盐p5d8f1
但是即使MD5 + 盐,也不是最安全的!
最安全的写法:BCrypt
只干一件事:加密用户密码,让黑客就算偷了数据库,也绝对解不开原始密码。
它专门解决:
- 密码不能明文存
- MD5 不安全
- 加盐太麻烦
- 黑客容易破解
这些问题。
它比 MD5 强在哪里?
① 自动加盐,不用你管
MD5 你要自己生成盐、拼接、存盐。 BCrypt 自动生成盐、自动存在密文里,你一行代码搞定。
② 相同密码,每次加密结果都不一样
- 123456 → 第一次加密:
$2a$10$xxx... - 123456 → 第二次加密:
$2a$10$yyy...
黑客彩虹表彻底失效,无法批量破解。
③ 跑得慢,专门防暴力破解
MD5 一秒能猜几亿次。 BCrypt 一秒只能猜几十次。黑客根本破不动。
④ 全球公认最安全的密码存储方案
银行、支付宝、微信、所有正规系统都用它存密码。
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
