量子计算对密码学的挑战

2019 年,Google 宣布「量子霸权」:其量子计算机 Sycamore 用 200 秒完成了传统超级计算机需要 1 万年才能完成的任务。

虽然「量子霸权」本身没有直接威胁到密码学,但这个里程碑预示着一个不可忽视的未来:量子计算将使今天广泛使用的 RSA、ECC 等非对称加密算法变得不再安全

这不仅是技术问题,更是关乎国家安全和商业机密的大事。

一、量子计算的发展现状

量子计算发展时间线

量子计算里程碑:

1994 - Shor 算法:量子计算机可以高效分解大整数
1996 - Grover 算法:量子搜索将搜索复杂度降低平方根
2001 - IBM 演示 7 量子比特量子计算机
2011 - D-Wave 推出商用量子计算机
2017 - IBM 推出 50 量子比特量子计算机
2019 - Google 声称量子霸权
2023 - IBM 发布 1121 量子比特系统
2024 - 错误纠正量子计算取得突破

预测:
- 2030 年代:可能破解 RSA-2048
- 2040 年代:大规模实用量子计算机

量子比特与经典比特的差异

经典比特 vs 量子比特:

经典比特:
┌─────────────────┐
│     状态:0 或 1 │
└─────────────────┘
     每次测量只能得到 0 或 1

量子比特:
┌─────────────────────────┐
│                         │
│   |ψ⟩ = α|0⟩ + β|1⟩  │
│                         │
│   α, β 是复数振幅       │
│   |α|² + |β|² = 1     │
│                         │
└─────────────────────────┘
     叠加态:可以同时是 0 和 1

量子计算机的威胁规模

威胁时间表预测:

2024 - 量子计算机状态:
  - 约 1000 物理量子比特
  - 错误率高,需要数千个物理量子比特实现 1 个逻辑量子比特

2028 - 预计:
  - 约 10,000 物理量子比特
  - 错误纠正改进

2030 - 预计(悲观):
  - 约 1 百万物理量子比特
  - 错误纠正基本解决
  - 可破解 RSA-2048

2030 - 预计(乐观):
  - 数百万物理量子比特
  - 可破解 RSA-2048

二、Shor 算法对非对称加密的威胁

Shor 算法原理

Shor 算法是由 Peter Shor 于 1994 年提出的量子算法,可以在多项式时间内分解大整数:

经典分解:
- 最优算法:General Number Field Sieve
- 复杂度:O(exp((log N)^(1/3)))
- RSA-2048 需要约 10^26 次操作

Shor 算法:
- 复杂度:O((log N)³)
- 量子比特需求:约 4000 个逻辑量子比特
- 相当于经典计算机约 10^12 年的计算量

为什么 RSA 不再安全

RSA 安全性基于:
n = p × q(两个大质数的乘积)

已知 n,求 p 和 q:
- 经典计算机:亚指数时间
- 量子计算机(Shor):多项式时间

Shor 算法步骤:
1. 选择随机数 x
2. 计算 gcd(x^r - 1, n)
3. 使用量子傅里叶变换 QFT 找到周期 r
4. 如果 r 是偶数,用 r 计算 p 和 q

对 ECC 的威胁

椭圆曲线离散对数问题:

已知 G(基点)和 Q = k × G,求 k

经典攻击:O(sqrt(n))
量子攻击(Shor 变体):O((log n)³)

ECC-256 相当于 RSA-2048 的安全性:
- 经典:需要约 2^128 次操作
- 量子:需要约 2^64 次操作

结论:ECC 同样被 Shor 算法威胁

三、Grover 算法对对称加密的威胁

Grover 算法原理

Grover 算法是一种量子搜索算法,可以将无序数据库的搜索复杂度从 O(N) 降低到 O(sqrt(N)):

经典搜索:
- 搜索 2^256 个可能的密钥
- 需要平均 2^255 次尝试
- 相当于约 10^76 次操作

Grover 量子搜索:
- 需要约 2^128 次「量子查询」
- 约 10^38 次操作
- 相当于将密钥长度减半

