如何选择合适的加密方式?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)); // 能还原 } }

特性MD5AES
类型哈希算法(摘要)对称加密算法
可逆性不可逆可逆
密钥不需要必须需要
输出长度固定 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个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP