Java 中的抗量子 ML-KEM 和 ML-DSA
1. 概述
ML-KEM (基於模組格的金鑰封裝機制)是一種後量子加密金鑰交換演算法,它允許雙方安全地建立共享金鑰,即使面對未來量子電腦的攻擊也能有效防禦。另一方面, ML-DSA (基於模組格的數位簽章演算法)是一種後量子數位簽章演算法,它能夠實現安全的身份驗證和訊息完整性保護,並能抵禦量子電腦的攻擊。
在 Java 24 之前,ML-KEM 和 ML-DSA 並非標準 JDK(Java 開發工具包)的一部分。我們必須使用像 Bounty Castle 這樣的外部函式庫來執行加密操作。
自 Java 24 以來,這兩種演算法都已成為 Java 原生 API 的一部分。 JEP 496和JEP 497分別提出了 Java 原生 API 中的 ML-KEM 和 ML-DSA 實作。
在本教程中,我們將討論在 Java 中使用抗量子 ML-KEM 和 ML-DSA。
2. 抗量子ML-KEM
金鑰封裝機制允許雙方(即發送方和接收方)在不安全的網路上安全地交換共用金鑰。此機制包含以下步驟:
- 接收者產生公鑰/私鑰對
- 發送方使用公鑰創建一個加密的共享密鑰。
- 接收者使用私鑰解密加密的共享金鑰。
因此,雙方都獲得了相同的密鑰。這個共享金鑰可以與對稱金鑰演算法(例如 AES(高級加密標準)和 Blowfish)一起使用。
ML-KEM 基於 M-LWE(帶誤差的模組學習)問題,此問題計算難度很高。 M-LWE 問題的難度也取決於模組格中某些計算問題的難度。因此,ML-KEM 能夠抵抗經典攻擊和量子攻擊。
2.1 產生密鑰對
首先,我們在接收端產生一個 ML-KEM 金鑰對:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-KEM");
kpg.initialize(NamedParameterSpec.ML_KEM_768);
KeyPair receiverKeyPair = kpg.generateKeyPair();
PrivateKey privateKey = receiverKeyPair.getPrivate();
PublicKey publicKey = receiverKeyPair.getPublic();
首先,我們取得一個用於 ML-KEM 演算法的KeyPairGenerator物件。然後,我們選擇ML_KEM_768來設定要產生的金鑰的安全等級。 JEP 496 增加了對 ML-KEM-512、ML-KEM-768 和 ML-KEM-1024 的支援。實際上, ML_KEM_768是預設選項,也就是說,如果我們不使用initialize()方法初始化KeyPairGenerator對象,安全性等級仍然會是ML_KEM_768 。
也可以直接將安全強度傳遞給getInstance() 。在這種情況下,我們也不需要呼叫initialize()方法:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-KEM-768");
KeyPair receiverKeyPair = kpg.generateKeyPair();
receiverKeyPair類型為KeyPair ,包含一個公鑰和一個私鑰。我們可以分別使用getPublic()和getPrivate()成員方法存取這些金鑰。接收者可以安全地將公鑰分享給發送方,但私鑰必須保密。
2.2 產生和封裝共享密鑰
發送方收到接收方的公鑰後,會產生並封裝一個共享的私鑰,供發送者和接收者共同使用:
KEM senderKem = KEM.getInstance("ML-KEM");
KEM.Encapsulator encapsulator = senderKem.newEncapsulator(publicKey);
KEM.Encapsulated encapsulated = encapsulator.encapsulate();
SecretKey senderSharedSecret = encapsulated.key();
byte[] ciphertext = encapsulated.encapsulation();
senderSharedSecret**是通訊中使用的實際金鑰。但發送方不會直接將其發送給接收方,而是使用接收方的公鑰對其進行加密封裝後再發送。 ciphertext **ciphertext於senderSharedSecret的加密版本。
2.3. 解封裝共享密鑰
接收者收到加密後的金鑰後,使用私鑰對金鑰進行解密:
KEM receiverKem = KEM.getInstance("ML-KEM");
KEM.Decapsulator decapsulator = receiverKem.newDecapsulator(privateKey);
SecretKey receiverSharedSecret = decapsulator.decapsulate(ciphertext);
實際的金鑰receiverSharedSecret是透過解封裝接收到的ciphertext提取出來的。因此,雙方都獲得了用於對稱加密和解密的同一個共享金鑰。我們可以透過以下方式驗證雙方是否使用了相同的金鑰:
boolean match = Arrays.equals(senderSharedSecret.getEncoded(), receiverSharedSecret.getEncoded());
比較結果為true 。因此,我們實現了在不安全網路上的安全通訊。此外,與RSA或Diffie-Hellman演算法不同,此方法能夠抵抗量子攻擊。
3. 抗量子ML-DSA
數位簽章演算法是一種加密方法,用於驗證數位資訊或文件的真實性和完整性。該演算法包含以下步驟:
- 簽署者(發送者)創建公鑰/私鑰對。
- 簽名者使用訊息和私鑰創建簽名。
- 驗證者(接收者)使用接收的訊息和公鑰驗證簽章。
與 ML-KEM 類似,ML-DSA 也基於 M-LWE 問題和另一個計算難度極高的問題 M-SIS(模短整數解) 。因此,ML-DSA 能夠抵抗經典攻擊和量子攻擊。
3.1 產生密鑰對
首先,我們在簽名方產生一個 ML-DSA 金鑰對:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-DSA");
kpg.initialize(NamedParameterSpec.ML_DSA_65);
KeyPair kp = kpg.generateKeyPair();
PrivateKey privateKey = kp.getPrivate();
PublicKey publicKey = kp.getPublic();
首先,我們取得一個用於 ML-DSA 演算法的KeyPairGenerator物件。然後,我們選擇ML_DSA_65來設定要產生的金鑰的安全強度。實際上, ML_DSA_65是預設選項。 JEP 497 增加了對 ML-DSA-44、ML-DSA-65 和 ML-DSA-87 的支援。
與 ML-KEM 類似,可以直接將安全強度傳遞給getInstance() 。
3.2 簽署
然後,我們(簽署者)使用私鑰對要傳送的訊息進行簽署:
Signature signature = Signature.getInstance("ML-DSA");
String message = "This is a test message signed";
byte[] messageBytes = message.getBytes();
signature.initSign(privateKey);
signature.update(messageBytes);
byte[] sigBytes = signature.sign();
首先,我們取得一個實作了 ML-DSA 演算法的Signature物件。然後,我們使用initSign()方法初始化該物件以進行簽名。我們將私鑰傳遞給此方法。接著,我們使用 ` update()方法將訊息更新到Signature物件。最後,**我們使用Signature物件的 ` sign()方法建立數位簽章**。
3.3 驗證
然後,在收到訊息和簽名後,我們(驗證者)使用公鑰驗證簽名:
signature.initVerify(publicKey);
signature.update(messageBytes);
boolean isValid = signature.verify(sigBytes);
這次,我們使用initVerify()方法初始化用於驗證的Signature物件。然後,我們使用update()方法將從簽署者收到的訊息更新到Signature物件。最後,我們使用Signature物件的verify()方法來驗證簽章。該方法傳回true 。驗證成功意味著簽名是使用相應的私鑰創建的。
4. 結論
本文探討了在 Java 中使用抗量子計算的 ML-KEM 和 ML-DSA 演算法。首先,我們了解到這些演算法在 Java 24 之前的標準 JDK 中並不存在。
接下來,我們了解了這些演算法在 Java 中的應用。我們使用 ML-KEM 模擬了接收方和發送方之間的金鑰交換。類似地,我們使用 ML-DSA 模擬了雙方之間的訊息簽章和簽章驗證。正如我們在範例中看到的,Java 24 提供了KeyPairGenerator和KEM類別的 ML-KEM 實現,以及KeyPairGenerator和Signature類別的 ML-DSA 實作。
與往常一樣,範例的完整原始程式碼可在 GitHub 上找到。