对称加密的影响

算法当前密钥长度经典安全强度量子安全强度应对措施
AES-128128 位128 位64 位升级到 AES-256
AES-256256 位256 位128 位无需改变
SHA-256256 位256 位128 位升级到 SHA-512
SHA-512512 位512 位256 位无需改变
量子搜索对哈希的影响:

Grover 算法使哈希碰撞搜索从 O(2^n) 降低到 O(2^(n/2))

原本 SHA-256 的 256 位安全强度:
- 经典:2^256 次尝试
- 量子:2^128 次尝试

但 2^128 仍然是天文数字,实际上安全

四、后量子密码学概述

什么是后量子密码学

后量子密码学(PQC)是指能够抵抗量子计算机攻击的密码学算法:

后量子密码学候选:

1. 基于格的密码学(Lattice-based)
   - 安全性基于格问题的困难性
   - 最被看好的方案
   - 包括:CRYSTALS-Kyber, CRYSTALS-Dilithium

2. 基于哈希的签名(Hash-based)
   - 安全性完全基于哈希函数
   - 成熟可靠
   - 包括:SPHINCS+

3. 基于编码的密码学(Code-based)
   - 安全性基于纠错码问题
   - 历史悠久
   - 包括:Classic McEliece

4. 基于多变量的密码学(Multivariate)
   - 基于多变量多项式问题
   - 适合签名
   - 包括:Rainbow

5. 同态加密(仍在研究中)
   - 可在加密数据上计算
   - 量子计算加速不明显

为什么格密码最被看好

格密码的优势:

1. 安全性基础坚实
   - 格问题被认为是量子计算机也难以解决
   - 长期密码学安全研究的基础

2. 效率高
   - 密钥和签名相对较小
   - 计算速度快

3. 多功能性
   - 可以实现加密、签名、密钥交换
   - 适合构建完整的密码系统

4.  NIST 标准化选择:
   - Kyber(密钥封装)
   - Dilithium(签名)
   - 都是基于格的算法

五、NIST 后量子密码标准化

NIST 标准化进程

NIST PQC 标准化时间线:

2016 - NIST 启动后量子密码标准化进程
     - 收到 82 个算法提案
     - 筛选到 69 个进入评估

2017 - 第一轮评估
     - 69 个算法参与

2019 - 第二轮评估
     - 26 个算法进入

2020 - 第三轮评估
     - 7 个算法进入决赛圈

2022 - 第一批标准发布
     - CRYSTALS-Kyber(密钥封装)
     - CRYSTALS-Dilithium(签名)
     - SPHINCS+(签名)
     - Classic McEliece(密钥封装)

2024 - 第二批标准
     - FALCON(签名)
     - BIKE, HQC(密钥封装)

已标准化的算法

PqcryptographyExamples.java
/**
 * 后量子密码算法示例(使用 PQCrypto 库)
 */

// CRYSTALS-Kyber 密钥封装
public class KyberExample {
    
    /**
     * 生成 Kyber 密钥对
     */
    public static KeyPair generateKyberKeyPair() {
        // Kyber 提供三种安全级别:
        // - Kyber512(相当于 AES-128)
        // - Kyber768(相当于 AES-192)
        // - Kyber1024(相当于 AES-256)
        
        // 使用 Kyber768
        byte[] publicKey = new byte[1184];
        byte[] privateKey = new byte[2400];
        
        KyberKeyGen.generate(publicKey, privateKey);
        
        return new KeyPair(publicKey, privateKey);
    }
    
    /**
     * Kyber 密钥封装
     */
    public static byte[] encapsulate(byte[] publicKey) {
        byte[] sharedSecret = new byte[32];
        byte[] ciphertext = new byte[1088];
        
        KyberEncaps.encapsulate(ciphertext, sharedSecret, publicKey);
        
        // ciphertext 用于传输
        // sharedSecret 作为共享密钥
        return ciphertext;
    }
    
