114
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | 202501福大-软件工程实践-w班 |
| 这个作业要求在哪里 | 软件工程实践总结&个人技术博客 |
| 这个作业的目标 | 完成个人技术总结 |
| 其他参考文献 | 阿里巴巴Java开发手册、Git Flow工作流指南、敏捷开发实践 |
本文聚焦于在 Java 后端开发中,如何通过 AES 对称加密 配合 Base64 编码 实现敏感数据(如设备指令、配置项)的安全存储与传输。该方案适用于需要可逆加解密的场景,尤其在无法使用 bcrypt 等单向哈希算法时作为替代方案。技术难点在于密钥生成的一致性、跨平台兼容性保障以及性能开销控制。
在“规巢”宿舍管理系统开发中,用户登录密码采用 bcrypt 安全哈希存储,但部分业务(如设备控制指令)需支持解密还原原始内容。由于 bcrypt 是单向函数,无法满足需求,我们设计了通用加密工具类 PasswdUtil,基于 AES-128 对称加密 + Base64 编码 实现可逆加密。
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 差异导致密钥不一致。


// 加密
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
本地 Windows + JDK 17 加密成功,但 Linux + JDK 11 服务器解密时报错:
javax.crypto.BadPaddingException: Given final block not properly padded
早期版本使用 SecureRandom.getInstance("SHA1PRNG") 生成密钥,但该算法在不同平台底层实现不同,即使种子相同,输出也可能不一致。
弃用 KeyGenerator,直接从固定字符串构造密钥(见 2.2 节代码)。
将加密结果作为 URL 参数传递(如 ?token=abc+/123==),后端收到时 + 变为空格,/ 被截断。
使用 URL 安全的 Base64 编码器:
// encode 方法中
return Base64.getUrlEncoder().withoutPadding().encodeToString(cipherText);
// decode 方法中
byte[] decoded = Base64.getUrlDecoder().decode(encryptedData);
getUrlEncoder() 将 + 替换为 -,/ 替换为 _
withoutPadding() 移除末尾 =,避免 URL 编码问题
PasswdUtil 提供了一套轻量、可靠、可逆的加密方案,适用于设备指令、API 密钥等需加解密的场景。
绝对不可用于用户密码存储——密码必须使用 bcrypt/scrypt/PBKDF2 等慢哈希算法。
密钥管理是安全核心:生产环境务必通过配置中心或环境变量注入,禁止硬编码。
跨平台部署前必须验证加解密一致性,推荐直接派生密钥而非依赖随机数生成器。
若用于网络传输(尤其是 URL),必须使用 URL 安全 Base64。
Java Cryptography Architecture (JCA) Reference Guide
Oracle官方文档
https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html
Base64 Encoding in Java: Standard vs URL-Safe
Baeldung
https://www.baeldung.com/java-base64-url-safe