如何加密 Java:自訂 XOR 加密與 GroupDocs

介紹

如果你曾經需要為特定工作流程 how to encrypt java 程式碼,便會體會到內建選項無法符合舊有協議或效能目標的挫折感。想像一下,你正將一個新的簽署模組整合到期待簡單 XOR 掩碼負載的舊 ERP 系統中。你可以重寫整個 ERP,但更快的做法是直接在 Java 應用程式內加入輕量級的自訂加密層。

在本指南中,我們將逐步說明如何建立自訂 XOR 加密機制,將其套用到 GroupDocs.Signature for Java,並討論何時此方法合適、何時應該改用業界標準演算法。完成後,你將能保護簽章中介資料、符合特殊的整合合約,並了解在正式產品程式碼中使用 XOR 的取捨。

以下是你將學到的內容:

  • 為何在舊有系統與效能情境下自訂加密很重要
  • XOR 加密的原理(淺顯說明 + Java 範例)
  • 與 GroupDocs.Signature for Java 的逐步整合
  • 真實案例、資安考量與常見陷阱
  • 如何在之後將 XOR 實作替換為更強的演算法

快速解答

  • 什麼是 XOR 加密? 一種使用金鑰翻轉位元的對稱運算;使用相同金鑰加密兩次會還原原始資料。
  • 什麼時候該使用自訂加密? 用於舊系統相容性、效能關鍵的混淆或學習目的——不適合保護敏感資料。
  • 本教學使用哪個函式庫? GroupDocs.Signature for Java(v23.12 或更新版本)。
  • 是否需要授權? 免費試用可用於測試;正式環境需購買完整授權。
  • 之後可以將 XOR 換成 AES 嗎? 可以——只要在保留相同 IDataEncryption 介面的前提下,替換 encrypt/decrypt 的實作即可。

什麼是 Java 中的自訂加密?

IDataEncryption 是 GroupDocs.Signature 提供的介面,定義了加密與解密資料的方法。自訂加密讓你能精確決定資料在儲存或傳輸前的轉換方式。使用 GroupDocs.Signature 時,只要提供 IDataEncryption 介面的實作,函式庫會在需要保護簽章資料時自動呼叫你的程式碼。這種外掛模式意味著你可以先以簡單的 XOR 程式作為概念驗證,之後再換成 AES‑256,而無需更動其他簽署流程。

為何自訂加密很重要

當現有演算法無法滿足特定限制(例如舊有協議格式、嚴格的效能預算或專有合約需求)時,自訂加密就顯得相當有價值。自行實作例程可讓你完整掌控資料轉換、降低開銷,並確保相容性而不必重寫外部系統,同時仍可利用 GroupDocs 的可擴充性。

舊系統整合

舊系統有時需要非常特定的位元組轉換——通常是使用單一位元組金鑰的 XOR。重新設計這些系統成本高昂,因此以自訂加密器符合其預期是較實際的做法。

效能最佳化

像 AES‑256 這類標準演算法在密碼學上很強大,但會消耗相當的 CPU 時間,尤其在低功耗裝置或處理數百萬筆小型負載時更為明顯。XOR 每個位元組只需一條 CPU 指令,對非敏感資料而言幾乎沒有額外負擔。

專有需求

某些合約或產業標準會規定使用自訂演算法(例如政府要求的「XOR‑mask」)。自行實作所需邏輯可確保符合規範,同時讓其餘系統保持現代化。

學習與彈性

打造自訂加密器會迫使你了解位元組層級的操作、金鑰管理,以及 IDataEncryption 介面的合約導向設計。這些知識在日後採用更複雜的密碼學時會大有幫助。

專業提示: 只在已經受到其他層級(TLS、VPN 或資料庫加密)保護的資料上使用自訂加密。切勿僅依賴 XOR 作為個人或金融資訊的唯一防線。

了解 XOR:基礎概念

XOR(異或)比較兩個位元,若不同則回傳 1,相同則回傳 0:

  • 0 XOR 0 = 0
  • 0 XOR 1 = 1
  • 1 XOR 0 = 1
  • 1 XOR 1 = 0