    /**
     * Kyber 密钥解封装
     */
    public static byte[] decapsulate(byte[] ciphertext, byte[] privateKey) {
        byte[] sharedSecret = new byte[32];
        
        KyberEncaps.decapsulate(sharedSecret, ciphertext, privateKey);
        
        return sharedSecret;
    }
}

// CRYSTALS-Dilithium 签名
public class DilithiumExample {
    
    /**
     * 生成 Dilithium 签名密钥对
     */
    public static KeyPair generateDilithiumKeyPair() {
        // Dilithium 提供三种安全级别:
        // - Dilithium2
        // - Dilithium3
        // - Dilithium5
        
        byte[] publicKey = new byte[1312];
        byte[] privateKey = new byte[4000];
        
        DilithiumKeyGen.generate(publicKey, privateKey);
        
        return new KeyPair(publicKey, privateKey);
    }
    
    /**
     * Dilithium 签名
     */
    public static byte[] sign(byte[] message, byte[] privateKey) {
        byte[] signature = new byte[2420];
        
        DilithiumSign.sign(signature, message, privateKey);
        
        return signature;
    }
    
    /**
     * Dilithium 验签
     */
    public static boolean verify(byte[] message, byte[] signature, byte[] publicKey) {
        return DilithiumSign.verify(signature, message, publicKey);
    }
}

算法对比

算法类型公钥大小密文/签名大小安全性
Kyber768KEM1184 字节1088 字节192 位
Dilithium3签名1952 字节3293 字节192 位
SPHINCS+-128s签名32 字节7856 字节128 位
Classic McElieceKEM1,048,575 字节1568 字节256 位

六、CRYSTALS-Dilithium 详解

Dilithium 算法原理

Dilithium 是基于格中 Module-LWE 问题的数字签名算法:

Module-LWE 问题:

给定:
- 矩阵 A(公开)
- 向量 b = As + e(模 q)
  其中 s 是随机小向量(私钥)
  其中 e 是随机小错误向量

求:
- s(短向量)

这被认为是即使量子计算机也难以解决的问题

Dilithium 结构

DilithiumStructure.java
/**
 * Dilithium 签名流程
 */
public class DilithiumSigning {
    
    /**
     * Dilithium 签名(简化版)
     */
    public static byte[] sign(byte[] message, byte[] privateKey) {
        
        // 1. 从私钥提取 A, s1, s2, t
        // A: 公共矩阵 (k × l)
        // s1, s2: 私钥中的短向量
        // t: 公钥向量
        
        // 2. 采样随机向量 y
        // y1: l 维随机向量
        // y2: k 维随机向量
        
        // 3. 计算 w = Ay(仅高比特位)
        // w = Ay mod q
        
        // 4. 计算哈希 c = H(seed || w_h)
        // w_h: w 的高比特位
        
        // 5. 计算 z = y + c * s1
        // s1: 私钥中的短向量
        
        // 6. 检查 ||z|| 是否有界
        // 如果无界,返回步骤 2
        
        // 7. 计算 c * t - y2 并检查低比特位
        // r1: 低比特位
        // r2: 高比特位 - c * t2
        
        // 8. 输出签名 (z, c, r1)
        
        return null; // 简化示例
    }
    
    /**
     * Dilithium 验证
     */
    public static boolean verify(byte[] message, byte[] signature, byte[] publicKey) {
        
        // 1. 从签名提取 (z, c, r1)
        
        // 2. 检查 ||z|| 有界
        
        // 3. 计算 w' = Ay - c * t + c * r2
        // 其中 r2 从 r1 计算
        
        // 4. 计算 c' = H(seed || w'_h)
        
        // 5. 比较 c == c'
        
        return false;
    }
}

七、迁移到后量子密码的挑战

技术挑战

迁移挑战:

1. 密钥和签名大小
   - RSA-2048 签名:256 字节
   - Dilithium3 签名:3293 字节(12x)
   - Kyber768 公钥:1184 字节
   
   影响:网络带宽、存储、证书大小

2. 计算性能
   - PQC 算法通常比传统算法慢
   - 需要硬件加速支持

3. 互操作性
   - 新旧系统需要共存
   - 需要混合模式

