tulip notes
首页
  • 学习笔记

    • 《Vue》
  • 踩坑日记

    • JavaScript
  • MQ
  • Nginx
  • IdentityServer
  • Redis
  • Linux
  • Java
  • SpringBoot
  • SpringCloud
  • MySql
  • docker
  • 算法与设计模式
  • 踩坑与提升
  • Git
  • GitHub技巧
  • Mac
  • 网络
  • 项目构建合集
  • 一些技巧
  • 面试
  • 一些杂货
  • 友情链接
  • 项目发布
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Star-Lord

希望一天成为大师的学徒
首页
  • 学习笔记

    • 《Vue》
  • 踩坑日记

    • JavaScript
  • MQ
  • Nginx
  • IdentityServer
  • Redis
  • Linux
  • Java
  • SpringBoot
  • SpringCloud
  • MySql
  • docker
  • 算法与设计模式
  • 踩坑与提升
  • Git
  • GitHub技巧
  • Mac
  • 网络
  • 项目构建合集
  • 一些技巧
  • 面试
  • 一些杂货
  • 友情链接
  • 项目发布
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 探索SpringBoot

  • 常用功能实现

  • Security认证授权

  • 扩展

    • Spring中的设计模式
    • 工作中常用的设计模式
    • 对接第三方接口的注意事项
    • MybatisPlus的使用跟扩展
    • 数据加密与安全
      • 数据加密的原因
      • 加密的方式
        • 哈希函数
        • 特点
        • 使用
        • 演变到 MD5+salt
        • 升级后的实现
        • 存在的问题
        • 对称加密
        • 加密工作流程
        • 示例-CBC模式 + PKCS5填充
        • 非对称加密
        • 混合加密
      • 一些建议
  • 实战与注意事项

  • 其它

  • 《SpringBoot》笔记
  • 扩展
EffectTang
2025-05-17
目录

数据加密与安全

# 数据加密与安全

# 数据加密的原因

为什么要对数据加密呢?

当然是为了提高安全性,试想这样一种场景,

  • 场景一

你的密码是123456,且存储在数据库是明文方式,如果不小心,被黑客攻破了数据库,你的账号岂不是别人可以随意使用,甚至说用来做些坏事,你可能会说,有运维,或者系统只在内网使用,不存在黑客攻破的风险,那假如管理人员里面有坏人,查看了你的密码后,使用你的账号去做坏事,你该怎么办呢?

所以,我们应该尽量保证数据安全,也就是这个密码只有你自己知道是什么,别人即使看到,也无法知道具体内容。

而要实现这个功能——别人看到,也无法知道具体内容,就是对数据进行加密。

其实加密,还会用在数据传输过程中,因为数据在公网中传递是很容易被拦截的。

# 加密的方式

在编程世界中,数据加密的主流方式主要包括以下几种:对称加密、非对称加密、哈希函数和混合加密。

注意是上是类型,并不是具体的加密算法。

# 哈希函数

我们以前常说的md5加密,就是哈希加密,或者说——md5加密就是一种哈希函数。以下是它的定义。

哈希函数:将任意长度的数据映射为固定长度的哈希值(不可逆)。

常见算法包括 MD5 和 SHA-256。

下面用MD5来举例说下它的优劣

# 特点

  • 优点:单向不可逆、计算速度快,用于数据完整性校验和密码存储。
  • 缺点:MD5 等弱哈希算法存在碰撞漏洞(不同输入可能生成相同哈希),不再推荐单独用于密码存储。

# 使用

在SpringBoot项目中,已经内置了工具类对其实现

import org.springframework.util.DigestUtils;

String password = DigestUtils.md5DigestAsHex(password.getBytes());
1
2
3

# 演变到 MD5+salt

MD5 具有上述特点,但由于其安全性较低,已被证明容易受到碰撞攻击(collision attack)和彩虹表攻击(rainbow table attack)的影响,因此在一些安全要求较高的场景中,已经不推荐单独使用 MD5 来加密密码等敏感信息。

解释一下碰撞攻击(collision attack)和彩虹表攻击(rainbow table attack)

碰撞攻击(collision attack)是指在密码学中,通过寻找两个不同的输入(消息、密码等),使它们经过哈希函数计算后得到相同的哈希值的攻击方式。对于哈希函数来说,由于输出空间有限,理论上总会存在不同的输入对应相同的输出,但好的哈希函数应该尽可能减小碰撞的概率。如果输入的信息得到的哈希值与密码的哈希值相同,那么这个密码就别破解了。

彩虹表攻击(Rainbow Table Attack)彩虹表是一种预先计算并存储大量明文密码与其对应哈希值的对照表。攻击者利用这个表来加速破解哈希值的过程。彩虹表攻击的核心思想是遍历预生成的彩虹表,通过比对哈希值,查找对应的明文密码或者原始数据。

为了解决该问题,保证数据库中用户隐私数据的安全性,通常会采用加盐算法。

在密码学中,"盐"(salt)是指在对密码进行哈希处理之前,向密码中添加的一段随机数据。这个随机数据可以是任意长度的,通常是一段随机生成的比特串,作为密码哈希过程中的附加输入。

升级后的MD5+salt,比起单独的MD5有了更高的安全性。

Salt:随机生成的一段数据,与用户密码组合后再进行哈希。每个用户的 Salt 唯一且与哈希结果一同存储。