因為此運算本身即為其逆運算,第二次使用相同金鑰即可還原原始值。在 Java 中,你可以使用 ^ 運算子對兩個位元組進行 XOR:

byte encrypted = (byte)(plainByte ^ key);

當你對整個位元組陣列使用單一位元組金鑰進行 XOR 時,會得到快速且可逆的轉換。請記住,單一位元組金鑰僅有 255 種可能的變化,因此任何擁有少量密文的人都能立即暴力破解金鑰。此作法僅適用於混淆,絕不可用於保護機密資料。

前置條件

在使用 GroupDocs.Signature for Java 實作自訂加密之前,請確保已具備以下條件:

必要的函式庫與相依性

  • GroupDocs.Signature for Java – 版本 23.12 或更新(整篇使用的 API)。
  • Java Development Kit – JDK 8 或更新;建議使用 JDK 11 以獲得長期支援。

環境設定需求

  • 如 IntelliJ IDEA、Eclipse 或具 Java 擴充功能的 VS Code 等 IDE。
  • Maven 或 Gradle 進行相依管理(兩者皆支援)。

知識前置條件

  • 熟悉 Java 類別、介面與位元組陣列操作。
  • 具備對稱加密概念的基本認識(已在 XOR 章節說明)。

如果上述條件皆符合,即可開始將 GroupDocs 加入你的專案。

設定 GroupDocs.Signature for Java

將函式庫加入建置系統只需一行 XML 或 Groovy 設定。

Maven

<dependency>
    <groupId>com.groupdocs</groupId>
    <artifactId>groupdocs-signature</artifactId>
    <version>23.12</version>
</dependency>

Gradle

implementation 'com.groupdocs:groupdocs-signature:23.12'

直接下載

如果你偏好手動管理,可從 GroupDocs.Signature for Java releases 下載 JAR,並加入至 classpath。

取得授權步驟

  1. 免費試用 – 下載試用版 JAR;輸出檔案會有可見的浮水印。
  2. 臨時授權 – 申請 30 天評估金鑰以完整測試功能。
  3. 購買 – 取得永久授權以供正式上線使用。

基本初始化與設定

Signature signature = new Signature("sample.pdf");

Signature 物件是 GroupDocs.Signature 中所有簽署、驗證與加密操作的入口。

實作指南

自訂 XOR 加密功能

我們將建立一個實作 IDataEncryption 介面的類別,並將其註冊至 Signature 物件。

步驟 1:實作 IDataEncryption 介面

IDataEncryption 是 GroupDocs.Signature 介面,定義了加密與解密資料的方法。

public class CustomXOREncryption implements IDataEncryption {
    private byte auto_Key = 0x5A; // example key

    @Override
    public byte[] encrypt(byte[] data) { /* implementation below */ }

    @Override
    public byte[] decrypt(byte[] data) { /* implementation below */ }

    public void setKey(byte key) { this.auto_Key = key; }
    public byte getKey() { return this.auto_Key; }
}

發生了什麼: 此類別承諾兩個核心操作——encrypt 與 decrypt。欄位 auto_Key 保存將套用於負載每個位元組的 XOR 金鑰。

步驟 2:定義加密與解密方法

因為 XOR 是對稱的,兩個方法執行相同的位元組轉換。

public byte[] encrypt(byte[] data) {
    if (auto_Key == 0 || data == null) return data;
    byte[] result = new byte[data.length];
    for (int i = 0; i < data.length; i++) {
        result[i] = (byte)(data[i] ^ auto_Key);
    }
    return result;
}
public byte[] decrypt(byte[] data) {
    return encrypt(data); // XOR decryption is identical to encryption
}

說明:

  • 防護條件避免使用零金鑰(會變成無操作)以及 null 輸入。
  • 新的位元組陣列保存轉換後的資料,以免改變原始緩衝區。
  • 迴圈將每個位元組與 auto_Key 進行 XOR。
  • 解密僅再次呼叫 encrypt,因為相同的 XOR 兩次即可還原原始位元組。