4. 密钥管理
   - 新的密钥类型
   - 新的存储要求

迁移策略

HybridMigrationStrategy.java
@Service
@Slf4j
public class HybridCryptographyMigration {
    
    /**
     * 混合加密模式(推荐迁移策略)
     */
    public static class HybridEncryption {
        
        /**
         * 混合加密:同时使用传统算法和 PQC 算法
         */
        public static EncryptedData hybridEncrypt(
                byte[] plaintext,
                PublicKey traditionalKey,
                PublicKey pqKey) throws Exception {
            
            // 1. 生成随机对称密钥 DEK
            byte[] dek = generateRandomKey(32);
            
            // 2. 用对称密钥加密数据
            byte[] ciphertext = encryptWithAes(plaintext, dek);
            
            // 3. 用传统非对称密钥加密 DEK
            byte[] encryptedDekTraditional = encryptWithTraditional(dek, traditionalKey);
            
            // 4. 用 PQC 密钥加密 DEK
            byte[] encryptedDekPqc = encapsulateWithKyber(dek, pqKey);
            
            // 5. 返回组合结果
            return new EncryptedData(
                ciphertext,
                encryptedDekTraditional,
                encryptedDekPqc
            );
        }
        
        /**
         * 混合解密(任一算法成功即可)
         */
        public static byte[] hybridDecrypt(
                EncryptedData encryptedData,
                PrivateKey traditionalPrivateKey,
                byte[] kyberPrivateKey) throws Exception {
            
            byte[] dek = null;
            
            // 1. 尝试用传统算法解密
            try {
                dek = decryptWithTraditional(
                    encryptedData.getEncryptedDekTraditional(),
                    traditionalPrivateKey
                );
            } catch (Exception e) {
                log.debug("传统算法解密失败");
            }
            
            // 2. 如果失败,尝试 PQC 解密
            if (dek == null) {
                dek = decapsulateWithKyber(
                    encryptedData.getEncryptedDekPqc(),
                    kyberPrivateKey
                );
            }
            
            // 3. 用 DEK 解密数据
            return decryptWithAes(encryptedData.getCiphertext(), dek);
        }
    }
    
    /**
     * 混合签名模式
     */
    public static class HybridSignature {
        
        public static byte[] hybridSign(
                byte[] message,
                PrivateKey traditionalKey,
                byte[] dilithiumPrivateKey) throws Exception {
            
            // 1. 用传统算法签名
            byte[] traditionalSig = signWithTraditional(message, traditionalKey);
            
            // 2. 用 Dilithium 签名
            byte[] pqSig = signWithDilithium(message, dilithiumPrivateKey);
            
            // 3. 组合签名
            return combineSignatures(traditionalSig, pqSig);
        }
        
        public static boolean hybridVerify(
                byte[] message,
                byte[] combinedSignature,
                PublicKey traditionalKey,
                byte[] dilithiumPublicKey) throws Exception {
            
            // 分离签名
            SignaturePair sigs = splitSignatures(combinedSignature);
            
            // 验证两者
            boolean traditionalValid = verifyWithTraditional(
                message, sigs.traditional, traditionalKey);
            boolean pqValid = verifyWithDilithium(
                message, sigs.pqc, dilithiumPublicKey);
            
            // 两者都有效才算通过
            return traditionalValid && pqValid;
        }
    }
}

八、企业应对策略

时间规划框架

┌─────────────────────────────────────────────────────────────────┐
│                    企业 PQC 迁移时间线                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  立即行动(现在):                                             │
│  - 盘点密码学资产                                             │
│  - 评估量子风险                                               │
│  - 制定迁移计划                                               │
│                                                                 │
│  2024-2025:                                                  │
│  - 开始试点 PQC 算法                                          │
│  - 升级到 AES-256(量子安全)                                 │
│  - 部署混合模式                                               │
│                                                                 │
│  2026-2028:                                                  │
│  - 全面部署 PQC                                               │
│  - 完成历史数据重新加密                                        │
│  - 关闭传统算法                                              │
│                                                                 │
│  关键原则:                                                    │
│  - 「先收集,后解密」数据需要优先迁移                         │
│  - 生命周期长的数据优先                                       │
│  - 配合密钥轮转进行                                           │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

