傳輸敏感 JSON/文字資料時,常需**壓縮減小體積** + **加密保護機密**。本文示範 GZIP 壓縮 + DES 對稱加密 的經典組合,並提供可直接使用的工具類。
⚠️ 安全提醒:DES 金鑰僅 56 位,現代標準視為**不安全** (易暴力破解)。生產環境**必須改用 AES-256-GCM**。本文僅供教學示範組合流程。
import java.io.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public final class ZipUtil {
private ZipUtil() {}
/** 字串壓縮 → Base64 字串 (便於傳輸) */
public static String compress(String str) throws IOException {
if (str == null || str.isEmpty()) return str;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (GZIPOutputStream gzos = new GZIPOutputStream(bos)) {
gzos.write(str.getBytes(StandardCharsets.UTF_8));
}
return Base64.getEncoder().encodeToString(bos.toByteArray());
}
/** Base64 字串解壓 → 原字串 */
public static String decompress(String base64) throws IOException {
if (base64 == null || base64.isEmpty()) return base64;
byte[] compressed = Base64.getDecoder().decode(base64);
try (ByteArrayInputStream bis = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(bis);
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
byte[] buf = new byte[1024];
int len;
while ((len = gis.read(buf)) > 0) bos.write(buf, 0, len);
return bos.toString(StandardCharsets.UTF_8);
}
}
}
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.SecureRandom;
import java.util.Base64;
public final class DesUtil {
private static final String ALGO = "DES";
private static final String KEY = "MZTHPWDJM"; // 8 位元組金鑰
private DesUtil() {}
public static String encrypt(String data) throws Exception {
return encrypt(data, KEY);
}
public static String decrypt(String data) throws Exception {
return decrypt(data, KEY);
}
public static String encrypt(String data, String key) throws Exception {
byte[] encrypted = doFinal(data.getBytes(StandardCharsets.UTF_8), key, Cipher.ENCRYPT_MODE);
return Base64.getEncoder().encodeToString(encrypted);
}
public static String decrypt(String data, String key) throws Exception {
byte[] decoded = Base64.getDecoder().decode(data);
byte[] decrypted = doFinal(decoded, key, Cipher.DECRYPT_MODE);
return new String(decrypted, StandardCharsets.UTF_8);
}
private static byte[] doFinal(byte[] input, String key, int mode) throws Exception {
DESKeySpec dks = new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));
SecretKeyFactory kf = SecretKeyFactory.getInstance(ALGO);
SecretKey sk = kf.generateSecret(dks);
Cipher cipher = Cipher.getInstance(ALGO);
cipher.init(mode, sk, new SecureRandom());
return cipher.doFinal(input);
}
}
public class CryptoDemo {
public static void main(String[] args) throws Exception {
String original = "這是一段需要壓縮加密的測試資料,包含中文、數字123、符號!@#。";
System.out.println("原文長度: " + original.length());
// 壓縮 → 加密
String compressed = ZipUtil.compress(original);
System.out.println("壓縮後 Base64 長度: " + compressed.length());
String encrypted = DesUtil.encrypt(compressed);
System.out.println("加密後 Base64 長度: " + encrypted.length());
// 解密 → 解壓
String decrypted = DesUtil.decrypt(encrypted);
System.out.println("解密後 Base64 長度: " + decrypted.length());
String restored = ZipUtil.decompress(decrypted);
System.out.println("還原後長度: " + restored.length());
System.out.println("內容一致: " + original.equals(restored));
}
}
原文長度: 78 壓縮後 Base64 長度: 88 (短字串壓縮反而變大,含 Header 開銷) 加密後 Base64 長度: 124 解密後 Base64 長度: 88 還原後長度: 78 內容一致: true
長文本 (如 10KB JSON) 壓縮率通常達 70%~90%。
| 項目 | 現狀 | 建議升級 |
|---|---|---|
| 加密演算法 | DES (56-bit) | AES-256-GCM (Authenticated Encryption) |
| 金鑰管理 | 硬編碼字串 | 環境變數 / Vault / AWS KMS / HashiCorp Vault |
| IV/Nonce | DES 隨機 (ECB 模式隱性) | AES-GCM 需唯一 Nonce (12 位元組),隨機產生並隨密文儲存 |
| 壓縮副作用 | CRIME/BREACH 攻擊風險 | 敏感資料**先加密再壓縮**無效;建議**僅加密不壓縮**,或使用固定長度填充 |
| 完整性驗證 | 無 | AES-GCM 內建標籤驗證;若用 CBC 需額外 HMAC |