基于 AES + Base64 的密码加密工具类实现与优化

102300426陈炜滨 2025-12-25 21:32:06

| 这个作业属于哪个课程 | 202501福大-软件工程实践-w班 |
| 这个作业要求在哪里 | 软件工程实践总结&个人技术博客 |
| 这个作业的目标 | 完成个人技术总结 |
| 其他参考文献 | 阿里巴巴Java开发手册、Git Flow工作流指南、敏捷开发实践 |

目录

  • 基于 AES + Base64 的密码加密工具类实现与优化
  • 1. 技术概述
  • 2. 技术详述
  • 2.1 背景与选型原因
  • 2.2 核心实现逻辑
  • 密钥生成机制(关键)
  • 2.3 加密流程图
  • 2.4 解密流程图
  • 2.5 使用示例
  • 3. 技术使用中遇到的问题与解决过程
  • 问题 1:不同 JDK/OS 下密钥不一致,导致解密失败
  • 现象:
  • 根本原因:
  • 解决方案:
  • 问题 2:Base64 字符串含 / 和 +,在 URL 中被错误解析
  • 现象:
  • 解决方案:
  • 4. 总结
  • 5. 参考文献

基于 AES + Base64 的密码加密工具类实现与优化

1. 技术概述

本文聚焦于在 Java 后端开发中,如何通过 AES 对称加密 配合 Base64 编码 实现敏感数据(如设备指令、配置项)的安全存储与传输。该方案适用于需要可逆加解密的场景,尤其在无法使用 bcrypt 等单向哈希算法时作为替代方案。技术难点在于密钥生成的一致性、跨平台兼容性保障以及性能开销控制。

2. 技术详述

2.1 背景与选型原因

在“规巢”宿舍管理系统开发中,用户登录密码采用 bcrypt 安全哈希存储,但部分业务(如设备控制指令)需支持解密还原原始内容。由于 bcrypt 是单向函数,无法满足需求,我们设计了通用加密工具类 PasswdUtil,基于 AES-128 对称加密 + Base64 编码 实现可逆加密。

2.2 核心实现逻辑

PasswdUtil.java 提供两个核心方法:

  • encode(String data):明文 → AES 加密 → Base64 编码 → 密文字符串

  • decode(String encryptedData):Base64 解码 → AES 解密 → 明文字符串

密钥生成机制(关键)


private static SecretKeySpec generateKeyFromPassword() {
String password = "app@guicao"; // 固定密钥种子(生产环境应从配置读取)
byte[] keyBytes = new byte[16]; // AES-128 要求 16 字节密钥
byte[] pwdBytes = password.getBytes(StandardCharsets.UTF_8);
System.arraycopy(pwdBytes, 0, keyBytes, 0, Math.min(pwdBytes.length, 16));
return new SecretKeySpec(keyBytes, "AES");
}

直接从固定字符串派生 16 字节密钥,确保跨平台一致性。
避免使用 SecureRandom + KeyGenerator 组合,防止 JDK/OS 差异导致密钥不一致。

2.3 加密流程图

img

2.4 解密流程图

img

2.5 使用示例


// 加密
String plain = "device_cmd_123";
String encrypted = PasswdUtil.encode(plain);
System.out.println("Encrypted: " + encrypted); // e.g., U2FsdGVkX1...

// 解密
String decrypted = PasswdUtil.decode(encrypted);
System.out.println("Decrypted: " + decrypted); // 输出: device_cmd_123

3. 技术使用中遇到的问题与解决过程

问题 1:不同 JDK/OS 下密钥不一致,导致解密失败

现象:

本地 Windows + JDK 17 加密成功,但 Linux + JDK 11 服务器解密时报错:


javax.crypto.BadPaddingException: Given final block not properly padded

根本原因:

早期版本使用 SecureRandom.getInstance("SHA1PRNG") 生成密钥,但该算法在不同平台底层实现不同,即使种子相同,输出也可能不一致。

解决方案:

弃用 KeyGenerator,直接从固定字符串构造密钥(见 2.2 节代码)。

问题 2:Base64 字符串含 / 和 +,在 URL 中被错误解析

现象:

将加密结果作为 URL 参数传递(如 ?token=abc+/123==),后端收到时 + 变为空格,/ 被截断。

解决方案:

使用 URL 安全的 Base64 编码器:


// encode 方法中
return Base64.getUrlEncoder().withoutPadding().encodeToString(cipherText);

// decode 方法中
byte[] decoded = Base64.getUrlDecoder().decode(encryptedData);

getUrlEncoder() 将 + 替换为 -,/ 替换为 _
withoutPadding() 移除末尾 =,避免 URL 编码问题

4. 总结

PasswdUtil 提供了一套轻量、可靠、可逆的加密方案,适用于设备指令、API 密钥等需加解密的场景。
绝对不可用于用户密码存储——密码必须使用 bcrypt/scrypt/PBKDF2 等慢哈希算法。
密钥管理是安全核心:生产环境务必通过配置中心或环境变量注入,禁止硬编码。
跨平台部署前必须验证加解密一致性,推荐直接派生密钥而非依赖随机数生成器。
若用于网络传输(尤其是 URL),必须使用 URL 安全 Base64。

5. 参考文献

  1. Java Cryptography Architecture (JCA) Reference Guide
    Oracle官方文档
    https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html

  2. Base64 Encoding in Java: Standard vs URL-Safe
    Baeldung
    https://www.baeldung.com/java-base64-url-safe

...全文
207 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

114

社区成员

发帖
与我相关
我的任务
社区描述
202501福大-软件工程实践-W班
软件工程团队开发结对编程 高校 福建省·福州市
社区管理员
  • 202501福大-软件工程实践-W班
  • 离离原上羊羊吃大草
  • MiraiZz2
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