分阶段迁移计划

PqcMigrationPlan.java
@Service
@Slf4j
public class PqcMigrationPlan {
    
    /**
     * 密码学资产盘点
     */
    public Map<String, CryptoAsset> inventory() {
        
        Map<String, CryptoAsset> assets = new HashMap<>();
        
        // 1. TLS 证书和密钥
        for (Certificate cert : certificateRepository.findAll()) {
            CryptoAsset asset = CryptoAsset.builder()
                .id(cert.getId())
                .type(AssetType.CERTIFICATE)
                .algorithm(cert.getAlgorithm())
                .keyLength(cert.getKeyLength())
                .dataClassification(cert.getDataClassification())
                .lifetimeYears(cert.getRemainingValidityYears())
                .build();
            assets.put(cert.getId(), asset);
        }
        
        // 2. 加密密钥
        for (EncryptionKey key : keyRepository.findAll()) {
            CryptoAsset asset = CryptoAsset.builder()
                .id(key.getId())
                .type(AssetType.ENCRYPTION_KEY)
                .algorithm(key.getAlgorithm())
                .keyLength(key.getKeyLength())
                .dataClassification(key.getDataClassification())
                .lifetimeYears(key.getRemainingLifetimeYears())
                .build();
            assets.put(key.getId(), asset);
        }
        
        // 3. 签名密钥
        for (SigningKey key : signingKeyRepository.findAll()) {
            CryptoAsset asset = CryptoAsset.builder()
                .id(key.getId())
                .type(AssetType.SIGNING_KEY)
                .algorithm(key.getAlgorithm())
                .keyLength(key.getKeyLength())
                .purpose(key.getPurpose())
                .build();
            assets.put(key.getId(), asset);
        }
        
        return assets;
    }
    
    /**
     * 风险评估
     */
    public RiskAssessment assessQuantumRisk(Map<String, CryptoAsset> assets) {
        
        RiskAssessment assessment = new RiskAssessment();
        
        for (CryptoAsset asset : assets.values()) {
            
            QuantumRisk risk = QuantumRisk.LOW;
            
            // 高敏感数据 + 长生命周期 = 高风险
            if (asset.getDataClassification() == DataClassification.RESTRICTED
                && asset.getLifetimeYears() > 5) {
                risk = QuantumRisk.HIGH;
            }
            // 高敏感数据 = 中风险
            else if (asset.getDataClassification() == DataClassification.RESTRICTED) {
                risk = QuantumRisk.MEDIUM;
            }
            // 非对称加密算法 = 高风险
            else if (asset.getType() == AssetType.CERTIFICATE 
                && isAsymmetric(asset.getAlgorithm())) {
                risk = QuantumRisk.HIGH;
            }
            
            assessment.addAssetRisk(asset.getId(), risk);
        }
        
        return assessment;
    }
    
    /**
     * 迁移计划
     */
    public MigrationPlan createMigrationPlan(RiskAssessment assessment) {
        
        MigrationPlan plan = new MigrationPlan();
        
        // 按优先级分组
        List<String> urgent = assessment.getHighRiskAssets();
        List<String> medium = assessment.getMediumRiskAssets();
        List<String> low = assessment.getLowRiskAssets();
        
        // 阶段 1:紧急迁移(高风险)
        plan.addPhase(MigrationPhase.builder()
            .name("紧急迁移")
            .assets(urgent)
            .targetAlgorithm("Hybrid (EC + Kyber)")
            .deadline(Instant.now().plus(Duration.ofDays(180)))
            .build());
        
        // 阶段 2:标准迁移(中风险)
        plan.addPhase(MigrationPhase.builder()
            .name("标准迁移")
            .assets(medium)
            .targetAlgorithm("Kyber/Dilithium")
            .deadline(Instant.now().plus(Duration.ofDays(365)))
            .build());
        
        // 阶段 3:收尾(低风险)
        plan.addPhase(MigrationPhase.builder()
            .name("收尾")
            .assets(low)
            .targetAlgorithm("Post-Quantum Only")
            .deadline(Instant.now().plus(Duration.ofDays(730)))
            .build());
        
        return plan;
    }
}

