資料加密與編碼是系統安全的基礎設施。本文提供兩個生產級工具類:DESUtil 實作 DES 對稱加密/解密(含 Base64 編碼輸出),Base64 實作標準 Base64 編碼/解碼(支援字串、位元組陣列、檔案)。程式碼基於 JDK 標準加密 API,無第三方依賴。
private String keyData = "ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstwxyz0123456789-_.";
private byte[] getKey() {
SecureRandom sr = new SecureRandom();
KeyGenerator kg = KeyGenerator.getInstance("DES");
kg.init(sr);
SecretKey key = kg.generateKey();
return key.getEncoded(); // 注意:每次生成不同密鑰!
}
關鍵缺陷:getKey() 每次調用生成新密鑰,導致加密解密密鑰不一致!原作者在註釋中已標註廢棄。
public String encrypt(String source, String charSet) throws UnsupportedEncodingException {
byte[] ret = encrypt(source.getBytes(charSet)); // 原始加密
return new String(Base64.encode(ret)); // Base64 編碼
}
private byte[] encrypt(byte[] primaryData) {
// 1. 建立 DESKeySpec(使用固定 keyData)
DESKeySpec dks = new DESKeySpec(keyData.getBytes());
// 2. 密鑰工廠生成 SecretKey
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(dks);
// 3. Cipher 初始化加密模式
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key, new SecureRandom());
// 4. 執行加密
return cipher.doFinal(primaryData);
}
public String decrypt(String encryptedData, String charSet)
throws UnsupportedEncodingException {
byte[] ret = descrypt(Base64.decode(encryptedData.toCharArray()));
return new String(ret, charSet);
}
private byte[] descrypt(byte[] encryptedData) {
// 同加密流程,但 Cipher.init 使用 DECRYPT_MODE
DESKeySpec dks = new DESKeySpec(keyData.getBytes());
SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key, new SecureRandom());
return cipher.doFinal(encryptedData);
}
DESUtil des = new DESUtil("MySecretKey8"); // 8 字元密鑰
String plain = "敏感資料加密測試";
String encrypted = des.encrypt(plain); // 加密 + Base64
String decrypted = des.decrypt(encrypted); // Base64 解碼 + 解密
System.out.println("原文: " + plain);
System.out.println("密文: " + encrypted);
System.out.println("解密: " + decrypted);
private static final char[] ALPHABET =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();
private static final byte[] CODES = new byte[256]; // 解碼查找表
static {
Arrays.fill(CODES, (byte) -1);
for (int i = 'A'; i <= 'Z'; i++) CODES[i] = (byte) (i - 'A');
for (int i = 'a'; i <= 'z'; i++) CODES[i] = (byte) (26 + i - 'a');
for (int i = '0'; i <= '9'; i++) CODES[i] = (byte) (52 + i - '0');
CODES['+'] = 62; CODES['/'] = 63; CODES['='] = 0;
}
// 編碼位元組陣列
public static char[] encode(byte[] data) {
char[] out = new char[((data.length + 2) / 3) * 4];
for (int i = 0, idx = 0; i < data.length; i += 3, idx += 4) {
int val = (data[i] & 0xFF) << 16;
if (i + 1 < data.length) val |= (data[i+1] & 0xFF) << 8;
if (i + 2 < data.length) val |= (data[i+2] & 0xFF);
out[idx+3] = ALPHABET[(i+2 < data.length) ? (val & 0x3F) : 64];
val >>= 6;
out[idx+2] = ALPHABET[(i+1 < data.length) ? (val & 0x3F) : 64];
val >>= 6;
out[idx+1] = ALPHABET[val & 0x3F];
val >>= 6;
out[idx] = ALPHABET[val & 0x3F];
}
return out;
}
// 解碼字元陣列
public static byte[] decode(char[] data) {
// 計算有效長度、分配輸出緩衝區、逐字元解碼還原位元組
// ... 核心邏輯:累積 6 位,每滿 8 位輸出一字節
}
public static void encode(File file) throws IOException {
byte[] decoded = readBytes(file);
char[] encoded = encode(decoded);
writeChars(file, encoded); // 覆蓋原檔案
}
public static void decode(File file) throws IOException {
char[] encoded = readChars(file);
byte[] decoded = decode(encoded);
writeBytes(file, decoded);
}
// 字串編碼
String encoded = Base64.encode("Hello World"); // SGVsbG8gV29ybGQ=
String decoded = Base64.decode(encoded); // Hello World
// 檔案編碼(圖片轉 Base64 字串)
Base64.encode(new File("image.png")); // 檔案內容變為 Base64 文本
Base64.decode(new File("image.png")); // 還原二進位
| 需求 | 推薦方案 | 優勢 |
|---|---|---|
| 對稱加密 | AES-GCM (JDK 8+) | 認證加密、效能佳、256位安全 |
| Base64 | java.util.Base64 (JDK 8+) | 標準庫、支援 Basic/URL/MIME、無依賴 |
| 密碼雜湊 | BCrypt / Argon2 | 自帶鹽值、可調計算成本、抗彩虹表 |
本文提供的 DESUtil 與 Base64 工具類代碼結構完整、功能齊全,適合學習加密編碼原理。但受限於演算法老舊(DES、ECB 模式)、密鑰管理缺陷,**嚴禁用於生產環境敏感資料加密**。現代專案請直接使用 JDK 8+ 內建 java.util.Base64 及 javax.crypto AES-GCM 實作。