金鑰設定選項

  • auto_Key 必須是 1 到 255 之間的非零值。超過 255 的值會被截斷為低 8 位元。
  • 請安全保存金鑰——建議使用環境變數、加密的設定檔或專用的祕密管理服務。
  • 在正式環境中,你可能會將此簡單的單位元組金鑰換成多位元組金鑰或完整的 AES 加密,但介面保持不變。

設定金鑰的範例

CustomXOREncryption xor = new CustomXOREncryption();
xor.setKey((byte)0x3C); // set a custom key at runtime
signature.setDataEncryption(xor);

常見實作錯誤

錯誤為何有問題如何修正
忘記設定金鑰加密變成無操作,資料以明文形式留下。使用加密器前務必呼叫 setKey(),或在建構子中提供預設的非零金鑰。
忽略 null 資料在簽署過程中導致 NullPointerException。在兩個方法的開頭加入 if (data == null) return data;。
假設 XOR 安全單一位元組金鑰可在毫秒內被暴力破解。僅將 XOR 用於混淆;對任何機密負載改用 AES‑256。
解密金鑰不匹配資料無法還原。將金鑰與加密負載一起保存,或使用金鑰識別映射。

安全性考量

為何 XOR 不足以保護敏感資料

單一位元組金鑰的 XOR 幾乎沒有任何密碼學強度;攻擊者可以立即列舉全部 255 種金鑰。此運算亦會洩漏統計模式,使頻率分析與已知明文攻擊變得簡單。因此,絕不應僅以 XOR 作為個人、金融或任何機密資訊的唯一防護。

何時可接受使用 XOR

當資料已受到 TLS、VPN 或資料庫加密等更強層級保護,且掩碼僅用於阻止隨意檢視或符合舊有格式時,XOR 可安全使用。它適用於暫時性識別碼、快取金鑰或永不離開受信任環境的內部旗標。

推薦的強力替代方案

  • AES‑256 – 產業標準,透過 javax.crypto 原生支援。
  • RSA‑2048 – 適合加密小型對稱金鑰。
  • ChaCha20 – 在行動裝置 CPU 上具高效能。

由於 IDataEncryption 合約對演算法保持中立,切換至 AES 只需將 encrypt/decrypt 的實作內容換成相應的加密呼叫即可。

實務應用

1. 安全文件簽署工作流程

你可能需要以防止隨意檢視的方式儲存簽署者的中介資料(ID、時間戳記、部門)。使用我們的 XOR 加密器,這些中介資料會以位元組陣列形式存放於簽章套件內,而 PDF 其餘部分則保持不變。

Signature signature = new Signature("contract.pdf");
signature.setDataEncryption(new CustomXOREncryption());
SignatureResult result = signature.sign("output.pdf", options);

2. 輕量完整性檢查

加密一個已知常數並與文件一起保存。之後解密並比對,以驗證檔案在傳輸過程中未受損壞。

3. 舊系統橋接

舊的主機系統期待每個位元組皆以 0x7F 進行 XOR 掩碼的負載。只要在 CustomXOREncryption 中設定相同金鑰,即可在不另寫轉換服務的情況下交換資料。

效能考量

原始速度

XOR 在現代 x86 核心上大約每位元組 1 ns,也就是說 10 MB 的負載加密時間遠低於 10 ms。相比之下,使用 CBC 模式的 AES‑256 同樣大小的資料通常需要 3‑4 倍的時間。

記憶體占用

我們的實作會複製輸入陣列,暫時將記憶體使用量加倍。對於 50 MB 的檔案,加密時大約需要 100 MB 的堆積空間。若需處理更大的檔案,請以 4 KB 為單位分段處理串流:

InputStream in = new FileInputStream(source);
OutputStream out = new FileOutputStream(target);
byte[] buffer = new byte[4096];
int read;
while ((read = in.read(buffer)) != -1) {
    for (int i = 0; i < read; i++) {
        buffer[i] ^= key;
    }
    out.write(buffer, 0, read);
}

Java 記憶體管理最佳實踐

  1. 使用後將金鑰清零:Arrays.fill(keyArray, (byte)0);
  2. 使用 try‑with‑resources 以確保串流關閉。
  3. 避免將加密位元組轉換為 String;保持為原始的 byte[]。
  4. 使用 VisualVM 等工具監控堆積,在同時處理多個大型文件時尤為重要。