思考题

问题 1:假设你的组织有大量使用 RSA-2048 加密的敏感数据,加密数据的有效期是 20 年。根据量子计算的发展预测,你应该在什么时候开始迁移到后量子密码?迁移的优先级如何确定?

参考答案

迁移时机分析

「现在收集,以后解密」威胁:

攻击者可能:
1. 今天收集所有加密通信
2. 等待量子计算机成熟
3. 在未来某个时间解密

「收获现在,解密以后」(Harvest Now, Decrypt Later) 攻击

时间线:
- 今天:攻击者收集加密数据
- 2030-2040 年:量子计算机可能足够强大
- 2044+ 年:数据仍需保密

结论:数据保密期超过 2030 年的,现在就需要考虑迁移

迁移时机决策树

数据保密期分析:

数据保密期 = 当前年份 + 需要保密的年数

判断标准:
├─ 数据保密期 > 2030 年?
│   ├─ 是 → 立即开始迁移评估
│   └─ 否 → 2030 年前完成迁移

├─ 数据属于「关键基础设施」?
│   ├─ 是 → 立即迁移
│   └─ 否 → 按计划迁移

└─ 数据涉及国家安全/核心机密?
    ├─ 是 → 立即迁移
    └─ 否 → 按优先级迁移

优先级确定方法

MigrationPriority.java
/**
 * 迁移优先级计算
 */
public class MigrationPriority {
    
    /**
     * 优先级分数(越高越优先)
     */
    public int calculatePriority(CryptoAsset asset) {
        int score = 0;
        
        // 1. 保密期限(最重要的因素)
        int remainingYears = asset.getRemainingConfidentialityYears();
        if (remainingYears >= 20) score += 50;
        else if (remainingYears >= 10) score += 40;
        else if (remainingYears >= 5) score += 30;
        else if (remainingYears >= 2) score += 20;
        else score += 10;
        
        // 2. 数据敏感度
        switch (asset.getDataClassification()) {
            case RESTRICTED: score += 30; break;
            case CONFIDENTIAL: score += 20; break;
            case INTERNAL: score += 10; break;
            case PUBLIC: score += 0; break;
        }
        
        // 3. 算法脆弱性
        if (asset.getAlgorithm().isAsymmetric()) {
            score += 20;  // 非对称加密最脆弱
        }
        
        // 4. 业务影响
        if (asset.isBusinessCritical()) score += 15;
        if (asset.hasExternalExposure()) score += 10;
        
        // 5. 迁移难度
        int complexityPenalty = assessMigrationComplexity(asset);
        score -= complexityPenalty;  // 复杂系统降低优先级
        
        return score;
    }
    
    /**
     * 优先级分组
     */
    public PriorityGroup classifyAsset(int priorityScore) {
        if (priorityScore >= 80) return PriorityGroup.CRITICAL;
        if (priorityScore >= 60) return PriorityGroup.HIGH;
        if (priorityScore >= 40) return PriorityGroup.MEDIUM;
        return PriorityGroup.LOW;
    }
}

迁移时间表建议

┌─────────────────────────────────────────────────────────────────┐
│                    建议迁移时间表                                    │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  高优先级(立即开始):                                         │
│  - 保密期超过 15 年的数据                                      │
│  - 政府和军事数据                                              │
│  - 医疗健康数据                                               │
│  - 金融核心数据                                               │
│  - 知识产权和商业机密                                          │
│  时间:现在开始,2 年内完成                                    │
│                                                                 │
│  中优先级(2024-2025):                                       │
│  - 保密期 5-15 年的数据                                       │
│  - 员工个人信息                                                │
│  - 合同和法律文档                                             │
│  时间:2024-2025 年完成                                       │
│                                                                 │
│  低优先级(2025-2027):                                       │
│  - 保密期 2-5 年的数据                                        │
│  - 一般业务数据                                                │
│  时间:2025-2027 年完成                                        │
│                                                                 │
│  立即行动(无论优先级):                                       │
│  - 升级对称加密到 AES-256                                      │
│  - 升级哈希到 SHA-384 或 SHA-512                               │
│  - 制定完整的迁移计划                                           │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

