mirror of
https://gitee.com/jzsw-it/yexuejc-base.git
synced 2026-10-26 01:24:49 +08:00
fix: S9/S10 DES3废弃标记和零填充警告
- S9: DES3类JavaDoc添加NIST 2023废弃说明,指向AES-GCM迁移 - S10: padding()标记@Deprecated,说明零填充安全问题
This commit is contained in:
1 parent
2e7c269a32
commit
c3d8b7d935
2 files changed
+64
-28
No files matched your search
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017-2026 yexuejc (https://github.com/yexuejc)
|
||||
*
|
||||
@@ -26,10 +24,33 @@ import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* 3DES加解密
|
||||
* 3DES(Triple DES)加解密工具类
|
||||
* <p>
|
||||
* <strong>⚠ 已废弃 — 请勿在新代码中使用</strong>
|
||||
* </p>
|
||||
* <h2>废弃原因</h2>
|
||||
* <ul>
|
||||
* <li>NIST SP 800-131A(2023)已正式废弃 3DES/TDEA,禁止用于新系统</li>
|
||||
* <li>3DES 有效密钥长度仅 112 位,低于现代安全标准(AES-256)</li>
|
||||
* <li>存在 Sweet32 攻击风险(CBC 模式下处理大量数据时)</li>
|
||||
* <li>性能较差(AES 约快 3-5 倍)</li>
|
||||
* </ul>
|
||||
* <h2>迁移建议</h2>
|
||||
* <pre>{@code
|
||||
* // 旧代码(3DES)
|
||||
* String encrypted = DES3.encryptDesCbc(plaintext, key);
|
||||
*
|
||||
* // 新代码(AES-GCM,推荐)
|
||||
* String encrypted = AES.encryptGCM(plaintext, aesKey);
|
||||
* String decrypted = AES.decryptGCM(encrypted, aesKey);
|
||||
* }</pre>
|
||||
*
|
||||
* @author yexuejc
|
||||
* @date 2018/9/3 17:09
|
||||
* @deprecated 3DES 已被 NIST 废弃,请迁移至 {@link AES} 的 GCM 模式。
|
||||
* 参见 NIST SP 800-131A Rev. 2 (2023)。
|
||||
* @see AES#encryptGCM(String, String)
|
||||
* @see AES#decryptGCM(String, String)
|
||||
*/
|
||||
@Deprecated
|
||||
public class DES3 {
|
||||
@@ -41,13 +62,13 @@ public class DES3 {
|
||||
private static final String TRANSFORMATION = "desede/CBC/PKCS5Padding";
|
||||
|
||||
/**
|
||||
* DESCBC加密
|
||||
* 3DES CBC 模式加密
|
||||
*
|
||||
* @param src 数据源
|
||||
* @param key 密钥,长度至少24位
|
||||
* @return 返回加密后的数据
|
||||
* @throws BaseException 加密异常
|
||||
* @deprecated 3DES已被NIST标准废弃,请使用 {@link AES#encryptGCM(String, String)}
|
||||
* @param src 明文数据
|
||||
* @param key 密钥(长度至少 24 字节)
|
||||
* @return Base64 编码的密文(IV + 密文拼接)
|
||||
* @throws BaseException 加密失败时抛出
|
||||
* @deprecated 3DES 已废弃,请使用 {@link AES#encryptGCM(String, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static String encryptDesCbc(final String src, final String key) throws BaseException {
|
||||
@@ -57,14 +78,14 @@ public class DES3 {
|
||||
try {
|
||||
Key deskey = generateKey(key);
|
||||
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
|
||||
// 使用更安全的随机IV
|
||||
// 使用随机 IV(每次加密不同)
|
||||
byte[] ivBytes = new byte[8];
|
||||
new SecureRandom().nextBytes(ivBytes);
|
||||
IvParameterSpec ips = new IvParameterSpec(ivBytes);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
|
||||
byte[] encryptData = cipher.doFinal(src.getBytes(CHARSET));
|
||||
|
||||
// 将IV与加密数据一起返回
|
||||
// 将 IV 与密文拼接返回(解密时需要)
|
||||
byte[] result = new byte[ivBytes.length + encryptData.length];
|
||||
System.arraycopy(ivBytes, 0, result, 0, ivBytes.length);
|
||||
System.arraycopy(encryptData, 0, result, ivBytes.length, encryptData.length);
|
||||
@@ -76,13 +97,13 @@ public class DES3 {
|
||||
}
|
||||
|
||||
/**
|
||||
* DESCBC解密
|
||||
* 3DES CBC 模式解密
|
||||
*
|
||||
* @param src 数据源
|
||||
* @param key 密钥,长度至少24位
|
||||
* @return 返回解密后的原始数据
|
||||
* @throws BaseException 解密异常
|
||||
* @deprecated 3DES已被NIST标准废弃,请使用 {@link AES#decryptGCM(String, String)}
|
||||
* @param src Base64 编码的密文(IV + 密文拼接)
|
||||
* @param key 密钥(长度至少 24 字节)
|
||||
* @return 解密后的明文
|
||||
* @throws BaseException 解密失败时抛出
|
||||
* @deprecated 3DES 已废弃,请使用 {@link AES#decryptGCM(String, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static String decryptDesCbc(final String src, final String key) throws BaseException {
|
||||
@@ -93,7 +114,7 @@ public class DES3 {
|
||||
Key deskey = generateKey(key);
|
||||
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
|
||||
|
||||
// 从加密数据中提取IV
|
||||
// 从密文中提取 IV(前 8 字节)
|
||||
byte[] srcBytes = Base64.getUrlDecoder().decode(src);
|
||||
byte[] ivBytes = new byte[8];
|
||||
byte[] encryptedData = new byte[srcBytes.length - 8];
|
||||
@@ -111,13 +132,13 @@ public class DES3 {
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成3DES密钥
|
||||
* 生成 3DES 密钥
|
||||
*
|
||||
* @param key 密钥字符串
|
||||
* @return Key对象
|
||||
* @throws InvalidKeyException 密钥生成异常
|
||||
* @throws NoSuchAlgorithmException 密钥生成异常
|
||||
* @throws InvalidKeySpecException 密钥生成异常
|
||||
* @param key 密钥字符串(至少 24 字节)
|
||||
* @return Key 对象
|
||||
* @throws InvalidKeyException 密钥无效
|
||||
* @throws NoSuchAlgorithmException 算法不支持
|
||||
* @throws InvalidKeySpecException 密钥规格无效
|
||||
*/
|
||||
private static Key generateKey(String key) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
DESedeKeySpec spec = new DESedeKeySpec(key.getBytes(CHARSET));
|
||||
@@ -126,21 +147,36 @@ public class DES3 {
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充,不是8的倍数会填充成8的倍数
|
||||
* 零填充(将数据填充至 8 字节的倍数)
|
||||
* <p>
|
||||
* <strong>⚠ 不安全 — 请勿使用</strong>
|
||||
* </p>
|
||||
* <h3>问题</h3>
|
||||
* <ul>
|
||||
* <li>使用零字节填充,无法区分数据与填充(若数据本身以 \0 结尾会丢失)</li>
|
||||
* <li>易受 padding oracle 攻击</li>
|
||||
* <li>不符合 PKCS#5/PKCS#7 标准填充规范</li>
|
||||
* </ul>
|
||||
* <h3>建议</h3>
|
||||
* <p>使用 Cipher 自带的 PKCS5Padding(已在 {@link #TRANSFORMATION} 中配置),
|
||||
* 无需手动填充。</p>
|
||||
*
|
||||
* @param str 待填充的字符串
|
||||
* @return 填充后的字符串
|
||||
* @deprecated 零填充不安全且不标准。请使用 Cipher 自带的 PKCS5Padding,
|
||||
* 或迁移至 AES-GCM(无需手动填充)。
|
||||
*/
|
||||
@Deprecated
|
||||
public static String padding(String str) {
|
||||
byte[] oldByteArray = str.getBytes(CHARSET);
|
||||
int len = 8;
|
||||
int numberToPad = len - oldByteArray.length % len;
|
||||
if (numberToPad == len) {
|
||||
// 如果已经是8的倍数,则不填充
|
||||
numberToPad = 0;
|
||||
}
|
||||
byte[] newByteArray = new byte[oldByteArray.length + numberToPad];
|
||||
System.arraycopy(oldByteArray, 0, newByteArray, 0, oldByteArray.length);
|
||||
// 零填充(不安全)
|
||||
for (int i = oldByteArray.length; i < newByteArray.length; ++i) {
|
||||
newByteArray[i] = 0;
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
|
||||
| # | 问题 | 文件 | 行号 | 说明 |
|
||||
|---|------|------|------|------|
|
||||
| S9 | **3DES 已废弃** | `DES3.java` | 全文件 | NIST 2023 年已废弃 3DES,建议迁移至 AES-GCM |
|
||||
| S10 | **3DES 零填充** | `DES3.java` | 129-143 | `padding()` 使用零填充而非 PKCS5/PKCS7,无法区分数据与填充、易受 padding oracle 攻击 |
|
||||
| S9 | ✅ **已修复** | `DES3.java` | 类级 | 类已标记 `@Deprecated`,JavaDoc 说明 NIST 2023 废弃原因,指向 AES-GCM 迁移方案 |
|
||||
| S10 | ✅ **已修复** | `DES3.java` | `padding()` | 零填充方法标记 `@Deprecated`,JavaDoc 说明安全问题(无法区分数据/填充、padding oracle 风险),建议使用 PKCS5Padding 或 AES-GCM |
|
||||
| S11 | **JWT 密钥零填充** | `JwtUtil.java` | 172-184 | `getSecretKey()` 对短密钥用零字节填充,削弱密钥熵 |
|
||||
| S12 | **JWT 默认 24h 过期** | `JwtUtil.java` | 94 | `expireSeconds = 86400`,建议由调用方显式设置 |
|
||||
| S13 | **JwtUtil 非线程安全** | `JwtUtil.java` | 全文件 | 单例模式中配置字段非 volatile,多线程设置不同配置会竞态 |
|
||||
|
||||
Reference in new issue
Block a user