作用:防止彩虹表攻击,增加破解难度,即使相同密码也会生成不同哈希。

# 升级后的实现

String salt = "random"; //salt为一个随机字符串
String saltedPassword = salt + password; 
String password = DigestUtils.md5DigestAsHex(saltedPassword.getBytes());
1
2
3

# 存在的问题

尽管,加盐大大提高了安全性,但现在仍不推荐使用,因为有了更好的加密算法,当然,MD5+Salt却是一个适合旧系统升级的方案,因为它无需彻底更换加密算法。

  1. 依赖 Salt 存储:需安全存储 Salt,若 Salt 泄露,可能被针对性攻击。
  2. MD5 自身缺陷:仍存在碰撞风险,且 GPU 暴力破解速度较快。
  3. 过时的算法:现代推荐使用更安全的 bcrypt、PBKDF2 或 Argon2。

# 对称加密

对称加密使用相同的密钥进行加密和解密。常见算法包括 AES(高级加密标准)和 DES(数据加密标准)。

  • 优点:速度快,适合处理大量数据。
  • 缺点:密钥管理困难,密钥泄露会导致数据暴露。

下面用AES来介绍下,

ES(Advanced Encryption Standard) 是一种对称加密算法,用于替代旧的DES算法,被广泛应用于保护敏感数据。其核心特点包括:

  • 对称加密:加密和解密使用相同的密钥。
  • 密钥长度:AES支持三种长度的密钥:128位、192位和256位。密钥长度越长,加密过程就越复杂,破解难度也相应增加。
  • 工作模式:AES可以通过不同的工作模式来适应不同的应用场景,如ECB(电子密码本模式)、CBC(密码块链接模式)、CFB(密码反馈模式)、OFB(输出反馈模式)和CTR(计数器模式)等。每种模式都有其特定的用途和安全性考虑
  • 高效性:AES算法设计得非常高效,能够在软件和硬件上快速执行,使其成为许多加密应用的首选算法。

# 加密工作流程

AES(Advanced Encryption Standard)是一种对称分组加密算法,其核心是对 128 位(16 字节)的数据块进行多轮加密处理。以下是 AES 加密的核心步骤:

AES 加密流程分为 初始轮(Initial Round) → N-1 次中间轮(Rounds) → 最终轮(Final Round),具体轮数由密钥长度决定:

  • AES-128:10 轮
  • AES-192:12 轮
  • AES-256:14 轮

内容有点多这里就不展开了,欢迎大家自行搜索。

# 示例-CBC模式 + PKCS5填充

以下是使用Java实现AES加密和解密的完整代码示例(基于javax.crypto包):

注意:明文长度需为块大小的整数倍,否则需填充(如PKCS5Padding)

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class AESExample {

    // 密钥(16字节,对应128位)
    private static final String KEY = "0123456789abcdef";
    // 初始向量(IV,16字节,需与密文一起传输)
    private static final String IV = "abcdefghijklmnop";
    // 加密算法和模式
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";

    /**
     * AES加密
     * @param plainText 明文
     * @return Base64编码的密文
     */
    public static String encrypt(String plainText) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes("UTF-8"), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes("UTF-8"));
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
            byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * AES解密
     * @param cipherText Base64编码的密文
     * @return 明文
     */
    public static String decrypt(String cipherText) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes("UTF-8"), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes("UTF-8"));
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            byte[] decodedBytes = Base64.getDecoder().decode(cipherText);
            byte[] decryptedBytes = cipher.doFinal(decodedBytes);
            return new String(decryptedBytes, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        String originalText = "Hello, AES Encryption!";
        System.out.println("原始文本: " + originalText);

        String encryptedText = encrypt(originalText);
        System.out.println("加密后: " + encryptedText);

        String decryptedText = decrypt(encryptedText);
        System.out.println("解密后: " + decryptedText);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

注意:使用CBC模式需固定IV(需随机生成并安全存储)

# 非对称加密

非对称加密使用一对密钥:公钥(加密)和 私钥(解密)。常见算法包括 RSA 和 ECC(椭圆曲线加密)。

  • 优点:安全性高,适合密钥交换和数字签名。
  • 缺点:加密速度慢,不适合处理大量数据。

# 混合加密

混合加密结合对称加密和非对称加密的优点:

  1. 使用非对称加密安全地交换对称密钥。
  2. 使用对称加密加密实际数据。

# 一些建议

密钥管理:

  • 对称加密的密钥需安全存储(如密钥库)。
  • 非对称加密的私钥必须严格保密。

算法选择:

  • 对称加密推荐使用 AES(256 位密钥)。
  • 非对称加密推荐使用 RSA(2048 位以上)或 ECC(资源受限场景)。
  • 哈希函数推荐使用 SHA-256(避免 MD5/SHA-1)。

安全性:

  • 避免硬编码密钥,使用环境变量或配置文件。
  • 定期更新密钥,防止长期暴露风险。
上次更新: 2025/05/21, 15:29:11
MybatisPlus的使用跟扩展
Spring声明式事务,请正确处理

← MybatisPlus的使用跟扩展 Spring声明式事务,请正确处理→

最近更新
01
面向切面跟自定义注解的结合
05-22
02
时间跟其他数据的序列化
05-19
03
异常捕获的一些细节
05-14
更多文章>
Theme by Vdoing | Copyright © 2023-2025 EffectTang
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式