问题 2:设计一个混合密码系统,同时使用传统算法和后量子算法,确保:

  1. 即便量子计算机攻破了其中一种算法,数据仍然安全
  2. 与现有系统保持向后兼容
  3. 可以渐进式迁移到纯后量子系统
参考答案

混合密码系统设计

设计原则:

1. 双重保护
   - 数据必须同时被传统算法和 PQC 算法保护
   - 攻击者需要同时破解两种算法

2. 向后兼容
   - 支持纯传统模式
   - 支持混合模式
   - 支持纯 PQC 模式

3. 平滑迁移
   - 新数据使用最强保护
   - 旧数据逐步迁移
   - 系统自动适应对方能力

系统架构

HybridCryptoSystem.java
@Service
@Slf4j
public class HybridCryptoSystem {
    
    /**
     * 运行模式
     */
    public enum OperationMode {
        /**
         * 仅传统算法(向后兼容)
         */
        TRADITIONAL_ONLY,
        
        /**
         * 混合模式(推荐初始阶段)
         */
        HYBRID,
        
        /**
         * 仅 PQC(未来目标)
         */
        POST_QUANTUM_ONLY,
        
        /**
         * 自动模式(根据对方能力选择)
         */
        AUTO
    }
    
    /**
     * 混合加密结果
     */
    public static class HybridEncryptedData {
        private final byte[] ciphertext;          // 数据密文
        private final EncryptedKey encryptedTraditionalKey;  // 传统算法加密的密钥
        private final EncryptedKey encryptedPqcKey;  // PQC 算法加密的密钥
        private final byte[] nonce;                 // 随机数
        
        // 元数据
        private final OperationMode mode;
        private final String algorithmSuite;
    }
    
    /**
     * 混合加密
     */
    public HybridEncryptedData encryptHybrid(
            byte[] plaintext,
            EncryptionKey traditionalKey,
            KyberPublicKey pqKey,
            OperationMode mode) throws Exception {
        
        // 1. 生成数据加密密钥
        byte[] dek = generateRandomKey(32);
        
        // 2. 用 DEK 加密数据(使用 AES-256-GCM)
        byte[] nonce = generateNonce(12);
        byte[] ciphertext = encryptAesGcm(plaintext, dek, nonce);
        
        EncryptedKey encryptedTraditionalKey = null;
        EncryptedKey encryptedPqcKey = null;
        
        switch (mode) {
            case HYBRID:
                // 3a. 用传统算法加密 DEK
                encryptedTraditionalKey = encryptWithTraditional(dek, traditionalKey);
                
                // 3b. 用 PQC 算法加密 DEK
                encryptedPqcKey = encapsulateWithKyber(dek, pqKey);
                break;
                
            case TRADITIONAL_ONLY:
                // 仅传统加密
                encryptedTraditionalKey = encryptWithTraditional(dek, traditionalKey);
                break;
                
            case POST_QUANTUM_ONLY:
                // 仅 PQC 加密
                encryptedPqcKey = encapsulateWithKyber(dek, pqKey);
                break;
                
            case AUTO:
                // 根据密钥可用性自动选择
                if (pqKey != null && traditionalKey != null) {
                    return encryptHybrid(plaintext, traditionalKey, pqKey, HYBRID);
                } else if (pqKey != null) {
                    return encryptHybrid(plaintext, traditionalKey, pqKey, POST_QUANTUM_ONLY);
                } else {
                    return encryptHybrid(plaintext, traditionalKey, pqKey, TRADITIONAL_ONLY);
                }
        }
        
        return new HybridEncryptedData(
            ciphertext,
            encryptedTraditionalKey,
            encryptedPqcKey,
            nonce,
            mode,
            determineAlgorithmSuite(mode)
        );
    }
    