常見問題排除

問題 1 – 「解密後的資料看起來像雜訊」

直接答案: 確認加密與解密使用相同的 XOR 金鑰,整個流程保持資料為位元組陣列,並避免任何可能破壞位元組的字元編碼轉換。

發生原因: 金鑰不匹配、資料截斷或意外的 String 轉換會改變位元組模式,導致輸出無法閱讀。

問題 2 – 「加密時發生 NullPointerException」

直接答案: encrypt 方法已檢查 null 輸入;若仍出現例外,請確認來源位元組陣列在傳入加密器前已正確初始化。

修正方式: 在呼叫端加入防護檢查,或確保在加密前以 signature.getSignatureData() 讀取文件的簽章資料。

問題 3 – 「加密似乎沒有作用」

直接答案: 通常表示 XOR 金鑰被設定為 0。零金鑰的 XOR 不會改變原始位元組,輸出與輸入相同。

解決方法: 透過 setKey() 設定非零金鑰,或在建構子中提供預設值。

問題 4 – 「大型 PDF 發生 OutOfMemoryError」

直接答案: 在加密前將整個 PDF 載入記憶體可能會超出 JVM 堆積。請改用分段串流方式處理檔案,如效能章節所示。

提示: 僅將最大堆積 (-Xmx2g) 提升作為暫時措施;為了可擴充性,應重構為分塊處理。

常見問答

Q: 如何選擇適當的 XOR 金鑰?
A: 任意 1 到 255 之間的非零整數皆可,但金鑰本身不提供安全性。若需真正保護,請改用 AES‑256,並將金鑰存放於安全保管庫。

Q: 可以在執行時變更 XOR 金鑰嗎?
A: 可以——呼叫 setKey() 並傳入新值。請記得在切換前先以舊金鑰解密資料,否則將無法存取該資料。

Q: 有哪些 XOR 加密的替代方案?
A: 作為學習可嘗試凱撒密碼或 Base64(僅是編碼)。在正式環境中,請使用 AES‑256、RSA‑2048 或透過 Java javax.crypto 套件的 ChaCha20。

Q: GroupDocs.Signature 在處理大型檔案加密時如何運作?
A: 函式庫會在可能的情況下串流 PDF 內容,但自訂的 IDataEncryption 實作決定資料的處理方式。請實作基於分塊的加密,以避免將整個檔案載入記憶體。

Q: 能將此功能整合至 Web 應用程式嗎?
A: 完全可以。將加密器註冊為 Spring Bean,注入 Signature 服務,並將金鑰存放於環境變數或祕密管理器。確保每個請求在獨立執行緒中處理資料,以避免競爭。

XOR 加密在 Java 中如何運作?

在 Java 中,XOR 透過 ^ 運算子作用於位元組值。先將明文載入位元組陣列,遍歷每個元素並套用 byte ^ key。因為 XOR 本身即為逆運算,使用相同金鑰執行相同例程即可還原原始位元組,使加密與解密具對稱性。

使用 GroupDocs 實作自訂加密的步驟是什麼?

要加入自訂加密,首先建立一個實作 IDataEncryption 介面的類別,然後以你的演算法編寫 encrypt 與 decrypt 方法。之後,透過 setDataEncryption 將實例註冊至 Signature 物件。從此,GroupDocs 會在需要保護簽章資料時呼叫你的程式碼。

結論

我們已完整說明如何使用自訂 XOR 程式 how to encrypt java、將其整合至 GroupDocs.Signature,並強調此輕量方法的適用情境。請記住:

  • 僅將 XOR 用於混淆,絕不可用於保護個人或金融資料。
  • IDataEncryption 介面提供了日後換成更強演算法的乾淨切換點。
  • 正確的金鑰管理、記憶體處理與串流機制是正式環境穩定性的關鍵。

下一步:

  1. 將 XOR 邏輯換成 AES‑256 以獲得真正的安全性。
  2. 實作金鑰輪替與安全存儲。
  3. 探索 GroupDocs 其他功能,如多簽章工作流程、驗證與文件蓋章。

