iT邦幫忙

2026 iThome 鐵人賽

0
Software Development

我是Java工程師,關於密碼學我想懂的不多系列 第 38 篇

Day37 - 後量子密碼學 (PQC):新一代加密標準 (ML-KEM / ML-DSA)

  • 分享至 

  • xImage
  •  

前言

在前面的章節中,我們建立在傳統非對稱密碼學(RSA、ECC、ECDH、ECDSA)與 PKI 體系的基礎上,構築了現代網路安全(TLS 1.3)與硬體安全(HSM/PKCS#11)的堅固防線。這些密碼學機制的安全性,全都依賴於傳統電腦無法在合理時間內解答的困難數學問題:大數分解問題(Integer Factorization)與離散對數問題(Discrete Logarithm Problem, DLP / ECDLP)。

然而,這座建造了數十年的安全大廈,正面臨著來自未來技術的毀滅性挑戰——量子電腦(Quantum Computer)。

2024 年 8 月,美國國家標準與技術研究院(NIST)正式頒布了全球首批後量子密碼學(Post-Quantum Cryptography, PQC)官方標準(FIPS 203、FIPS 204 與 FIPS 205),標誌著密碼學正式邁入 PQC 轉型時代。本章將剖析量子電腦對現有密碼學的實質威脅、解析 NIST PQC 新標準演算法(ML-KEM 與 ML-DSA)的數學基石(格密碼學),並透過 Java 實作新一代抗量子加密與數位簽章。

一、 量子電腦的毀滅性威脅:Shor 與 Grover 演算法

量子電腦利用量子位元(Qubit)的「疊加(Superposition)」與「糾纏(Entanglement)」特性,能在特定數學問題上實現相較於傳統電腦的指數級加速(Exponential Speedup)。

[ 傳統密碼學數學難題 ]
   ├── 大數分解問題 (RSA)              ──┐ (Shor 演算法: 指數級加速)
   ├── 離散對數問題 (Diffie-Hellman)   ──┼─────────────────────────────> 🚨 完全破解 (多項式時間內解開)
   └── 橢圓曲線離散對數問題 (ECC/ECDSA) ──┘

[ 對稱加密與雜湊函式 ]
   ├── AES-128 / AES-256             ──┐ (Grover 演算法: 平方級加速)
   └── SHA-256 / SHA-3               ──┴─────────────────────────────> ⚠️ 安全強度減半 (AES-256 依然安全)

1. Shor 演算法 (Shor's Algorithm):非對稱加密的終結者

1994 年由 Peter Shor 提出的量子演算法,可以在多項式時間(Polynomial Time, $\mathcal{O}((\log N)^3)$)內解出大數分解與離散對數問題。

  • 受害者:RSA、DH、ECDH、ECDSA、Ed25519、DSA。
  • 衝擊:只要一台具備約數千個邏輯 Qubit 的「具備容錯能力的量子電腦(CRQC)」,現有網際網路所有的 RSA 憑證、ECC 金鑰交換與 TLS 握手將瞬間形同虛設。

2. Grover 演算法 (Grover's Algorithm):對稱加密的強度減半

1996 年由 Lov Grover 提出的量子搜尋演算法,能對無結構的資料庫搜尋實現平方級加速(Quadratic Speedup)。

  • 衝擊:尋找 $N$-bit 窮舉搜尋的時間複雜度從 $\mathcal{O}(2^N)$ 降至 $\mathcal{O}(2^{N/2})$。
  • 影響與對策:
  • AES-128 的安全強度降至 $2^{64}$,不再安全。
  • AES-256 的安全強度降至 $2^{128}$,在量子時代依然絕對安全!因此對稱加密只需將金鑰長度提升至 256 位元即可防禦。

3. 「現在收集,未來解密」(Harvest Now, Decrypt Later, HNDL)攻擊

許多人認為:「量子電腦離商業化還有 10 到 15 年,我們現在需要擔心嗎?」

答案是:必須立刻採取行動。攻擊者(如國家級駭客組織)目前正在大量側錄並儲存金融機構、政府與企業傳送的 TLS 加密流量。一旦量子電腦問世,他們將拿著量子電腦解密歷史上錄下的所有敏感資料。這意味著,保護長效型敏感資料(如國防機密、醫療病歷、長期商業合約)的金鑰交換機制,必須現在就升級為 PQC!

二、 NIST PQC 新一代加密標準正式登場 (2024 FIPS)

經過長達 8 年(2016~2024)的全球密碼學徵集與多輪嚴格審查,NIST 於 2024 年 8 月正式發布了三項最終版 PQC 標準:

標準編號 官方演算法名稱 前身專案名稱 數學族群 密碼學用途 替代對象
FIPS 203 ML-KEM CRYSTALS-Kyber 模組格 (Module-LWE) 金鑰封裝機制 (KEM) RSA Key Exchange, ECDH
FIPS 204 ML-DSA CRYSTALS-Dilithium 模組格 (Module-LWE) 數位簽章 (Digital Signature) RSA PKCS#1 v1.5/PSS, ECDSA
FIPS 205 SLH-DSA SPHINCS+ 無狀態雜湊樹 (Hash-Based) 數位簽章 (Digital Signature) 保守備用簽章(不依賴格數學)

三、 格密碼學 (Lattice-Based Cryptography) 核心概念

ML-KEM 與 ML-DSA 的安全基礎建立在高維度格(Lattice)上的困難數學難題——例如容錯學習問題(Learning With Errors, LWE) 與 Module-LWE。

1. 什麼是格(Lattice)?

幾何學上,格是高維空間中無限延伸的散落點陣列。在幾何格空間中,尋找兩個點之間的最短距離向量,稱為最短向量問題(Shortest Vector Problem, SVP)。當空間維度擴展到數百甚至數千維時,不論是傳統電腦還是量子電腦,都無法## 四、 渡過期過渡架構:混合式金鑰交換 (Hybrid Key Exchange)

由於 PQC 演算法問世時間較短,密碼學界擔心未來格數學可能存在尚未被發現的理論漏洞。因此,RFC 9370 與 TLS 1.3 推進了混合式加密(Hybrid Cryptography):

$$
\text{Shared Secret} = \text{HKDF}(\text{ECDH Secret} \parallel \text{ML-KEM Secret})
$$

  • 雙重安全屏障:同時執行傳統 X25519 與後量子 ML-KEM-768。
  • 安全歸宿:即使 ML-KEM 未來被數學突破,X25519 能擋住目前的傳統駭客;即使量子電腦問世破了 X25519,ML-KEM 能擋住量子攻擊。兩者必須同時被破解,系統才會失效。時間內解出 SVP 問題。
2 維空間的格 (簡單)                  500+ 維度的高維格 (NP-Hard 難題)
•   •   •   •   •                    ┌                                 ┐
•   •   •   •   •  ───(量子電腦無法解)───> │ 求解 Shortest Vector (SVP)      │
•   •   •   •   •                    │ 找不到高維度格子點的極小向量     │
•   •   •   •   •                    └                                 ┘

2. KEM (Key Encapsulation Mechanism) 運作原理

在傳統 DH 中,兩端透過交換公鑰協商共享密鑰;而在 PQC 中,標準規範採用 KEM(金鑰封裝機制):

[ 接收方 (Bob) ]                                            [ 發送方 (Alice) ]
       │                                                           │
       ├─ 1. 生成 (pk, sk)                                         │
       ├────────────────────── 2. 傳送公鑰 pk ────────────────────>│
       │                                                           │
       │                                                           ├─ 3. [c, K] = Encaps(pk)
       │                                                           │     (產出密文 c 與對稱金鑰 K)
       │<───────────────────── 4. 傳送封包密文 c ──────────────────┤
       │                                                           │
       ├─ 5. K = Decaps(sk, c)                                     │
       │    (解封算出相同的對稱金鑰 K)                             └─ 持有對稱金鑰 K

四、 渡過期過渡架構:混合式金鑰交換 (Hybrid Key Exchange)

由於 PQC 演算法問世時間較短,密碼學界擔心未來格數學可能存在尚未被發現的理論漏洞。因此,RFC 9370 與 TLS 1.3 推進了混合式加密(Hybrid Cryptography):

$$
\text{Shared Secret} = \text{HKDF}(\text{ECDH Secret} \parallel \text{ML-KEM Secret})
$$

  • 雙重安全屏障:同時執行傳統 X25519 與後量子 ML-KEM-768。
  • 安全歸宿:即使 ML-KEM 未來被數學突破,X25519 能擋住目前的傳統駭客;即使量子電腦問世破了 X25519,ML-KEM 能擋住量子攻擊。兩者必須同時被破解,系統才會失效。

五、 Java 實戰:使用 Bouncy Castle 實現 ML-KEM 與 ML-DSA

標準 JDK 目前正在透過 JEP 逐步將 PQC 整合至原生 JCA 中。目前生產環境中最完整支援 NIST FIPS 203/204 的標準庫是 Bouncy Castle (v1.78+)。

以下範例演示如何在 Java 中使用 Bouncy Castle 執行 ML-KEM-768 金鑰封裝與 ML-DSA-65 數位簽章:

import org.bouncycastle.jcajce.SecretKeyWithEncapsulation;
import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
import org.bouncycastle.pqc.jcajce.spec.MLDSAParameterSpec;
import org.bouncycastle.pqc.jcajce.spec.MLKEMParameterSpec;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.KEMExtractSpec;
import javax.crypto.spec.KEMGenerateSpec;
import java.nio.charset.StandardCharsets;
import java.security.*;

public class PostQuantumCryptographyProductionExample {

    public static void main(String[] args) throws Exception {
        // 1. 動態註冊 Bouncy Castle PQC Provider
        Security.addProvider(new BouncyCastlePQCProvider());
        System.out.println("=== Day 37 - 後量子密碼學 (PQC) Java 實戰 ===");

        // =========================================================================
        // 實戰 1: ML-KEM-768 (FIPS 203) - 後量子金鑰封裝機制
        // =========================================================================
        System.out.println("\n--- [ 1. ML-KEM-768 金鑰封裝與解封測試 ] ---");

        // Step 1.1: 接收方 (Bob) 產生 ML-KEM-768 金鑰對
        KeyPairGenerator kemKeyPairGen = KeyPairGenerator.getInstance("ML-KEM", "BCPQC");
        kemKeyPairGen.initialize(MLKEMParameterSpec.ml_kem_768, new SecureRandom());
        KeyPair bobKeyPair = kemKeyPairGen.generateKeyPair();

        System.out.println("Bob 公鑰長度 (ML-KEM-768) : " + bobKeyPair.getPublic().getEncoded().length + " bytes");
        System.out.println("Bob 私鑰長度 (ML-KEM-768) : " + bobKeyPair.getPrivate().getEncoded().length + " bytes");

        // Step 1.2: 發送方 (Alice) 使用 Bob 的公鑰封裝 (Encapsulate) 產出對稱金鑰與密文
        KeyGenerator keyEncapsulator = KeyGenerator.getInstance("ML-KEM", "BCPQC");
        keyEncapsulator.init(new KEMGenerateSpec(bobKeyPair.getPublic(), "AES"), new SecureRandom());
  
        SecretKeyWithEncapsulation encapsResult = (SecretKeyWithEncapsulation) keyEncapsulator.generateKey();
        byte[] ciphertext = encapsResult.getEncapsulation(); // 傳給 Bob 的封裝密文
        SecretKey aliceSharedKey = encapsResult;             // Alice 算出的 AES 金鑰

        System.out.println("Alice 產出的密文長度: " + ciphertext.length + " bytes");

        // Step 1.3: 接收方 (Bob) 使用自己的私鑰解封 (Decapsulate) 密文
        KeyGenerator keyDecapsulator = KeyGenerator.getInstance("ML-KEM", "BCPQC");
        keyDecapsulator.init(new KEMExtractSpec(bobKeyPair.getPrivate(), ciphertext, "AES"));
        SecretKey bobSharedKey = (SecretKey) keyDecapsulator.generateKey();

        // Step 1.4: 校驗兩端產出的對稱金鑰是否完全一致
        boolean keyMatched = MessageDigest.isEqual(aliceSharedKey.getEncoded(), bobSharedKey.getEncoded());
        System.out.println("ML-KEM-768 金鑰協商成功,兩端 AES 金鑰一致: " + keyMatched);


        // =========================================================================
        // 實戰 2: ML-DSA-65 (FIPS 204) - 後量子數位簽章
        // =========================================================================
        System.out.println("\n--- [ 2. ML-DSA-65 數位簽章與驗證測試 ] ---");

        // Step 2.1: 產生 ML-DSA-65 簽章金鑰對
        KeyPairGenerator dsaKeyPairGen = KeyPairGenerator.getInstance("ML-DSA", "BCPQC");
        dsaKeyPairGen.initialize(MLDSAParameterSpec.ml_dsa_65, new SecureRandom());
        KeyPair signerKeyPair = dsaKeyPairGen.generateKeyPair();

        System.out.println("簽署者公鑰長度 (ML-DSA-65): " + signerKeyPair.getPublic().getEncoded().length + " bytes");

        // Step 2.2: 執行簽章
        byte[] dataToSign = "Post-Quantum Security Message 2026".getBytes(StandardCharsets.UTF_8);
        Signature signer = Signature.getInstance("ML-DSA", "BCPQC");
        signer.initSign(signerKeyPair.getPrivate());
        signer.update(dataToSign);
        byte[] signature = signer.sign();

        System.out.println("ML-DSA-65 簽章結果長度   : " + signature.length + " bytes");

        // Step 2.3: 執行簽章驗證
        Signature verifier = Signature.getInstance("ML-DSA", "BCPQC");
        verifier.initVerify(signerKeyPair.getPublic());
        verifier.update(dataToSign);
        boolean isSignatureValid = verifier.verify(signature);

        System.out.println("ML-DSA-65 數位簽章驗證結果: " + isSignatureValid);
    }
}

上一篇
Day36 - 硬體金鑰保護:HSM、智慧卡與 USB Token
系列文
我是Java工程師,關於密碼學我想懂的不多 共 38 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言