    /**
     * 混合解密
     */
    public byte[] decryptHybrid(
            HybridEncryptedData encryptedData,
            EncryptionKey traditionalKey,
            KyberPrivateKey pqKey) throws Exception {
        
        byte[] dek = null;
        
        switch (encryptedData.getMode()) {
            case HYBRID:
                // 尝试两种解密方式
                try {
                    dek = decapsulateWithKyber(
                        encryptedData.getEncryptedPqcKey(), pqKey);
                } catch (Exception e) {
                    log.debug("PQC 解密失败,尝试传统算法");
                }
                
                if (dek == null) {
                    dek = decryptWithTraditional(
                        encryptedData.getEncryptedTraditionalKey(), 
                        traditionalKey);
                }
                break;
                
            case TRADITIONAL_ONLY:
                dek = decryptWithTraditional(
                    encryptedData.getEncryptedTraditionalKey(), 
                    traditionalKey);
                break;
                
            case POST_QUANTUM_ONLY:
                dek = decapsulateWithKyber(
                    encryptedData.getEncryptedPqcKey(), pqKey);
                break;
        }
        
        // 用 DEK 解密数据
        return decryptAesGcm(encryptedData.getCiphertext(), dek, encryptedData.getNonce());
    }
}

迁移支持

MigrationSupport.java
@Service
@Slf4j
public class HybridCryptoMigration {
    
    /**
     * 检测对方的加密能力
     */
    public Capabilities detectPeerCapabilities(Peer peer) {
        Capabilities caps = new Capabilities();
        
        // 1. 尝试协商 PQC
        KyberPublicKey pqKey = peer.getKyberPublicKey();
        caps.setSupportsPqc(pqKey != null);
        
        // 2. 检测传统能力
        caps.setSupportsTraditional(peer.hasTraditionalKey());
        
        // 3. 返回支持的最优模式
        if (caps.supportsPqc() && caps.supportsTraditional()) {
            caps.setPreferredMode(OperationMode.HYBRID);
        } else if (caps.supportsPqc()) {
            caps.setPreferredMode(OperationMode.POST_QUANTUM_ONLY);
        } else {
            caps.setPreferredMode(OperationMode.TRADITIONAL_ONLY);
        }
        
        return caps;
    }
    
    /**
     * 渐进式迁移
     */
    public void migrateExistingData(DataMigrationPlan plan) {
        
        // 1. 识别需要迁移的数据
        List<EncryptedData> toMigrate = findDataNeedingMigration();
        
        // 2. 按优先级排序
        toMigrate.sort(Comparator.comparing(
            EncryptedData::getDataClassification).reversed());
        
        // 3. 分批重新加密
        for (EncryptedData data : toMigrate) {
            try {
                // 读取旧数据
                byte[] plaintext = readData(data);
                
                // 用新模式重新加密
                HybridEncryptedData newEncrypted = encryptHybrid(
                    plaintext,
                    plan.getNewTraditionalKey(),
                    plan.getNewPqKey(),
                    OperationMode.HYBRID
                );
                
                // 保存新数据
                saveData(data.getId(), newEncrypted);
                
                // 删除旧数据(可选)
                if (plan.isDeleteOldAfterMigration()) {
                    deleteOldData(data);
                }
                
                log.info("数据迁移完成: {}", data.getId());
                
            } catch (Exception e) {
                log.error("数据迁移失败: {}", data.getId(), e);
                recordMigrationFailure(data.getId(), e);
            }
        }
    }
}

安全属性分析

混合加密的安全证明:

假设:
- 传统算法被量子计算机攻破
- PQC 算法保持安全

结论:
- 攻击者需要破解 PQC 算法才能获取密钥
- 因为 PQC 仍然安全,数据保持机密

反之亦然:
- 如果 PQC 被攻破,传统算法仍然安全
- (假设传统算法在经典计算机上安全)

混合方案的安全性 ≥ max(传统安全性, PQC安全性)