現在你已具備在任何 Java 簽署解決方案中自訂加密的堅實基礎——快依照你的業務需求進行客製化吧!


最後更新: 2026-06-26
測試環境: GroupDocs.Signature 23.12 for Java
作者: GroupDocs

Original data: 5 (binary: 0101)
Key: 3 (binary: 0011)
Encrypted: 5 XOR 3 = 6 (binary: 0110)
Decrypted: 6 XOR 3 = 5 (binary: 0101) ← We're back!
<dependency>
    <groupId>com.groupdocs</groupId>
    <artifactId>groupdocs-signature</artifactId>
    <version>23.12</version>
</dependency>
implementation 'com.groupdocs:groupdocs-signature:23.12'
import com.groupdocs.signature.Signature;

class InitializeGroupDocs {
    public static void main(String[] args) {
        Signature signature = new Signature("path/to/your/document");
        // Additional setup and operations can be performed here.
    }
}
import com.groupdocs.signature.domain.extensions.encryption.IDataEncryption;

class CustomXOREncryption implements IDataEncryption {
    private int auto_Key;
    
    public final int getKey() {
        return auto_Key;
    }
    
    // Additional methods for encryption and decryption will be implemented here.
}
class CustomXOREncryption {
    private int auto_Key;

    public byte[] encrypt(byte[] data) {
        if (auto_Key == 0 || data == null) return data;
        
        byte[] result = new byte[data.length];
        for (int i = 0; i < data.length; i++) {
            result[i] = (byte) (data[i] ^ auto_Key);
        }
        return result;
    }

    public byte[] decrypt(byte[] encryptedData) {
        // Since XOR is symmetric, use the same method as encryption
        return encrypt(encryptedData);
    }
}
CustomXOREncryption encryption = new CustomXOREncryption();
encryption.setKey(42); // Any non-zero value works
CustomXOREncryption encryption = new CustomXOREncryption();
// Oops! Never called setKey(), so auto_Key is 0
byte[] encrypted = encryption.encrypt(myData); // Returns data unchanged!
Signature signature = new Signature("contract.pdf");
CustomXOREncryption encryption = new CustomXOREncryption();
encryption.setKey(73); // Configure your key

// GroupDocs will use your encryption for signature data
// (Actual integration depends on specific GroupDocs API methods)
String integrityToken = "VALID_SIGNATURE_2025";
byte[] encrypted = encryption.encrypt(integrityToken.getBytes());
// Store encrypted with document...
// Later, decrypt and compare to verify nothing changed
// Old system expects data encrypted with XOR key 42
CustomXOREncryption legacyEncryption = new CustomXOREncryption();
legacyEncryption.setKey(42);

// Encrypt data before sending to legacy system
byte[] dataForOldSystem = legacyEncryption.encrypt(modernData);
sendToLegacyAPI(dataForOldSystem);
// More memory‑efficient for large data
public void encryptInPlace(byte[] data) {
    if (auto_Key == 0 || data == null) return;
    
    for (int i = 0; i < data.length; i++) {
        data[i] = (byte) (data[i] ^ auto_Key);
    }
}
   Arrays.fill(decryptedData, (byte) 0); // Overwrite with zeros
   try (FileInputStream fis = new FileInputStream("encrypted.dat")) {
       // Process data
   } // Automatically closed
assert auto_Key != 0 : "Encryption key must be set!";
try (FileInputStream in = new FileInputStream(path);
     FileOutputStream out = new FileOutputStream(encryptedPath)) {
    byte[] buffer = new byte[4096];
    int bytesRead;
    while ((bytesRead = in.read(buffer)) != -1) {
        encryptInPlace(buffer, 0, bytesRead);
        out.write(buffer, 0, bytesRead);
    }
}
@Component
public class EncryptionService {
    private CustomXOREncryption encryption;
    
    public EncryptionService(@Value("${app.encryption.key}") int key) {
        this.encryption = new CustomXOREncryption();
        this.encryption.setKey(key);
    }
    // Use in your controllers...
}

相關教學