Skip to main content

encryption/pqc/
ml_kem.rs

1// Copyright (c) 2026 erik <erik@erik.xyz> — https://erik.xyz
2
3//! FIPS 203 ML-KEM 后量子密钥封装(Module-Lattice-Based KEM,前身 CRYSTALS-Kyber)。
4//!
5//! 三个参数集,公钥 / 私钥 / 密文 / 共享密钥均为十六进制(1 字节 = 2 位):
6//!
7//! | 标识            | 公钥 ek          | 私钥 dk          | 密文 ct          | 共享密钥     |
8//! |-----------------|------------------|------------------|------------------|--------------|
9//! | `ml-kem-512`    | 1600 位(800 B) | 3264 位(1632 B)| 1536 位(768 B) | 64 位(32 B)|
10//! | `ml-kem-768`    | 2368 位(1184 B)| 4800 位(2400 B)| 2176 位(1088 B)| 64 位(32 B)|
11//! | `ml-kem-1024`   | 3136 位(1568 B)| 6336 位(3168 B)| 3136 位(1568 B)| 64 位(32 B)|
12//!
13//! 错误映射:十六进制非法 → [`Error::InvalidHex`];公钥 / 私钥字节数不符、私钥的
14//! §7.3 hash check 不符(H(内嵌 ek) ≠ 存储的 h)、或公钥(含私钥内嵌的公钥)未通过
15//! §7.2 风格 modulus check(t̂ 存在 ≥ q 的系数)→ [`Error::InvalidKey`];密文字节数
16//! 不符 → [`Error::InvalidKeyLength`]。
17//!
18//! **隐式拒绝**:密文被篡改(或私钥与公钥不配对)时,解封装**不报错**,而是返回
19//! 一个与封装端不同的伪随机共享密钥(FIPS 203 §7.3)。这是标准行为,调用方应以
20//! 「共享密钥不匹配」而非「出错」来理解,契约注释里亦有强调。
21//!
22//! 对应 PHP 版 `Pqc/` 的密钥封装服务与 `Contract/KeyEncapsulationInterface`。
23
24use ml_kem::array::typenum::Unsigned;
25use ml_kem::kem::{Decapsulate, Encapsulate};
26use ml_kem::{Ciphertext, Encoded, EncodedSizeUser, KemCore, MlKem512, MlKem768, MlKem1024};
27use rand_core::OsRng;
28
29use crate::contract::{Identified, KeyEncapsulation};
30use crate::error::{Error, Result};
31use crate::internal::{hex_decode, hex_encode};
32
33/// ML-KEM-512(FIPS 203 安全类别 1,≈AES-128 强度)。
34#[derive(Debug, Default, Clone, Copy)]
35pub struct MlKem512Kem;
36
37impl MlKem512Kem {
38    pub const IDENTIFIER: &'static str = "ml-kem-512";
39
40    pub fn new() -> Self {
41        Self
42    }
43}
44
45impl Identified for MlKem512Kem {
46    fn identifier(&self) -> &str {
47        Self::IDENTIFIER
48    }
49}
50
51impl KeyEncapsulation for MlKem512Kem {
52    fn generate(&self) -> Result<(String, String)> {
53        generate_hex::<MlKem512>()
54    }
55
56    fn encapsulate(&self, public_key_hex: &str) -> Result<(String, String)> {
57        encapsulate_hex::<MlKem512>(public_key_hex, "ML-KEM-512")
58    }
59
60    fn decapsulate(&self, ciphertext_hex: &str, private_key_hex: &str) -> Result<String> {
61        decapsulate_hex::<MlKem512>(
62            ciphertext_hex,
63            private_key_hex,
64            "ML-KEM-512",
65            "ML-KEM-512 ciphertext",
66        )
67    }
68}
69
70/// ML-KEM-768(FIPS 203 安全类别 3,≈AES-192 强度)。
71#[derive(Debug, Default, Clone, Copy)]
72pub struct MlKem768Kem;
73
74impl MlKem768Kem {
75    pub const IDENTIFIER: &'static str = "ml-kem-768";
76
77    pub fn new() -> Self {
78        Self
79    }
80}
81
82impl Identified for MlKem768Kem {
83    fn identifier(&self) -> &str {
84        Self::IDENTIFIER
85    }
86}
87
88impl KeyEncapsulation for MlKem768Kem {
89    fn generate(&self) -> Result<(String, String)> {
90        generate_hex::<MlKem768>()
91    }
92
93    fn encapsulate(&self, public_key_hex: &str) -> Result<(String, String)> {
94        encapsulate_hex::<MlKem768>(public_key_hex, "ML-KEM-768")
95    }
96
97    fn decapsulate(&self, ciphertext_hex: &str, private_key_hex: &str) -> Result<String> {
98        decapsulate_hex::<MlKem768>(
99            ciphertext_hex,
100            private_key_hex,
101            "ML-KEM-768",
102            "ML-KEM-768 ciphertext",
103        )
104    }
105}
106
107/// ML-KEM-1024(FIPS 203 安全类别 5,≈AES-256 强度)。
108#[derive(Debug, Default, Clone, Copy)]
109pub struct MlKem1024Kem;
110
111impl MlKem1024Kem {
112    pub const IDENTIFIER: &'static str = "ml-kem-1024";
113
114    pub fn new() -> Self {
115        Self
116    }
117}
118
119impl Identified for MlKem1024Kem {
120    fn identifier(&self) -> &str {
121        Self::IDENTIFIER
122    }
123}
124
125impl KeyEncapsulation for MlKem1024Kem {
126    fn generate(&self) -> Result<(String, String)> {
127        generate_hex::<MlKem1024>()
128    }
129
130    fn encapsulate(&self, public_key_hex: &str) -> Result<(String, String)> {
131        encapsulate_hex::<MlKem1024>(public_key_hex, "ML-KEM-1024")
132    }
133
134    fn decapsulate(&self, ciphertext_hex: &str, private_key_hex: &str) -> Result<String> {
135        decapsulate_hex::<MlKem1024>(
136            ciphertext_hex,
137            private_key_hex,
138            "ML-KEM-1024",
139            "ML-KEM-1024 ciphertext",
140        )
141    }
142}
143
144/// 生成密钥对,返回 `(公钥 hex, 私钥 hex)`。随机源为系统 CSPRNG([`OsRng`])。
145fn generate_hex<K: KemCore>() -> Result<(String, String)> {
146    let (decapsulation_key, encapsulation_key) = K::generate(&mut OsRng);
147    Ok((
148        hex_encode(&encapsulation_key.as_bytes()),
149        hex_encode(&decapsulation_key.as_bytes()),
150    ))
151}
152
153/// 用公钥封装,返回 `(密文 hex, 共享密钥 hex)`。
154fn encapsulate_hex<K: KemCore>(
155    public_key_hex: &str,
156    label: &'static str,
157) -> Result<(String, String)> {
158    let bytes = hex_decode(public_key_hex)?;
159    let encoded = Encoded::<K::EncapsulationKey>::try_from(bytes.as_slice())
160        .map_err(|_| Error::InvalidKey { label })?;
161    // 长度之外还要过 FIPS 203 §7.2 的 modulus check(ml-kem 0.2.3 只查长度)。
162    modulus_check_ek(&bytes, label)?;
163    let encapsulation_key = K::EncapsulationKey::from_bytes(&encoded);
164    let (ciphertext, shared_key) = encapsulation_key
165        .encapsulate(&mut OsRng)
166        .map_err(|_| Error::EncryptionFailed { label })?;
167    Ok((hex_encode(&ciphertext), hex_encode(&shared_key)))
168}
169
170/// 用私钥解封装,返回共享密钥 hex。
171///
172/// 按 FIPS 203 隐式拒绝语义,密文内容错误(但长度合法)时不会返回错误,
173/// 而是一个与封装端不同的伪随机共享密钥。
174fn decapsulate_hex<K: KemCore>(
175    ciphertext_hex: &str,
176    private_key_hex: &str,
177    label: &'static str,
178    ciphertext_label: &'static str,
179) -> Result<String> {
180    let dk_bytes = hex_decode(private_key_hex)?;
181    let encoded = Encoded::<K::DecapsulationKey>::try_from(dk_bytes.as_slice())
182        .map_err(|_| Error::InvalidKey { label })?;
183    // dk = dkPKE ‖ ek ‖ H(ek) ‖ z。两道检查:
184    // 1) §7.3 的 hash check(解封装密钥输入检查):H(内嵌 ek) == 尾部存储的 h
185    //    (ml-kem 0.2.3 不做此检查,上游留有 XXX 注释;h 由公开 ek 派生,
186    //    非常量时间比较无信息泄露面);
187    // 2) 防御性扩展:§7.2 风格的 modulus check 顺带用于内嵌 ek —— §7.3 的检查
188    //    对象是 H(ek) 哈希,拦不住非规范 t̂,此扩展补上这一缺口。
189    let ek_size = <K::EncapsulationKey as EncodedSizeUser>::EncodedSize::USIZE;
190    let embedded_ek = &dk_bytes[dk_bytes.len() - 64 - ek_size..dk_bytes.len() - 64];
191    let stored_h = &dk_bytes[dk_bytes.len() - 64..dk_bytes.len() - 32];
192    if sha3_256(embedded_ek).as_slice() != stored_h {
193        return Err(Error::InvalidKey { label });
194    }
195    modulus_check_ek(embedded_ek, label)?;
196    let decapsulation_key = K::DecapsulationKey::from_bytes(&encoded);
197    let ciphertext = parse_ciphertext::<K>(ciphertext_hex, ciphertext_label)?;
198    let shared_key = decapsulation_key
199        .decapsulate(&ciphertext)
200        .map_err(|_| Error::DecryptionFailed { label })?;
201    Ok(hex_encode(&shared_key))
202}
203
204/// 解析定长编码(公钥 / 私钥):十六进制非法 → [`Error::InvalidHex`];
205/// 字节数或结构不符 → [`Error::InvalidKey`]。仅测试(KAT 向量装载)使用。
206#[cfg(test)]
207fn parse_encoded<T: EncodedSizeUser>(hex: &str, label: &'static str) -> Result<Encoded<T>> {
208    let bytes = hex_decode(hex)?;
209    Encoded::<T>::try_from(bytes.as_slice()).map_err(|_| Error::InvalidKey { label })
210}
211
212/// 解析密文:十六进制非法 → [`Error::InvalidHex`];字节数不符 → [`Error::InvalidKeyLength`]。
213fn parse_ciphertext<K: KemCore>(hex: &str, label: &'static str) -> Result<Ciphertext<K>> {
214    let bytes = hex_decode(hex)?;
215    Ciphertext::<K>::try_from(bytes.as_slice()).map_err(|_| Error::InvalidKeyLength {
216        label,
217        expected: <K::CiphertextSize as Unsigned>::USIZE,
218        got: bytes.len(),
219    })
220}
221
222/// SHA3-256(FIPS 203 §7.3 hash check 用;与 ml-kem 内部同源,digest 0.10 代际)。
223fn sha3_256(data: &[u8]) -> [u8; 32] {
224    use sha3::{Digest, Sha3_256};
225    Sha3_256::digest(data).into()
226}
227
228/// FIPS 203 §7.2 的 modulus check:`t̂` 的每个系数必须 < q(3329)。
229///
230/// `ek = ByteEncode₁₂(t̂) ‖ ρ`(ρ 为末尾 32 字节,不参与校验)。直接传入封装
231/// 接口的 ek 可能来自外部 / 不可信来源;非规范编码(系数 ≥ q)在 ml-kem 0.2.3
232/// 中不会被拒绝,本库在封装、以及解封装前(对 dk 内嵌的 ek)自行校验。系数按
233/// FIPS 203 §4.2.1 ByteDecode₁₂ 的 12 位小端打包解出。
234fn modulus_check_ek(ek: &[u8], label: &'static str) -> Result<()> {
235    const Q: u16 = 3329;
236    let (t_hat, _rho) = ek.split_at(ek.len() - 32);
237    for chunk in t_hat.as_chunks::<3>().0 {
238        let a0 = u16::from(chunk[0]) | (u16::from(chunk[1] & 0x0f) << 8);
239        let a1 = u16::from(chunk[1] >> 4) | (u16::from(chunk[2]) << 4);
240        if a0 >= Q || a1 >= Q {
241            return Err(Error::InvalidKey { label });
242        }
243    }
244    Ok(())
245}
246
247#[cfg(test)]
248mod tests {
249    use super::*;
250    use crate::registry::Registry;
251    use ml_kem::{B32, EncapsulateDeterministic};
252
253    use crate::manager::KeyEncapsulationManager;
254
255    /// ACVP 定值向量(每个参数集取第一个用例):
256    /// NIST ACVP-Server 仓库 `gen-val/json-files/ML-KEM-keyGen-FIPS203` 与
257    /// `ML-KEM-encapDecap-FIPS203` 的 internalProjection 数据(commit 65370b86,
258    /// 与 RustCrypto ml-kem 0.2.3 自带 KAT 同源)。keyGen 用例给出 (d, z) → (ek, dk),
259    /// encapDecap 用例给出 (ek, m) → (c, k) 及解封装 dk。
260    struct Kat {
261        d: &'static str,
262        z: &'static str,
263        gen_ek: &'static str,
264        gen_dk: &'static str,
265        encap_ek: &'static str,
266        encap_dk: &'static str,
267        m: &'static str,
268        c: &'static str,
269        k: &'static str,
270    }
271
272    const KAT_512: Kat = Kat {
273        d: "2CB843A02EF02EE109305F39119FABF49AB90A57FFECB3A0E75E179450F52761",
274        z: "84CC9121AE56FBF39E67ADBD83AD2D3E3BB80843645206BDD9F2F629E3CC49B7",
275        gen_ek: "A32439F85A3C21D21A71B9B92A9B64EA0AB84312C77023694FD64EAAB907A43539DDB27BA0A853CC9069EAC8508C653E600B2AC018381B4BB4A879ACDAD342F91179CA8249525CB1968BBE52F755B7F5B43D6663D7A3BF0F3357D8A21D15B52DB3818ECE5B402A60C993E7CF436487B8D2AE91E6C5B88275E75824B0007EF3123C0AB51B5CC61B9B22380DE66C5B20B060CBB986F8123D94060049CDF8036873A7BE109444A0A1CD87A48CAE54192484AF844429C1C58C29AC624CD504F1C44F1E1347822B6F221323859A7F6F754BFE710BDA60276240A4FF2A5350703786F5671F449F20C2A95AE7C2903A42CB3B303FF4C427C08B11B4CD31C418C6D18D0861873BFA0332F11271552ED7C035F0E4BC428C43720B39A65166BA9C2D3D770E130360CC2384E83095B1A159495533F116C7B558B650DB04D5A26EAAA08C3EE57DE45A7F88C6A3CEB24DC5397B88C3CEF003319BB0233FD692FDA1524475B351F3C782182DECF590B7723BE400BE14809C44329963FC46959211D6A623339537848C251669941D90B130258ADF55A720A724E8B6A6CAE3C2264B1624CCBE7B456B30C8C7393294CA5180BC837DD2E45DBD59B6E17B24FE93052EB7C43B27AC3DC249CA0CBCA4FB5897C0B744088A8A0779D32233826A01DD6489952A4825E5358A700BE0E179AC197710D83ECC853E52695E9BF87BB1F6CBD05B02D4E679E3B88DD483B0749B11BD37B383DCCA71F9091834A1695502C4B95FC9118C1CFC34C84C2265BBBC563C282666B60AE5C7F3851D25ECBB5021CC38CB73EB6A3411B1C29046CA66540667D136954460C6FCBC4BC7C049BB047FA67A63B3CC1111C1D8AC27E8058BCCA4A15455858A58358F7A61020BC9C4C17F8B95C268CCB404B9AAB4A272A21A70DAF6B6F15121EE01C156A354AA17087E07702EAB38B3241FDB553F657339D5E29DC5D91B7A5A828EE959FEBB90B07229F6E49D23C3A190297042FB43986955B69C28E1016F77A58B431514D21B888899C3608276081B75F568097CDC1748F32307885815F3AEC9651819AA6873D1A4EB83B1953843B93422519483FEF0059D36BB2DB1F3D468FB068C86E8973733C398EAF00E1702C6734AD8EB3B",
276        gen_dk: "7FE4206F26BEDB64C1ED0009615245DC98483F663ACC617E65898D596A8836C49FBD3B4A849759AA1546BDA835CAF175642C28280892A7878CC318BCC75B834CB29FDF5360D7F982A52C88AE914DBF02B58BEB8BA887AE8FAB5EB78731C6757805471EBCEC2E38DB1F4B8310D288920D8A492795A390A74BCD55CD8557B4DAABA82C28CB3F152C5231196193A66A8CCF34B80E1F6942C32BCFF96A6E3CF3939B7B942498CC5E4CB8E8468E702759852AA229C0257F02982097338607C0F0F45446FAB4267993B8A5908CAB9C46780134804AE18815B1020527A222EC4B39A3194E661737791714122662D8B9769F6C67DE625C0D483C3D420FF1BB889A727E756281513A70047648D29C0C30F9BE52EC0DEB977CF0F34FC2078483456964743410638C57B5539577BF85669078C356B3462E9FA5807D49591AFA41C1969F65E3405CB64DDF163F26734CE348B9CF4567A33A5969EB326CFB5ADC695DCA0C8B2A7B1F4F404CC7A0981E2CC24C1C23D16AA9B4392415E26C22F4A934D794C1FB4E5A67051123CCD153764DEC99D553529053C3DA550BCEA3AC54136A26A676D2BA8421067068C6381C2A62A727C933702EE5804A31CA865A45588FB74DE7E2223D88C0608A16BFEC4FAD6752DB56B48B8872BF26BA2FFA0CEDE5343BE8143689265E065F41A6925B86C892E62EB0772734F5A357C75CA1AC6DF78AB1B8885AD0819615376D33EBB98F8733A6755803D977BF51C12740424B2B49C28382A6917CBFA034C3F126A38C216C03C35770AD481B9084B5588DA65FF118A74F932C7E537ABE5863FB29A10C09701B441F8399C1F8A637825ACEA3E93180574FDEB88076661AB46951716A500184A040557266598CAF76105E1C1870B43969C3BCC1A04927638017498BB62CAFD3A6B082B7BF7A23450E191799619B925112D072025CA888548C791AA42251504D5D1C1CDDB213303B049E7346E8D83AD587836F35284E109727E66BBCC9521FE0B191630047D158F75640FFEB5456072740021AFD15A45469C583829DAAC8A7DEB05B24F0567E4317B3E3B33389B5C5F8B04B099FB4D103A32439F85A3C21D21A71B9B92A9B64EA0AB84312C77023694FD64EAAB907A43539DDB27BA0A853CC9069EAC8508C653E600B2AC018381B4BB4A879ACDAD342F91179CA8249525CB1968BBE52F755B7F5B43D6663D7A3BF0F3357D8A21D15B52DB3818ECE5B402A60C993E7CF436487B8D2AE91E6C5B88275E75824B0007EF3123C0AB51B5CC61B9B22380DE66C5B20B060CBB986F8123D94060049CDF8036873A7BE109444A0A1CD87A48CAE54192484AF844429C1C58C29AC624CD504F1C44F1E1347822B6F221323859A7F6F754BFE710BDA60276240A4FF2A5350703786F5671F449F20C2A95AE7C2903A42CB3B303FF4C427C08B11B4CD31C418C6D18D0861873BFA0332F11271552ED7C035F0E4BC428C43720B39A65166BA9C2D3D770E130360CC2384E83095B1A159495533F116C7B558B650DB04D5A26EAAA08C3EE57DE45A7F88C6A3CEB24DC5397B88C3CEF003319BB0233FD692FDA1524475B351F3C782182DECF590B7723BE400BE14809C44329963FC46959211D6A623339537848C251669941D90B130258ADF55A720A724E8B6A6CAE3C2264B1624CCBE7B456B30C8C7393294CA5180BC837DD2E45DBD59B6E17B24FE93052EB7C43B27AC3DC249CA0CBCA4FB5897C0B744088A8A0779D32233826A01DD6489952A4825E5358A700BE0E179AC197710D83ECC853E52695E9BF87BB1F6CBD05B02D4E679E3B88DD483B0749B11BD37B383DCCA71F9091834A1695502C4B95FC9118C1CFC34C84C2265BBBC563C282666B60AE5C7F3851D25ECBB5021CC38CB73EB6A3411B1C29046CA66540667D136954460C6FCBC4BC7C049BB047FA67A63B3CC1111C1D8AC27E8058BCCA4A15455858A58358F7A61020BC9C4C17F8B95C268CCB404B9AAB4A272A21A70DAF6B6F15121EE01C156A354AA17087E07702EAB38B3241FDB553F657339D5E29DC5D91B7A5A828EE959FEBB90B07229F6E49D23C3A190297042FB43986955B69C28E1016F77A58B431514D21B888899C3608276081B75F568097CDC1748F32307885815F3AEC9651819AA6873D1A4EB83B1953843B93422519483FEF0059D36BB2DB1F3D468FB068C86E8973733C398EAF00E1702C6734AD8EB3B620130D6C2B8C904A3BB9307BE5103F8D814505FB6A60AF7937EA6CAA117315E84CC9121AE56FBF39E67ADBD83AD2D3E3BB80843645206BDD9F2F629E3CC49B7",
277        encap_ek: "DD1924935AA8E617AF18B5A065AC45727767EE897CF4F9442B2ACE30C0237B307D3E76BF8EEB78ADDC4AACD16463D8602FD5487B63C88BB66027F37D0D614D6F9C24603C42947664AC4398C6C52383469B4F9777E5EC7206210F3E5A796BF45C53268E25F39AC261AF3BFA2EE755BEB8B67AB3AC8DF6C629C1176E9E3B965E9369F9B3B92AD7C20955641D99526FE7B9FE8C850820275CD964849250090733CE124ECF316624374BD18B7C358C06E9C136EE1259A9245ABC55B964D689F5A08292D28265658EBB40CBFE488A2228275590AB9F32A34109709C1C291D4A23337274C7A5A5991C7A87B81C974AB18CE77859E4995E7C14F0371748B7712FB52C5966CD63063C4F3B81B47C45DDE83FB3A2724029B10B3230214C04FA0577FC29AC9086AE18C53B3ED44E507412FCA04B4F538A51588EC1F1029D152D9AE7735F76A077AA9484380AED9189E5912487FCC5B7C7012D9223DD967EECDAC3008A8931B648243537F548C171698C5B381D846A72E5C92D4226C5A8909884F1C4A3404C1720A5279414D7F27B2B982652B6740219C56D217780D7A5E5BA59836349F726881DEA18EF75C0772A8B922766953718CACC14CCBACB5FC412A2D0BE521817645AB2BF6A4785E92BC94CAF477A967876796C0A5190315AC0885671A4C749564C3B2C7AED9064EBA299EF214BA2F40493667C8BD032AEC5621711B41A3852C5C2BAB4A349CE4B7F085A812BBBC820B81BEFE63A05B8BCDFE9C2A70A8B1ACA9BF9816481907FF4432461111287303F0BD817C05726BFA18A2E24C7724921028032F622BD960A317D83B356B57F4A8004499CBC73C97D1EB7745972631C0561C1A3AB6EF91BD363280A10545DA693E6D58AED6845E7CC5F0D08CA7905052C77366D1972CCFCC1A27610CB543665AA798E20940128B9567A7EDB7A900407C70D359438435E13961608D552A94C5CDA7859220509B483C5C52A210E9C812BC0C2328CA00E789A56B2606B90292E3543DACAA2431841D61A22CA90C1CCF0B5B4E0A6F640536D1A26AB5B8D2151327928CE02904CF1D15E32788A95F62D3C270B6FA1508F97B9155A2726D80A1AFA3C5387A276A4D031A08ABF4F2E74F1A0BB8A0FD3CB",
278        encap_dk: "A5E26E1B2360203944ACFC2D7C376780E55B5A5CA38674919437C794F54B8217BB0629C84C692EF7827EED864D0C508990CA4553F16F4720CB75368C1B8CA9DBC175F51BBEBAA456F36611A2364775D248C0F4C40B342608F7370A983CF75C915570248E367375B665D9357CE4A8553E659BE4A60CA68B58724689C23B74D34C9E78E168E7CB0DF84641E41B6E6807BE6CF4CF8F338525D57090B08AAB5721216395C49147F6E817B117B129987317A7A5FF15A279F86AF93C6A4995954000C3D4D8B0A07499A95A5C98D0B8303702DFD801B67C37268904C96ABC462750384BAEA767A5AD30C5D452682B3AC864D1671DB38F1CF2CE6E6C901D39C144DA3D93B863F95717C3C585AB876D3EF2B10AFA0B8142164C3C27FB179A923A3F924B15CEBB22EC762907324F1CD4C47573CA1F103CA88844F3B86687280B3B5BB569B1C118B63565055834F39F320CB88C05C199E29684D7802CF45D8DA342CC444D91A84D6D9461C873B66F9785488723A167412019077C9A7FCF4C7BD028BE3007B3483026A442A095124C9607C950443FD69993615697E9AC1CB9D380437B85EB300CE4D9B5A5BC2132660DA3527031A1057A565F2C76775565B0088637707410F2E955355425EFE496113149CF52C901BCCC48864C8AA4262367213602B63AA1A8BED77826C0C476152AB3464A20C9CD73F17A1D019466F2AE37859E6E5A8BB8862A480C1B12D6797B79663ED2333F188F34E6CF6EC87E43979F88787CE35877DDF0B689547BF5BA9EEBB2659D76354EBC39EE83975310ACA4F8867FF290793CC08BF29E60A97C28A71EA3084FE27845AB3664E80592412043B03056FDD5744BD74C9584094C2B75C689ACA8E4B3D3F91994E4722B9B331399310975275A0065935B6CDF5A6A8216188452394238BC82736488A84A0C96C580A81C69032AD5E96F4C3061DF5AB246C258CBA0B68A32916BFC6686730B3FF0944A070F535A113FC349CDDB0B67B40DEBFB5215167090F9891365BB3D87639FDA05843A079A430FD5892F57AC4510450DEC00B7905A3A14442231919F9ED4A76B2B159A6CCC3685B3DD1924935AA8E617AF18B5A065AC45727767EE897CF4F9442B2ACE30C0237B307D3E76BF8EEB78ADDC4AACD16463D8602FD5487B63C88BB66027F37D0D614D6F9C24603C42947664AC4398C6C52383469B4F9777E5EC7206210F3E5A796BF45C53268E25F39AC261AF3BFA2EE755BEB8B67AB3AC8DF6C629C1176E9E3B965E9369F9B3B92AD7C20955641D99526FE7B9FE8C850820275CD964849250090733CE124ECF316624374BD18B7C358C06E9C136EE1259A9245ABC55B964D689F5A08292D28265658EBB40CBFE488A2228275590AB9F32A34109709C1C291D4A23337274C7A5A5991C7A87B81C974AB18CE77859E4995E7C14F0371748B7712FB52C5966CD63063C4F3B81B47C45DDE83FB3A2724029B10B3230214C04FA0577FC29AC9086AE18C53B3ED44E507412FCA04B4F538A51588EC1F1029D152D9AE7735F76A077AA9484380AED9189E5912487FCC5B7C7012D9223DD967EECDAC3008A8931B648243537F548C171698C5B381D846A72E5C92D4226C5A8909884F1C4A3404C1720A5279414D7F27B2B982652B6740219C56D217780D7A5E5BA59836349F726881DEA18EF75C0772A8B922766953718CACC14CCBACB5FC412A2D0BE521817645AB2BF6A4785E92BC94CAF477A967876796C0A5190315AC0885671A4C749564C3B2C7AED9064EBA299EF214BA2F40493667C8BD032AEC5621711B41A3852C5C2BAB4A349CE4B7F085A812BBBC820B81BEFE63A05B8BCDFE9C2A70A8B1ACA9BF9816481907FF4432461111287303F0BD817C05726BFA18A2E24C7724921028032F622BD960A317D83B356B57F4A8004499CBC73C97D1EB7745972631C0561C1A3AB6EF91BD363280A10545DA693E6D58AED6845E7CC5F0D08CA7905052C77366D1972CCFCC1A27610CB543665AA798E20940128B9567A7EDB7A900407C70D359438435E13961608D552A94C5CDA7859220509B483C5C52A210E9C812BC0C2328CA00E789A56B2606B90292E3543DACAA2431841D61A22CA90C1CCF0B5B4E0A6F640536D1A26AB5B8D2151327928CE02904CF1D15E32788A95F62D3C270B6FA1508F97B9155A2726D80A1AFA3C5387A276A4D031A08ABF4F2E74F1A0BB8A0FD3CB0AC923A76D541CA65FDEC9C788A407326C7DB508119F617F43B6E8A6F48A398702E051C20C31DE77A1BA6777829F5539C886E3E14DED294D56AE5E88AC06AB09",
279        m: "6FF02E1DC7FD911BEEE0C692C8BD100C3E5C48964D31DF92994218E80664A6CA",
280        c: "19C592505907C24C5FA2EBFA932D2CBB48F3E4340A28F7EBA5D068FCACABEDF77784E2B24D7961775F0BF1A997AE8BA9FC4311BE63716779C2B788F812CBB78C74E7517E22E910EFF5F38D44469C50DE1675AE198FD6A289AE7E6C30A9D4351B3D1F4C36EFF9C68DA91C40B82DC9B2799A33A26B60A4E70D7101862779469F3A9DAEC8E3E8F8C6A16BF092FBA5866186B8D208FDEB274AC1F829659DC2BE4AC4F306CB5584BAD1936A92C9B76819234281BB395841C25756086EA564CA3E227E3D9F1052C0766D2EB79A47C150721E0DEA7C0069D551B264801B7727ECAF82EECB99A876FDA090BF6C3FC6B109F1701485F03CE66274B8435B0A014CFB3E79CCED67057B5AE2AD7F5279EB714942E4C1CCFF7E85C0DB43E5D41289207363B444BB51BB8AB0371E70CBD55F0F3DAD403E105176E3E8A225D84AC8BEE38C821EE0F547431145DCB3139286ABB11794A43A3C1B5229E4BCFE959C78ADAEE2D5F2497B5D24BC21FA03A9A58C2455373EC89583E7E588D7FE67991EE93783ED4A6F9EEAE04E64E2E1E0E699F6DC9C5D39EF9278C985E7FDF2A764FFD1A0B95792AD681E930D76DF4EFE5D65DBBD0F1438481ED833AD4946AD1C69AD21DD7C86185774426F3FCF53B52AD4B40D228CE124072F592C7DAA057F17D790A5BD5B93834D58C08C88DC8F0EF488156425B744654EACA9D64858A4D6CEB478795194BFADB18DC0EA054F9771215AD3CB1FD031D7BE4598621926478D375A1845AA91D7C733F8F0E188C83896EDF83B8646C99E29C0DA2290E71C3D2E970720C97B5B7F950486033C6A2571DDF2BCCDABB2DFA5FCE4C3A1884606041D181C728794AE0E806ECB49AF16756A4CE73C87BD4234E60F05535FA5929FD5A34473266401F63BBD6B90E003472AC0CE88F1B666597279D056A632C8D6B790FD411767848A69E37A8A839BC766A02CA2F695EC63F056A4E2A114CACF9FD90D730C970DB387F6DE73395F701A1D953B2A89DD7EDAD439FC205A54A481E889B098D5255670F026B4A2BF02D2BDDE87C766B25FC5E0FD453757E756D18C8CD912F9A77F8E6BF0205374B462",
281        k: "0BF323338D6F0A21D5514B673CD10B714CE6E36F35BCD1BF544196368EE51A13",
282    };
283
284    const KAT_768: Kat = Kat {
285        d: "E34A701C4C87582F42264EE422D3C684D97611F2523EFE0C998AF05056D693DC",
286        z: "A85768F3486BD32A01BF9A8F21EA938E648EAE4E5448C34C3EB88820B159EEDD",
287        gen_ek: "6D14A071F7CC452558D5E71A7B087062ECB1386844588246126402B1FA1637733CD5F60CC84BCB646A7892614D7C51B1C7F1A2799132F13427DC482158DA254470A59E00A4E49686FDC077559367270C2153F11007592C9C4310CF8A12C6A8713BD6BB51F3124F989BA0D54073CC242E0968780B875A869EFB851586B9A868A384B9E6821B201B932C455369A739EC22569C977C212B381871813656AF5B567EF893B584624C863A259000F17B254B98B185097C50EBB68B244342E05D4DE520125B8E1033B1436093ACE7CE8E71B458D525673363045A3B3EEA9455428A398705A42327ADB3774B7057F42B017EC0739A983F19E8214D09195FA24D2D571DB73C19A6F8460E50830D415F627B88E94A7B153791A0C0C7E9484C74D53C714889F0E321B6660A532A5BC0E557FBCA35E29BC611200ED3C633077A4D873C5CC67006B753BF6D6B7AF6CA402AB618236C0AFFBC801F8222FBC36CE0984E2B18C944BBCBEF03B1E1361C1F44B0D734AFB1566CFF8744DA8B9943D6B45A3C09030702CA201FFE20CB7EC5B0D4149EE2C28E8B23374F471B57150D0EC9336261A2D5CB84A3ACACC4289473A4C0ABC617C9ABC178734434C82E1685588A5C2EA2678F6B3C2228733130C466E5B86EF491153E48662247B875D201020B566B81B64D839AB4633BAA8ACE202BAAB4496297F9807ADBBB1E332C6F8022B2A18CFDD4A82530B6D3F007C3353898D966CC2C21CB4244BD00443F209870ACC42BC33068C724EC17223619C1093CCA6AEB29500664D1225036B4B81091906969481F1C723C140B9D6C168F5B64BEA69C5FD6385DF7364B8723BCC85E038C7E464A900D68A2127818994217AEC8BDB39A970A9963DE93688E2AC82ABCC22FB9277BA22009E878381A38163901C7D4C85019538D35CAAE9C41AF8C929EE20BB08CA619E72C2F2262C1C9938572551AC02DC9268FBCC35D79011C3C090AD40A4F111C9BE55C427EB796C1932D8673579AF1B4C638B0944489012A2559A3B02481B01AC30BA8960F80C0C2B3947D36A12C080498BEE448716C973416C8242804A3DA099EE137B0BA90FE4A5C6A89200276A0CFB643EC2C56A2D708D7B4373E44C1502A763A600586E6CDA6273897D44448287DC2E602DC39200BF6166236559FD12A60892AEB153DD651BB469910B4B34669F91DA8654D1EB72EB6E02800B3B0A7D0A48C836854D3A83E65569CB7230BB44F3F143A6DEC5F2C39AB90F274F2088BD3D6A6FCA0070273BEDC84777FB52E3C558B0AE06183D5A48D452F68E15207F861627ACA14279630F82EC3A0CA078633B600AFA79743A600215BE5637458CE2CE8AFF5A08EB5017B2C766577479F8DC6BF9F5CC75089932161B96CEA406620AEDB630407F7687EBBB4814C7981637A48A90DE68031E062A7AF7612B4F5C7A6DA86BD136529E64295A5613EA73BD3D4448CB81F243135C0A660BEB9C17E651DEF469A7D90A15D3481090BCBF227012328941FA46F39C5006AD93D458AA6ADD655862B418C3094F551460DF2153A5810A7DA74F0614C2588BE49DC6F5E88154642BD1D3762563326433507156A57C57694BDD26E7A246FEB723AED67B04887C8E476B48CAB59E5362F26A9EF50C2BC80BA146226216FE62968A60D04E8C170D741C7A2B0E1ABDAC968",
288        gen_dk: "98A1B2DA4A65CFB5845EA7311E6A06DB731F1590C41EE74BA10782715B35A3102DF637872BE65BAB37A1DE2511D703C70247B35EF27435485024D93FD9E77C43804F371749BA00B20A8C5C588BC9ABE068AEAAA938517EBFE53B6B663282903DCD189736D7296816C733A1C77C6375E5397C0F189BBFE47643A61F58F8A3C6911BE4611A8C7BC050021163D0A404DC14065748FF29BE60D2B9FDCC8FFD98C587F38C67115786464BDB342B17E897D64617CBFB117973A5458977A7D7617A1B4D83BA03C611138A4673B1EB34B078033F97CFFE80C146A26943F842B976327BF1CBC60119525BB9A3C03493349000DD8F51BA21A2E92361762324600E0C13AAA6CB69BFB24276483F6B02421259B7585263C1A028D682C508BBC2801A56E98B8F620B0483D79B5AD8585AC0A475BAC77865194196338791B7985A05D109395CCA8932722A91950D37E12B891420A52B62CBFA815DF6174CE00E68BCA75D4838CA280F713C7E6924AFD95BAA0D01ADA637B158347034C0AB1A7183331A820ACBCB83193A1A94C8F7E384AED0C35ED3CB3397BB638086E7A35A6408A3A4B90CE953707C19BC46C3B2DA3B2EE32319C56B928032B5ED1256D0753D341423E9DB139DE7714FF075CAF58FD9F57D1A54019B5926406830DAE29A875302A81256F4D6CF5E74034EA614BF70C2764B20C9589CDB5C25761A04E58292907C578A94A35836BEE3112DC2C3AE2192C9DEAA304B29C7FEA1BDF47B3B6BCBA2C0E55C9CDB6DE7149E9CB17917718F12C8032DE1ADE0648D405519C70719BECC701845CF9F4B912FE71983CA34F9018C7CA7BB2F6C5D7F8C5B297359EC75209C2543FF11C4244977C5969524EC454D44C323FCCA94ACAC273A0EC49B4A8A585BCE7A5B305C04C3506422580357016A850C3F7EE17205A77B291C7731C9836C02AEE5406F63C6A07A214382AA15336C05D1045588107645EA7DE6870FC0E55E1540974301C42EC14105518680F688ABE4CE453738FE471B87FC31F5C68A39E68AF51B0240B90E0364B04BAC43D6FB68AB65AE028B62BD683B7D28AD38806BEE725B5B2416A8D79C16EC2A99EA4A8D92A2F5052E67F97352289761C5C39FC5C742E9C0A740CA59FC0182F709D01B5187F00063DAAB397596EEA4A31BDBCBD4C1BB0C55BE7C6850FDA9326B353E288C5013226C3C3923A791609E8002E73A5F7B6BB4A877B1FDF53BB2BAB3DD424D31BBB448E609A66B0E343C286E8760312B6D37AA5201D21F53503D88389ADCA21C70FB6C0FC9C69D6616C9EA3780E35565C0C97C15179C95343ECC5E1C2A24DE4699F6875EA2FA2DD3E357BC43914795207E026B850A2237950C108A512FC88C22488112607088185FB0E09C2C4197A83687266BAB2E583E21C40F4CC008FE652804D8223F1520A90B0D5385C7553CC767C58D120CCD3EF5B5D1A6CD7BC00DFF1321B2F2C432B64EFB8A3F5D0064B3F34293026C851C2DED68B9DFF4A28F6A8D225535E0477084430CFFDA0AC0552F9A212785B749913A06FA2274C0D15BAD325458D323EF6BAE13C0010D525C1D5269973AC29BDA7C983746918BA0E002588E30375D78329E6B8BA8C4462A692FB6083842B8C8C92C60F252726D14A071F7CC452558D5E71A7B087062ECB1386844588246126402B1FA1637733CD5F60CC84BCB646A7892614D7C51B1C7F1A2799132F13427DC482158DA254470A59E00A4E49686FDC077559367270C2153F11007592C9C4310CF8A12C6A8713BD6BB51F3124F989BA0D54073CC242E0968780B875A869EFB851586B9A868A384B9E6821B201B932C455369A739EC22569C977C212B381871813656AF5B567EF893B584624C863A259000F17B254B98B185097C50EBB68B244342E05D4DE520125B8E1033B1436093ACE7CE8E71B458D525673363045A3B3EEA9455428A398705A42327ADB3774B7057F42B017EC0739A983F19E8214D09195FA24D2D571DB73C19A6F8460E50830D415F627B88E94A7B153791A0C0C7E9484C74D53C714889F0E321B6660A532A5BC0E557FBCA35E29BC611200ED3C633077A4D873C5CC67006B753BF6D6B7AF6CA402AB618236C0AFFBC801F8222FBC36CE0984E2B18C944BBCBEF03B1E1361C1F44B0D734AFB1566CFF8744DA8B9943D6B45A3C09030702CA201FFE20CB7EC5B0D4149EE2C28E8B23374F471B57150D0EC9336261A2D5CB84A3ACACC4289473A4C0ABC617C9ABC178734434C82E1685588A5C2EA2678F6B3C2228733130C466E5B86EF491153E48662247B875D201020B566B81B64D839AB4633BAA8ACE202BAAB4496297F9807ADBBB1E332C6F8022B2A18CFDD4A82530B6D3F007C3353898D966CC2C21CB4244BD00443F209870ACC42BC33068C724EC17223619C1093CCA6AEB29500664D1225036B4B81091906969481F1C723C140B9D6C168F5B64BEA69C5FD6385DF7364B8723BCC85E038C7E464A900D68A2127818994217AEC8BDB39A970A9963DE93688E2AC82ABCC22FB9277BA22009E878381A38163901C7D4C85019538D35CAAE9C41AF8C929EE20BB08CA619E72C2F2262C1C9938572551AC02DC9268FBCC35D79011C3C090AD40A4F111C9BE55C427EB796C1932D8673579AF1B4C638B0944489012A2559A3B02481B01AC30BA8960F80C0C2B3947D36A12C080498BEE448716C973416C8242804A3DA099EE137B0BA90FE4A5C6A89200276A0CFB643EC2C56A2D708D7B4373E44C1502A763A600586E6CDA6273897D44448287DC2E602DC39200BF6166236559FD12A60892AEB153DD651BB469910B4B34669F91DA8654D1EB72EB6E02800B3B0A7D0A48C836854D3A83E65569CB7230BB44F3F143A6DEC5F2C39AB90F274F2088BD3D6A6FCA0070273BEDC84777FB52E3C558B0AE06183D5A48D452F68E15207F861627ACA14279630F82EC3A0CA078633B600AFA79743A600215BE5637458CE2CE8AFF5A08EB5017B2C766577479F8DC6BF9F5CC75089932161B96CEA406620AEDB630407F7687EBBB4814C7981637A48A90DE68031E062A7AF7612B4F5C7A6DA86BD136529E64295A5613EA73BD3D4448CB81F243135C0A660BEB9C17E651DEF469A7D90A15D3481090BCBF227012328941FA46F39C5006AD93D458AA6ADD655862B418C3094F551460DF2153A5810A7DA74F0614C2588BE49DC6F5E88154642BD1D3762563326433507156A57C57694BDD26E7A246FEB723AED67B04887C8E476B48CAB59E5362F26A9EF50C2BC80BA146226216FE62968A60D04E8C170D741C7A2B0E1ABDAC968E29020839D052FA372585627F8B59EE312AE414C979D825F06A6929A79625718A85768F3486BD32A01BF9A8F21EA938E648EAE4E5448C34C3EB88820B159EEDD",
289        encap_ek: "89D2CB65F94DCBFC890EFC7D0E5A7A38344D1641A3D0B024D50797A5F23C3A18B3101A1269069F43A842BACC098A8821271C673DB1BEB33034E4D7774D16635C7C2C3C2763453538BC1632E1851591A51642974E5928ABB8E55FE55612F9B141AFF015545394B2092E590970EC29A7B7E7AA1FB4493BF7CB731906C2A5CB49E6614859064E19B8FA26AF51C44B5E7535BFDAC072B646D3EA490D277F0D97CED47395FED91E8F2BCE0E3CA122C2025F74067AB928A822B35653A74F06757629AFB1A1CAF237100EA935E793C8F58A71B3D6AE2C8658B10150D4A38F572A0D49D28AE89451D338326FDB3B4350036C1081117740EDB86B12081C5C1223DBB5660D5B3CB3787D481849304C68BE875466F14EE5495C2BD795AE412D09002D65B8719B90CBA3603AC4958EA03CC138C86F7851593125334701B677F82F4952A4C93B5B4C134BB42A857FD15C650864A6AA94EB691C0B691BE4684C1F5B7490467FC01B1D1FDA4DDA35C4ECC231BC73A6FEF42C99D34EB82A4D014987B3E386910C62679A118F3C5BD9F467E4162042424357DB92EF484A4A1798C1257E870A30CB20AAA0335D83314FE0AA7E63A862648041A72A6321523220B1ACE9BB701B21AC1253CB812C15575A9085EABEADE73A4AE76E6A7B158A20586D78A5AC620A5C9ABCC9C043350A73656B0ABE822DA5E0BA76045FAD75401D7A3B703791B7E99261710F86B72421D240A347638377205A152C794130A4E047742B888303BDDC309116764DE7424CEBEA6DB65348AC537E01A9CC56EA667D5AA87AC9AAA4317D262C10143050B8D07A728CA633C13E468ABCEAD372C77B8ECF3B986B98C1E55860B2B4216766AD874C35ED7205068739230220B5A2317D102C598356F168ACBE80608DE4C9A710B8DD07078CD7C671058AF1B0B8304A314F7B29BE78A933C7B9294424954A1BF8BC745DE86198659E0E1225A910726074969C39A97C19240601A46E013DCDCB677A8CBD2C95A40629C256F24A328951DF57502AB30772CC7E5B850027C8551781CE4985BDACF6B865C104E8A4BC65C41694D456B7169E45AB3D7ACABEAFE23AD6A7B94D1979A2F4C1CAE7CD77D681D290B5D8E451BFDCCCF5310B9D12A88EC29B10255D5E17A192670AA9731C5CA67EC784C502781BE8527D6FC003C6701B3632284B40307A527C7620377FEB0B73F722C9E3CD4DEC64876B93AB5B7CFC4A657F852B659282864384F442B22E8A21109387B8B47585FC680D0BA45C7A8B1D7274BDA57845D100D0F42A3B74628773351FD7AC305B2497639BE90B3F4F71A6AA3561EECC6A691BB5CB3914D8634CA1E1AF543C049A8C6E868C51F0423BD2D5AE09B79E57C27F3FE3AE2B26A441BABFC6718CE8C05B4FE793B910B8FBCBBE7F1013242B40E0514D0BDC5C88BAC594C794CE5122FBF34896819147B928381587963B0B90034AA07A10BE176E01C80AD6A4B71B10AF4241400A2A4CBBC05961A15EC1474ED51A3CC6D35800679A462809CAA3AB4F7094CD6610B4A700CBA939E7EAC93E38C99755908727619ED76A34E53C4FA25BFC97008206697DD145E5B9188E5B014E941681E15FE3E132B8A3903474148BA28B987111C9BCB3989BBBC671C581B44A492845F288E62196E471FED3C39C1BBDDB0837D0D4706B0922C4",
290        encap_dk: "B09125AFB3CFB5295581373AB6885284D9706318280D223EDC987FD14410DBE82E6AC89ADFAB70E67CA4B1C641AD037FD8C47870F159EC79CDCD52605B9890499BB6DBD8347F342C61436B642C0DDF4617DB06198B8285DCE4C09D9775A2F41C8CD18AF8E75F57D4127DF94D901AC83BACBD584CC50C43750F49B357F59350875C9B475480A8AAA168592DDB158614A639813566D205368C6C39F0413CA3230DF60D44008282B682AC66B76C3C95F00B2A555035529C86EF3905B4A3968FEA7802B6C5EECB08E8F0C42D7AB7CD21A62FB136412A1840B52C99970CCF51892F73497C3775BE2189F7FC25E7C74D81FC217683292AA4866DDB04469855323A0810F0893DE5C7F94A9C0B5337DB83C44891B2E694695B76575032BF51761682958BD4F97BE9A355B4A85BB6858B7E5A5EF653AB781056AF9187D811C3A8936E5706503DB57062410BCC9421F1AB867A657856C411C4E025ECB3C387729AE8E112F330B988E22F47C35C280750D21B107687AF7B329EF3CB5289F06FB7D44548391E97BA6DD499B5907C54958413D92AA99D5646CF47A8F48CB70A07AD056B4EEFE6C8C46645F7028A32410558638C48E83AC1570160C3833BF64052F5B7DF4364D3E0B24E790AA7C98CEE0441E6731D9DE22D156C61E1C740397672EF54724F01B9D49923AA321F86B98823F21360138392B90C69434635275F9BFBB9B8A99E8E1B7F4EC25F75DBCE33C13F750170BD6722EFE496E7463E16AAA5867B869A96AD41B22BD2556C924596FD778D79A102F6E46D8EB18FEFAC8DB19993E5414AC816705286892492C8C9E852D6145DFF0C10E4A6703A459E7E732A6DFA2766A622B0622BFEDB8F41C125F61B2EC264853B9CCC165979F6A263BEB148905AAC7618A70E829E23F28696F92EF6FA07C102CDBDB1288BA5CFF3A81ABBA15974535FE3106A80068F14E98964572350A7112B1601C196710C096CCF164FBCE1AABAC9C5B9535070E61AB8068D611CA765FABB6412607DAB30C4FC6AD073731FDC4C48B88E267C47B439AD2560C30561815CEB1F52C896489944BBBAB52B1B1D1680A1057964DAFA600C93A39A447DDBB0ADF911AFE3E823D8ACC7CC04659F625F2C1837BB175282542CD22601F621581AB5A6C0384E087CCD32A5380B522FDD3A4202B5B41C85CAFF2903B2DC2645703D9BC711FBB404C0C0376187AC588AAF5718522D2273A9408DABCBC9701698D2DA172AA6267A4C9693A24011C2265A2B6DC8E96304A98DDC5319A3140C399A08412C20F48537870BB84C32A094457895511FF7EC421DE01A64B78534653F78327441B90CD115939DFAAFA95B40D0A63D62D12EB5C9096018CC83871E44E6CD0BE26D16B7B5A209B8E6471D2954ADF9FABD0153707C9CAA2BCC38DED841C791A0EB597EEEE2C518D926EDB28AB53CAA5B7746466931B0AC9150688BF37049C1F82BCF648332434CD0A92FD2C958353A26CB65CB499057109B2D688CC43C4B385DA7C50868AF1B8075E57088F5DB12DFA493EACB6DC4EC6E205BAA2A89858EC2823C00553714CDE47A96E36C7C198B3EC57CCF74D92CDDB86AA0A8B8B5CA9D52BB60ABA79F4F72B0125532CEB7A9077480D2BB60DF51A989D2CB65F94DCBFC890EFC7D0E5A7A38344D1641A3D0B024D50797A5F23C3A18B3101A1269069F43A842BACC098A8821271C673DB1BEB33034E4D7774D16635C7C2C3C2763453538BC1632E1851591A51642974E5928ABB8E55FE55612F9B141AFF015545394B2092E590970EC29A7B7E7AA1FB4493BF7CB731906C2A5CB49E6614859064E19B8FA26AF51C44B5E7535BFDAC072B646D3EA490D277F0D97CED47395FED91E8F2BCE0E3CA122C2025F74067AB928A822B35653A74F06757629AFB1A1CAF237100EA935E793C8F58A71B3D6AE2C8658B10150D4A38F572A0D49D28AE89451D338326FDB3B4350036C1081117740EDB86B12081C5C1223DBB5660D5B3CB3787D481849304C68BE875466F14EE5495C2BD795AE412D09002D65B8719B90CBA3603AC4958EA03CC138C86F7851593125334701B677F82F4952A4C93B5B4C134BB42A857FD15C650864A6AA94EB691C0B691BE4684C1F5B7490467FC01B1D1FDA4DDA35C4ECC231BC73A6FEF42C99D34EB82A4D014987B3E386910C62679A118F3C5BD9F467E4162042424357DB92EF484A4A1798C1257E870A30CB20AAA0335D83314FE0AA7E63A862648041A72A6321523220B1ACE9BB701B21AC1253CB812C15575A9085EABEADE73A4AE76E6A7B158A20586D78A5AC620A5C9ABCC9C043350A73656B0ABE822DA5E0BA76045FAD75401D7A3B703791B7E99261710F86B72421D240A347638377205A152C794130A4E047742B888303BDDC309116764DE7424CEBEA6DB65348AC537E01A9CC56EA667D5AA87AC9AAA4317D262C10143050B8D07A728CA633C13E468ABCEAD372C77B8ECF3B986B98C1E55860B2B4216766AD874C35ED7205068739230220B5A2317D102C598356F168ACBE80608DE4C9A710B8DD07078CD7C671058AF1B0B8304A314F7B29BE78A933C7B9294424954A1BF8BC745DE86198659E0E1225A910726074969C39A97C19240601A46E013DCDCB677A8CBD2C95A40629C256F24A328951DF57502AB30772CC7E5B850027C8551781CE4985BDACF6B865C104E8A4BC65C41694D456B7169E45AB3D7ACABEAFE23AD6A7B94D1979A2F4C1CAE7CD77D681D290B5D8E451BFDCCCF5310B9D12A88EC29B10255D5E17A192670AA9731C5CA67EC784C502781BE8527D6FC003C6701B3632284B40307A527C7620377FEB0B73F722C9E3CD4DEC64876B93AB5B7CFC4A657F852B659282864384F442B22E8A21109387B8B47585FC680D0BA45C7A8B1D7274BDA57845D100D0F42A3B74628773351FD7AC305B2497639BE90B3F4F71A6AA3561EECC6A691BB5CB3914D8634CA1E1AF543C049A8C6E868C51F0423BD2D5AE09B79E57C27F3FE3AE2B26A441BABFC6718CE8C05B4FE793B910B8FBCBBE7F1013242B40E0514D0BDC5C88BAC594C794CE5122FBF34896819147B928381587963B0B90034AA07A10BE176E01C80AD6A4B71B10AF4241400A2A4CBBC05961A15EC1474ED51A3CC6D35800679A462809CAA3AB4F7094CD6610B4A700CBA939E7EAC93E38C99755908727619ED76A34E53C4FA25BFC97008206697DD145E5B9188E5B014E941681E15FE3E132B8A3903474148BA28B987111C9BCB3989BBBC671C581B44A492845F288E62196E471FED3C39C1BBDDB0837D0D4706B0922C472E31DF613DA9A1DD33B5D2D8939684B89F7649E1C59B959FFBE972786C477F66177DBF3B059173FD06AFCD90E80E862174FC57F97607BBFF5B73D6360FB5C37",
291        m: "2CE74AD291133518FE60C7DF5D251B9D82ADD48462FF505C6E547E949E6B6BF7",
292        c: "56B42D593AAB8E8773BD92D76EABDDF3B1546F8326F57A7B773764B6C0DD30470F68DFF82E0DCA92509274ECFE83A954735FDE6E14676DAAA3680C30D524F4EFA79ED6A1F9ED7E1C00560E8683538C3105AB931BE0D2B249B38CB9B13AF5CEAF7887A59DBA16688A7F28DE0B14D19F391EB41832A56479416CCF94E997390ED7878EEAFF49328A70E0AB5FCE6C63C09B35F4E45994DE615B88BB722F70E87D2BBD72AE71E1EE9008E459D8E743039A8DDEB874FCE5301A2F8C0EE8C2FEE7A4EE68B5ED6A6D9AB74F98BB3BA0FE89E82BD5A525C5E8790F818CCC605877D46C8BDB5C337B025BB840FF471896E43BFA99D73DBE31805C27A43E57F0618B3AE522A4644E0D4E4C1C548489431BE558F3BFC50E16617E110DD7AF9A6FD83E3FBB68C304D15F6CB700D61D7AA915A6751EA3BA80223E654132A20999A43BF408592730B9A9499636C09FA729F9CB1F9D3442F47357A2B9CF15D3103B9BF396C23088F118EDE346B5C03891CFA5D517CEF8471322E7E31087C4B036ABAD784BFF72A9B11FA198FACBCB91F067FEAF76FCFE5327C1070B3DA6988400756760D2D1F060298F1683D51E3616E98C51C9C03AA42F2E633651A47AD3CC2AB4A852AE0C4B04B4E1C3DD944445A2B12B4F42A6435105C04122FC3587AFE409A00B308D63C5DD8163654504EEDBB7B5329577C35FBEB3F463872CAC28142B3C12A740EC6EA7CE9AD78C6FC8FE1B4DF5FC55C1667F31F2312DA07799DC870A478608549FEDAFE021F1CF2984180364E90AD98D845652AA3CDD7A8EB09F5E51423FAB42A7B7BB4D514864BE8D71297E9C3B17A993F0AE62E8EF52637BD1B885BD9B6AB727854D703D8DC478F96CB81FCE4C60383AC01FCF0F971D4C8F352B7A82E218652F2C106CA92AE686BACFCEF5D327347A97A9B375D67341552BC2C538778E0F9801823CCDFCD1EAADED55B18C9757E3F212B2889D3857DB51F981D16185FD0F900853A75005E3020A8B95B7D8F2F2631C70D78A957C7A62E1B3719070ACD1FD480C25B83847DA027B6EBBC2EEC2DF22C87F9B46D5D7BAF156B53CEE929572B92C4784C4E829F3446A1FFE47F99DECD0436029DDEBD3ED8E87E5E73D123DBE8A4DDACF2ABDE87F33AE2B621C0EC5D5CAD1259DEEC2AEFF6088F04F27A20338B5762543E5100899A4CBFB7B3CA456B3A19B83A4C432230C23E1C7F107C4CB112152F1C0F30DA0BB33F4F11F47EEA43872BAFA84AE22256D708E0604DADE4B2A4DDE8CCCF11930E13553934AE3ECE52F3D7CCC00287377879FE6B8ECE7EF79423507C9DA339559C20DE1C51955999BAE47401DC3CDFAA1B256D09C7DB9FC8698BFCEFA7302D56FBCDE1FBAAA1C653454E6FD3D84E4F79A931C681CBB6CB462B10DAE112BDFB7F65C7FDF6E5FC594EC3A474A94BD97E6EC81F71C230BF70CA0F13CE3DFFBD9FF9804EFD8F37A4D3629B43A8F55544EBC5AC0ABD9A33D79699068346A0F1A3A96E115A5D80BE165B562D082984D5AACC3A2301981A6418F8BA7D7B0D7CA5875C6",
293        k: "2696D28E9C61C2A01CE9B1608DCB9D292785A0CD58EFB7FE13B1DE95F0DB55B3",
294    };
295
296    const KAT_1024: Kat = Kat {
297        d: "49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3",
298        z: "99E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7",
299        gen_ek: "A04184D4BC7B532A0F70A54D7757CDE6175A6843B861CB2BC4830C0012554CFC5D2C8A2027AA3CD967130E9B96241B11C4320C7649CC23A71BAFE691AFC08E680BCEF42907000718E4EACE8DA28214197BE1C269DA9CB541E1A3CE97CFADF9C6058780FE6793DBFA8218A2760B802B8DA2AA271A38772523A76736A7A31B9D3037AD21CEBB11A472B8792EB17558B940E70883F264592C689B240BB43D5408BF446432F412F4B9A5F6865CC252A43CF40A320391555591D67561FDD05353AB6B019B3A08A73353D51B6113AB2FA51D975648EE254AF89A230504A236A4658257740BDCBBE1708AB022C3C588A410DB3B9C308A06275BDF5B4859D3A2617A295E1A22F90198BAD0166F4A943417C5B831736CB2C8580ABFDE5714B586ABEEC0A175A08BC710C7A2895DE93AC438061BF7765D0D21CD418167CAF89D1EFC3448BCBB96D69B3E010C82D15CAB6CACC6799D3639669A5B21A633C865F8593B5B7BC800262BB837A924A6C5440E4FC73B41B23092C3912F4C6BEBB4C7B4C62908B03775666C22220DF9C88823E344C7308332345C8B795D34E8C051F21F5A21C214B69841358709B1C305B32CC2C3806AE9CCD3819FFF4507FE520FBFC27199BC23BE6B9B2D2AC1717579AC769279E2A7AAC68A371A47BA3A7DBE016F14E1A727333663C4A5CD1A0F8836CF7B5C49AC51485CA60345C990E06888720003731322C5B8CD5E6907FDA1157F468FD3FC20FA8175EEC95C291A262BA8C5BE990872418930852339D88A19B37FEFA3CFE82175C224407CA414BAEB37923B4D2D83134AE154E490A9B45A0563B06C953C3301450A2176A07C614A74E3478E48509F9A60AE945A8EBC7815121D90A3B0E07091A096CF02C57B25BCA58126AD0C629CE166A7EDB4B33221A0D3F72B85D562EC698B7D0A913D73806F1C5C87B38EC003CB303A3DC51B4B35356A67826D6EDAA8FEB93B98493B2D1C11B676A6AD9506A1AAAE13A824C7C08D1C6C2C4DBA9642C76EA7F6C8264B64A23CCCA9A74635FCBF03E00F1B5722B214376790793B2C4F0A13B5C40760B4218E1D2594DCB30A70D9C1782A5DD30576FA4144BFC8416EDA8118FC6472F56A979586F33BB070FB0F1B0B10BC4897EBE01BCA3893D4E16ADB25093A7417D0708C83A26322E22E6330091E30152BF823597C04CCF4CFC7331578F43A2726CCB428289A90C863259DD180C5FF142BEF41C7717094BE07856DA2B140FA67710967356AA47DFBC8D255B4722AB86D439B7E0A6090251D2D4C1ED5F20BBE6807BF65A90B7CB2EC0102AF02809DC9AC7D0A3ABC69C18365BCFF59185F33996887746185906C0191AED4407E139446459BE29C6822717644353D24AB6339156A9C424909F0A9025BB74720779BE43F16D81C8CC666E99710D8C68BB5CC4E12F314E925A551F09CC59003A1F88103C254BB978D75F394D3540E31E771CDA36E39EC54A62B5832664D821A72F1E6AFBBA27F84295B2694C498498E812BC8E9378FE541CEC5891B25062901CB7212E3CDC46179EC5BCEC10BC0B9311DE05074290687FD6A5392671654284CD9C8CC3EBA80EB3B662EB53EB75116704A1FEB5C2D056338532868DDF24EB8992AB8565D9E490CADF14804360DAA90718EAB616BAB0765D33987B47EFB6599C5563235E61E4BE670E97955AB292D9732CB8930948AC82DF230AC72297A23679D6B94C17F1359483254FEDC2F05819F0D069A443B78E3FC6C3EF4714B05A3FCA81CBBA60242A7060CD885D8F39981BB18092B23DAA59FD9578388688A09BBA079BC809A54843A60385E2310BBCBCC0213CE3DFAAB33B47F9D6305BC95C6107813C585C4B657BF30542833B14949F573C0612AD524BAAE69590C1277B86C286571BF66B3CFF46A3858C09906A794DF4A06E9D4B0A2E43F10F72A6C6C47E5646E2C799B71C33ED2F01EEB45938EB7A4E2E2908C53558A540D350369FA189C616943F7981D7618CF02A5B0A2BCC422E857D1A47871253D08293C1C179BCDC0437069107418205FDB9856623B8CA6B694C96C084B17F13BB6DF12B2CFBBC2B0E0C34B00D0FCD0AECFB27924F6984E747BE2A09D83A8664590A8077331491A4F7D720843F23E652C6FA840308DB4020337AAD37967034A9FB523B67CA70330F02D9EA20C1E84CB8E5757C9E1896B60581441ED618AA5B26DA56C0A5A73C4DCFD755E610B4FC81FF84E21",
300        gen_dk: "8C8B3722A82E550565521611EBBC63079944C9B1ABB3B0020FF12F631891A9C468D3A67BF6271280DA58D03CB042B3A461441637F929C273469AD15311E910DE18CB9537BA1BE42E98BB59E498A13FD440D0E69EE832B45CD95C382177D67096A18C07F1781663651BDCAC90DEDA3DDD143485864181C91FA2080F6DAB3F86204CEB64A7B4446895C03987A031CB4B6D9E0462FDA829172B6C012C638B29B5CD75A2C930A5596A3181C33A22D574D30261196BC350738D4FD9183A763336243ACED99B3221C71D8866895C4E52C119BF3280DAF80A95E15209A795C4435FBB3570FDB8AA9BF9AEFD43B094B781D5A81136DAB88B8799696556FEC6AE14B0BB8BE4695E9A124C2AB8FF4AB1229B8AAA8C6F41A60C34C7B56182C55C2C685E737C6CA00A23FB8A68C1CD61F30D3993A1653C1675AC5F0901A7160A73966408B8876B715396CFA4903FC69D60491F8146808C97CD5C533E71017909E97B835B86FF847B42A696375435E006061CF7A479463272114A89EB3EAF2246F0F8C104A14986828E0AD20420C9B37EA23F5C514949E77AD9E9AD12290DD1215E11DA274457AC86B1CE6864B122677F3718AA31B02580E64317178D38F25F609BC6C55BC374A1BF78EA8ECC219B30B74CBB3272A599238C93985170048F176775FB19962AC3B135AA59DB104F7114DBC2C2D42949ADECA6A85B323EE2B2B23A77D9DB235979A8E2D67CF7D2136BBBA71F269574B38888E1541340C19284074F9B7C8CF37EB01384E6E3822EC4882DFBBEC4E6098EF2B2FC177A1F0BCB65A57FDAA89315461BEB7885FB68B3CD096EDA596AC0E61DD7A9C507BC6345E0827DFCC8A3AC2DCE51AD731AA0EB932A6D0983992347CBEB3CD0D9C9719797CC21CF0062B0AD94CAD734C63E6B5D859CBE19F0368245351BF464D7505569790D2BB724D8659A9FEB1C7C473DC4D061E29863A2714BAC42ADCD1A8372776556F7928A7A44E94B6A25322D03C0A1622A7FD261522B7358F085BDFB60758762CB901031901B5EECF4920C81020A9B1781BCB9DD19A9DFB66458E7757C52CEC75B4BA740A24099CB56BB60A76B6901AA3E0169C9E83496D73C4C99435A28D613E97A1177F58B6CC595D3B2331E9CA7B57B74DC2C5277D26F2FE19240A55C35D6CFCA26C73E9A2D7C980D97960AE1A04698C16B398A5F20C35A0914145CE1674B71ABC6066A909A3E4B911E69D5A849430361F731B07246A6329B52361904225082D0AAC5B21D6B34862481A890C3C360766F04263603A6B73E802B1F70B2EB00046836B8F493BF10B90B8737C6C548449B294C47253BE26CA72336A632063AD3D0B48C8B0F4A34447EF13B764020DE739EB79ABA20E2BE1951825F293BEDD1089FCB0A91F560C8E17CDF52541DC2B81F972A7375B201F10C08D9B5BC8B95100054A3D0AAFF89BD08D6A0E7F2115A435231290460C9AD435A3B3CF35E52091EDD1890047BCC0AABB1ACEBC75F4A32BC1451ACC4969940788E89412188946C9143C5046BD1B458DF617C5DF533B052CD6038B7754034A23C2F7720134C7B4EACE01FAC0A2853A9285847ABBD06A3343A778AC6062E458BC5E61ECE1C0DE0206E6FE8A84034A7C5F1B005FB0A584051D3229B86C909AC5647B3D75569E05A88279D80E5C30F574DC327512C6BBE8101239EC62861F4BE67B05B9CDA9C545C13E7EB53CFF260AD9870199C21F8C63D64F0458A7141285023FEB829290872389644B0C3B73AC2C8E121A29BB1C43C19A233D56BED82740EB021C97B8EBBA40FF328B541760FCC372B52D3BC4FCBC06F424EAF253804D4CB46F41FF254C0C5BA483B44A87C219654555EC7C163C79B9CB760A2AD9BB722B93E0C28BD4B1685949C496EAB1AFF90919E3761B346838ABB2F01A91E554375AFDAAAF3826E6DB79FE7353A7A578A7C0598CE28B6D9915214236BBFFA6D45B6376A07924A39A7BE818286715C8A3C110CD76C02E0417AF138BDB95C3CCA798AC809ED69CFB672B6FDDC24D89C06A6558814AB0C21C62B2F84C0E3E0803DB337A4E0C7127A6B4C8C08B1D1A76BF07EB6E5B5BB47A16C74BC548375FB29CD789A5CFF91BDBD071859F4846E355BB0D29484E264DFF36C9177A7ACA78908879695CA87F25436BC12630724BB22F0CB64897FE5C41195280DA04184D4BC7B532A0F70A54D7757CDE6175A6843B861CB2BC4830C0012554CFC5D2C8A2027AA3CD967130E9B96241B11C4320C7649CC23A71BAFE691AFC08E680BCEF42907000718E4EACE8DA28214197BE1C269DA9CB541E1A3CE97CFADF9C6058780FE6793DBFA8218A2760B802B8DA2AA271A38772523A76736A7A31B9D3037AD21CEBB11A472B8792EB17558B940E70883F264592C689B240BB43D5408BF446432F412F4B9A5F6865CC252A43CF40A320391555591D67561FDD05353AB6B019B3A08A73353D51B6113AB2FA51D975648EE254AF89A230504A236A4658257740BDCBBE1708AB022C3C588A410DB3B9C308A06275BDF5B4859D3A2617A295E1A22F90198BAD0166F4A943417C5B831736CB2C8580ABFDE5714B586ABEEC0A175A08BC710C7A2895DE93AC438061BF7765D0D21CD418167CAF89D1EFC3448BCBB96D69B3E010C82D15CAB6CACC6799D3639669A5B21A633C865F8593B5B7BC800262BB837A924A6C5440E4FC73B41B23092C3912F4C6BEBB4C7B4C62908B03775666C22220DF9C88823E344C7308332345C8B795D34E8C051F21F5A21C214B69841358709B1C305B32CC2C3806AE9CCD3819FFF4507FE520FBFC27199BC23BE6B9B2D2AC1717579AC769279E2A7AAC68A371A47BA3A7DBE016F14E1A727333663C4A5CD1A0F8836CF7B5C49AC51485CA60345C990E06888720003731322C5B8CD5E6907FDA1157F468FD3FC20FA8175EEC95C291A262BA8C5BE990872418930852339D88A19B37FEFA3CFE82175C224407CA414BAEB37923B4D2D83134AE154E490A9B45A0563B06C953C3301450A2176A07C614A74E3478E48509F9A60AE945A8EBC7815121D90A3B0E07091A096CF02C57B25BCA58126AD0C629CE166A7EDB4B33221A0D3F72B85D562EC698B7D0A913D73806F1C5C87B38EC003CB303A3DC51B4B35356A67826D6EDAA8FEB93B98493B2D1C11B676A6AD9506A1AAAE13A824C7C08D1C6C2C4DBA9642C76EA7F6C8264B64A23CCCA9A74635FCBF03E00F1B5722B214376790793B2C4F0A13B5C40760B4218E1D2594DCB30A70D9C1782A5DD30576FA4144BFC8416EDA8118FC6472F56A979586F33BB070FB0F1B0B10BC4897EBE01BCA3893D4E16ADB25093A7417D0708C83A26322E22E6330091E30152BF823597C04CCF4CFC7331578F43A2726CCB428289A90C863259DD180C5FF142BEF41C7717094BE07856DA2B140FA67710967356AA47DFBC8D255B4722AB86D439B7E0A6090251D2D4C1ED5F20BBE6807BF65A90B7CB2EC0102AF02809DC9AC7D0A3ABC69C18365BCFF59185F33996887746185906C0191AED4407E139446459BE29C6822717644353D24AB6339156A9C424909F0A9025BB74720779BE43F16D81C8CC666E99710D8C68BB5CC4E12F314E925A551F09CC59003A1F88103C254BB978D75F394D3540E31E771CDA36E39EC54A62B5832664D821A72F1E6AFBBA27F84295B2694C498498E812BC8E9378FE541CEC5891B25062901CB7212E3CDC46179EC5BCEC10BC0B9311DE05074290687FD6A5392671654284CD9C8CC3EBA80EB3B662EB53EB75116704A1FEB5C2D056338532868DDF24EB8992AB8565D9E490CADF14804360DAA90718EAB616BAB0765D33987B47EFB6599C5563235E61E4BE670E97955AB292D9732CB8930948AC82DF230AC72297A23679D6B94C17F1359483254FEDC2F05819F0D069A443B78E3FC6C3EF4714B05A3FCA81CBBA60242A7060CD885D8F39981BB18092B23DAA59FD9578388688A09BBA079BC809A54843A60385E2310BBCBCC0213CE3DFAAB33B47F9D6305BC95C6107813C585C4B657BF30542833B14949F573C0612AD524BAAE69590C1277B86C286571BF66B3CFF46A3858C09906A794DF4A06E9D4B0A2E43F10F72A6C6C47E5646E2C799B71C33ED2F01EEB45938EB7A4E2E2908C53558A540D350369FA189C616943F7981D7618CF02A5B0A2BCC422E857D1A47871253D08293C1C179BCDC0437069107418205FDB9856623B8CA6B694C96C084B17F13BB6DF12B2CFBBC2B0E0C34B00D0FCD0AECFB27924F6984E747BE2A09D83A8664590A8077331491A4F7D720843F23E652C6FA840308DB4020337AAD37967034A9FB523B67CA70330F02D9EA20C1E84CB8E5757C9E1896B60581441ED618AA5B26DA56C0A5A73C4DCFD755E610B4FC81FF84E21D2E574DFD8CD0AE893AA7E125B44B924F45223EC09F2AD1141EA93A68050DBF699E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7",
301        encap_ek: "307A4CEA4148219B958EA0B7886659235A4D1980B192610847D86EF32739F94C3B446C4D81D89B8B422A9D079C88B11ACAF321B014294E18B296E52F3F744CF9634A4FB01DB0D99EF20A633A552E76A0585C6109F018768B763AF3678B4780089C1342B96907A29A1C11521C744C2797D0BF2B9CCDCA614672B45076773F458A31EF869BE1EB2EFEB50D0E37495DC5CA55E07528934F6293C4168027D0E53D07FACC6630CB08197E53FB193A171135DC8AD9979402A71B6926BCDCDC47B93401910A5FCC1A813B682B09BA7A72D2486D6C799516465C14729B26949B0B7CBC7C640F267FED80B162C51FD8E09227C101D505A8FAE8A2D7054E28A78BA8750DECF9057C83979F7ABB084945648006C5B28804F34E73B238111A65A1F500B1CC606A848F2859070BEBA7573179F36149CF5801BF89A1C38CC278415528D03BDB943F96280C8CC52042D9B91FAA9D6EA7BCBB7AB1897A3266966F78393426C76D8A49578B98B159EBB46EE0A883A270D8057CD0231C86906A91DBBADE6B2469581E2BCA2FEA8389F7C74BCD70961EA5B934FBCF9A6590BF86B8DB548854D9A3FB30110433BD7A1B659CA8568085639237B3BDC37B7FA716D482A25B54106B3A8F54D3AA99B5123DA96066904592F3A54EE23A7981AB608A2F4413CC658946C6D7780EA765644B3CC06C70034AB4EB351912E7715B56755D09021571BF340AB92598A24E811893195B96A1629F8041F58658431561FC0AB15292B913EC473F04479BC145CD4C563A286235646CD305A9BE1014E2C7B130C33EB77CC4A0D9786BD6BC2A954BF3005778F8917CE13789BBB962807858B67731572B6D3C9B4B5206FAC9A7C8961698D88324A915186899B29923F08442A3D386BD416BCC9A100164C930EC35EAFB6AB35851B6C8CE6377366A175F3D75298C518D44898933F53DEE617145093379C4659F68583B2B28122666BEC57838991FF16C368DD22C36E780C91A3582E25E19794C6BF2AB42458A8DD7705DE2C2AA20C054E84B3EF35032798626C248263253A71A11943571340A978CD0A602E47DEE540A8814BA06F31414797CDF6049582361BBABA387A83D89913FE4C0C112B95621A4BDA8123A14D1A842FB57B83A4FBAF33A8E552238A596AAE7A150D75DA648BC44644977BA1F87A4C68A8C4BD245B7D00721F7D64E822B085B901312EC37A8169802160CCE1160F010BE8CBCACE8E7B005D7839234A707868309D03784B4273B1C8A160133ED298184704625F29CFA086D13263EE5899123C596BA788E5C54A8E9BA829B8A9D904BC4BC0BBEA76BC53FF811214598472C9C202B73EFF035DC09703AF7BF1BABAAC73193CB46117A7C9492A43FC95789A924C5912787B2E2090EBBCFD3796221F06DEBF9CF70E056B8B9161D6347F47335F3E1776DA4BB87C15CC826146FF0249A413B45AA93A805196EA453114B524E310AEDAA46E3B99642368782566D049A726D6CCA910993AED621D0149EA588A9ABD909DBB69AA22829D9B83ADA2209A6C2659F2169D668B9314842C6E22A74958B4C25BBDCD293D99CB609D866749A485DFB56024883CF5465DBA0363206587F45597F89002FB8607232138E03B2A894525F265370054B48863614472B95D0A2303442E378B0DD1C75ACBAB971A9A8D1281C79613ACEC6933C377B3C578C2A61A1EC181B101297A37CC5197B2942F6A0E4704C0EC63540481B9F159DC255B59BB55DF496AE54217B7689BD51DBA0383A3D72D852FFCA76DF05B66EECCBD47BC53040817628C71E361D6AF889084916B408A466C96E7086C4A60A10FCF7537BB94AFBCC7D437590919C28650C4F2368259226A9BFDA3A3A0BA1B5087D9D76442FD786C6F81C68C0360D7194D7072C4533AEA86C2D1F8C0A27696066F6CFD11003F797270B32389713CFFA093D991B63844C385E72277F166F5A3934D6BB89A4788DE28321DEFC7457AB484BD30986DC1DAB3008CD7B22F69702FABB9A1045407DA4791C3590FF599D81D688CFA7CC12A68C50F51A1009411B44850F9015DC84A93B17C7A207552C661EA9838E31B95EAD546248E56BE7A5130505268771199880A141771A9E47ACFED590CB3AA7CB7C5F74911D8912C29D6233F4D53BC64139E2F55BE75507DD77868E384AEC581F3F411DB1A742972D3EBFD3315C84A5AD63A0E75C8BCA3E3041E05D9067AFF3B1244F763E7983",
302        encap_dk: "673751CBB596541131C66398662CB4B0EB80796A88B28144A5BBC854F80D4B35BE0AB241E4795F8FBBA814F50FA80498CBE8BF68A0A583A4C5981B41DF0667DB614A628C3060697438E62C8D36026EE29C96B673BF1A194EE49481351F4D1748DD01CD023142F01057142B741CBA8302E432F88C63D0B4B5767AC3A5A59AFA3A321E65B1D1511807A06E16A04B2F1070E465586D4A9B68E2B42D57A356FA7BB3D04E51B193FF4C757CFA0F15924EA6E49AFB83B2919C985869ADA544338F44AE96A874C425AF87BC73F3CB0FD2627B1539B1F19A77E36B7FC817851D39BD8A069A6C2202C17469D421A588E65DAF450030B6674EC1C734AA25414B119E61B26EFC90DF81059D2B9599414F93692BF45A4B1C5CC09EDB37B1B1433026AEA6B0200722B819C7BC061C53A4304992FCA2AEE2324A324AB91C3E5D562096B8A141756940F15A2800C274EA4F65817E639C5D2A278C6A294F9DB331F84CCB0A10309F530A06EB962573C86005C15BFC7531A143026396721297E25CB655A294964B2FE531905F2802376B8ACE35AE3E2814BAB7062BC1A840657DBFCB5F41BB55475697849A31E2222E995518CA7640AD4B9CEE9820984138BE0510FFD6AC225393A5F0CB030528CD2A0610E78A5CF1B073039A6D143068C53DBD15A1D4446DA7B310EE795D1FB31B2F97008F83BDF348A593A3BDCBB571907B36D0978162C253E6F50106C463149834ABFB0707D8AB4A4BABC323598A085B309764B7C32C9DB0C9F2D52EF2F00BACE7846868C33B82AFA430A4C2F67B698A60526A161CD62115DCA767C203E3E2CC787031A73B5B7DBA1EEE5AB04B77BB569B952D9A15D198779804197D23C18E5B055F5C8087D742F64418D6505E70418ABFC6B1BF7BB3DE286599F4676CF87946D65144998AFAE1C689449E3F349FD0809AFB856DDE4A94A2C0258D56432F40C3DA812D3FD3B72259A61D2882E0F50B355121E564C6BD33366F32BF4A5996B9998961354925A2BACDF48056118453AC3792A7879B71579ADB65F5D83B1ED6C8C49836DE379DAA027E62B96F683C1688935CB3FCCD64329267273E60C6CD59BA1B7FC911E2662527ECCB7A474E5EF00CA9F789A3838E889242E7FB2B08F3790613C4EED3C912EC4EB029B971096B384727697B4DDC3B698C9A6DA6971FA4C574ECD18EB1C84C0C5790153AA6B9DB61D8BAC0A680A37ED623582A7E8C0885EBB35AF341477764368E0647B14553672316D0B90317C5B53AA747E61B4750DB9E63CC3712900005CA24226B523E0A179582C85968C107857BB41521B7342B13DCAC462A53BE38446F2142519667B48B1C68FCAFA4D3C7E3E5AFF163C41F2C1B4DBAC5456C30776078E7C3A713819F6B9ACA55D77D60637183A723035730F94285C42AC3587637F66AC30F2C4039E60420967576E27B96C8C004D9585F33939AC44F0D195B35D472FC219076F12D0984AC844728D5D2266BB5CD8B325DDA497B4F397BFE722C9D7684201A921F502271985CB3F31C04884C090B063631253DC454537031F2C82C10A1722DE6C556464DC9D64389DA37E469480C921065C79A30C83C867C952B30548A6B5BDFEB6EA6247480F163B427B17CF94889220FE934564DAB90F5B6A11648870B654495A6691AE21FEA86BDC8C49093FA07E926AF3ABA0E7CEC21F613B49986C6C8A139EDA70B7ED8211A3215E8C43EF8C151AE61740EF83B48276033614B58E9CEB992233CD21DFF70C7A6F7171707A2ADD37ACBF136A4EB4A79517FD0C8AFF0B5126435C3100331F208A546C9A4044A8F0503C8ADE9506A018B4CA7C6E8D70120017D38B13B52786A85A540D81B8E71C376B796A7215ABF065086D3C80EE94B8F09E2A3BA13B82583B825388E87BA010AF507173563789A1DCD088907C52BD7FC1C6930605F060F37978211C10FB5717E3FA291D20B5D43FB74CD4711394B0027E41C52B523797470532CBE123C92950720E5E255256577D4E156EBD4C698D813405C61430B978694ACDE78031E74BA1D8517DAE2346F008411231FCCE7BFF75BC361E691E776049004097B36490D876288701B2D3A1743AB8753D47AC6200E2DA7458D3A059681233872794E6720186B20108B1D1033971CE19ED67A2A28E499A360A4AD86AE4194034F202F8FA3626FE75F307A4CEA4148219B958EA0B7886659235A4D1980B192610847D86EF32739F94C3B446C4D81D89B8B422A9D079C88B11ACAF321B014294E18B296E52F3F744CF9634A4FB01DB0D99EF20A633A552E76A0585C6109F018768B763AF3678B4780089C1342B96907A29A1C11521C744C2797D0BF2B9CCDCA614672B45076773F458A31EF869BE1EB2EFEB50D0E37495DC5CA55E07528934F6293C4168027D0E53D07FACC6630CB08197E53FB193A171135DC8AD9979402A71B6926BCDCDC47B93401910A5FCC1A813B682B09BA7A72D2486D6C799516465C14729B26949B0B7CBC7C640F267FED80B162C51FD8E09227C101D505A8FAE8A2D7054E28A78BA8750DECF9057C83979F7ABB084945648006C5B28804F34E73B238111A65A1F500B1CC606A848F2859070BEBA7573179F36149CF5801BF89A1C38CC278415528D03BDB943F96280C8CC52042D9B91FAA9D6EA7BCBB7AB1897A3266966F78393426C76D8A49578B98B159EBB46EE0A883A270D8057CD0231C86906A91DBBADE6B2469581E2BCA2FEA8389F7C74BCD70961EA5B934FBCF9A6590BF86B8DB548854D9A3FB30110433BD7A1B659CA8568085639237B3BDC37B7FA716D482A25B54106B3A8F54D3AA99B5123DA96066904592F3A54EE23A7981AB608A2F4413CC658946C6D7780EA765644B3CC06C70034AB4EB351912E7715B56755D09021571BF340AB92598A24E811893195B96A1629F8041F58658431561FC0AB15292B913EC473F04479BC145CD4C563A286235646CD305A9BE1014E2C7B130C33EB77CC4A0D9786BD6BC2A954BF3005778F8917CE13789BBB962807858B67731572B6D3C9B4B5206FAC9A7C8961698D88324A915186899B29923F08442A3D386BD416BCC9A100164C930EC35EAFB6AB35851B6C8CE6377366A175F3D75298C518D44898933F53DEE617145093379C4659F68583B2B28122666BEC57838991FF16C368DD22C36E780C91A3582E25E19794C6BF2AB42458A8DD7705DE2C2AA20C054E84B3EF35032798626C248263253A71A11943571340A978CD0A602E47DEE540A8814BA06F31414797CDF6049582361BBABA387A83D89913FE4C0C112B95621A4BDA8123A14D1A842FB57B83A4FBAF33A8E552238A596AAE7A150D75DA648BC44644977BA1F87A4C68A8C4BD245B7D00721F7D64E822B085B901312EC37A8169802160CCE1160F010BE8CBCACE8E7B005D7839234A707868309D03784B4273B1C8A160133ED298184704625F29CFA086D13263EE5899123C596BA788E5C54A8E9BA829B8A9D904BC4BC0BBEA76BC53FF811214598472C9C202B73EFF035DC09703AF7BF1BABAAC73193CB46117A7C9492A43FC95789A924C5912787B2E2090EBBCFD3796221F06DEBF9CF70E056B8B9161D6347F47335F3E1776DA4BB87C15CC826146FF0249A413B45AA93A805196EA453114B524E310AEDAA46E3B99642368782566D049A726D6CCA910993AED621D0149EA588A9ABD909DBB69AA22829D9B83ADA2209A6C2659F2169D668B9314842C6E22A74958B4C25BBDCD293D99CB609D866749A485DFB56024883CF5465DBA0363206587F45597F89002FB8607232138E03B2A894525F265370054B48863614472B95D0A2303442E378B0DD1C75ACBAB971A9A8D1281C79613ACEC6933C377B3C578C2A61A1EC181B101297A37CC5197B2942F6A0E4704C0EC63540481B9F159DC255B59BB55DF496AE54217B7689BD51DBA0383A3D72D852FFCA76DF05B66EECCBD47BC53040817628C71E361D6AF889084916B408A466C96E7086C4A60A10FCF7537BB94AFBCC7D437590919C28650C4F2368259226A9BFDA3A3A0BA1B5087D9D76442FD786C6F81C68C0360D7194D7072C4533AEA86C2D1F8C0A27696066F6CFD11003F797270B32389713CFFA093D991B63844C385E72277F166F5A3934D6BB89A4788DE28321DEFC7457AB484BD30986DC1DAB3008CD7B22F69702FABB9A1045407DA4791C3590FF599D81D688CFA7CC12A68C50F51A1009411B44850F9015DC84A93B17C7A207552C661EA9838E31B95EAD546248E56BE7A5130505268771199880A141771A9E47ACFED590CB3AA7CB7C5F74911D8912C29D6233F4D53BC64139E2F55BE75507DD77868E384AEC581F3F411DB1A742972D3EBFD3315C84A5AD63A0E75C8BCA3E3041E05D9067AFF3B1244F763E7983D48BA34134BAB88D635D8CF8FF5D686058FA68B6C2FEEAA5FA4DE65757086C0125E937BCC0D02FAA8988AE7169DF07F6A771E6E7FE3AB65E965C63C3E40ED909",
303        m: "59C5154C04AE43AAFF32700F081700389D54BEC4C37C088B1C53F66212B12C72",
304        c: "E2D5FD4C13CEA0B52D874FEA9012F3A51743A1093710BBF23950F9147A472EE5533928A2F46D592F35DA8B4F758C893B0D7B98948BE447B17CB2AE58AF8A489DDD9232B99B1C0D2DE77CAA472BC3BBD4A7C60DBFDCA92EBF3A1CE1C22DAD13E887004E2924FD22656F5E508791DE06D85E1A1426808ED9A89F6E2FD3C245D4758B22B02CADE33B60FC889A33FC4447EDEBBFD4530DE86596A33789D5DBA6E6EC9F89879AF4BE4909A69017C9BB7A5E31815EA5F132EEC4984FAA7CCF594DD00D4D8487E45621AF8F6E330551439C93EC078A7A3CC1594AF91F8417375FD6088CEB5E85C67099091BAC11498A0D711455F5E0D95CD7BBE5CDD8FECB319E6853C23C9BE2C763DF578666C40A40A87486E46BA8716146192904510A6DC59DA8025825283D684DB91410B4F12C6D8FBD0ADD75D3098918CB04AC7BC4DB0D6BCDF1194DD86292E05B7B8630625B589CC509D215BBD06A2E7C66F424CDF8C40AC6C1E5AE6C964B7D9E92F95FC5C8852281628B81B9AFABC7F03BE3F62E8047BB88D01C68687B8DD4FE63820062B6788A53729053826ED3B7C7EF8241E19C85117B3C5341881D4F299E50374C8EEFD5560BD18319A7963A3D02F0FBE84BC484B5A4018B97D274191C95F702BAB9B0D105FAF9FDCFF97E437236567599FAF73B075D406104D403CDF81224DA590BEC2897E30109E1F2E5AE4610C809A73F638C84210B3447A7C8B6DDDB5AE200BF20E2FE4D4BA6C6B12767FB8760F66C5118E7A9935B41C9A471A1D3237688C1E618CC3BE936AA3F5E44E086820B810E063211FC21C4044B3AC4D00DF1BCC7B24DC07BA48B23B0FC12A3ED3D0A5CF7671415AB9CF21286FE63FB41418570555D4739B88104A8593F293025A4E3EE7C67E4B48E40F6BA8C09860C3FBBE55D45B45FC9AB629B17C276C9C9E2AF3A043BEAFC18FD4F25EE7F83BDDCD2D93914B7ED4F7C9AF127F3F15C277BE16551FEF3AE03D7B9143F0C9C019AB97EEA076366131F518363711B34E96D3F8A513F3E20B1D452C4B7AE3B975EA94D880DAC6693399750D02220403F0D3E3FC1172A4DE9DC280EAF0FEE2883A6660BF5A3D246FF41D21B36EA521CF7AA689F800D0F86F4FA1057D8A13F9DA8FFFD0DC1FAD3C04BB1CCCB7C834DB051A7AC2E4C60301996C93071EA416B421759935659CF62CA5F13AE07C3B195C148159D8BEB03D440B00F5305765F20C0C46EEE59C6D16206402DB1C715E888BDE59C781F35A7CC7C1C5ECB2155AE3E959C0964CC1EF8D7C69D1458A9A42F95F4C6B5B996345712AA290FBBF7DFD4A6E86463022A3F4725F6511BF7EA5E95C707CD3573609AADEAF540152C495F37FE6EC8BB9FA2AA61D15735934F4737928FDE90BA995722465D4A64505A5201F07AA58CFD8AE226E02070B2DBF512B975319A7E8753B4FDAE0EB4922869CC8E25C4A5560C2A0685DE3AC392A8925BA882004894742E43CCFC277439EC8050A9AEB42932E01C840DFCEDCC34D3991289A62C17D1284C839514B93351DBB2DDA81F924565D70E7079D5B8126CAAB7A4A1C731655A53BCC09F5D63EC9086DEA650055985EDFA8297D9C95410C5D1894D17D5930549ADBC2B8733C99FE62E17C4DE34A5D89B12D18E42A422D2CE779C2C28EB2D98003D5CD323FCBECF02B5066E0E734810F09ED89013C00F011BD220F2E5D6A362DF90599198A093B03C8D8EFBFE0B617592FAF1E64220C4440B53FFB47164F369C95290BA9F3108D686C57DB645C53C012E57AF25BD6693E2CC6B57651AF1591FE5D8916640EC017C253DF0606BB6B3035FAE748F3D4034223B1B5EFBF5283E778C1094291CF7B19BE0F317350E6F8518FDE0EFB1381FB6E16C241F7F17A5210693A274159E7FAC868CD0DC4359C3D9EEFEA0D9E31E43FA651392C65A543A59B3EEE3A639DC9417D056A5FF0F160BEEE2EAC29A7D88C0982CF70B5A46379F21E506AAC61A9BB1B8C2B9DAB0E44A823B61D0AA11D94F76A4A8E21F9D4280683208F4EA911116F6FD6A97426934EC3426B8C8F703DA85E9DCF99336136003728B8ECDD04A389F6A817A78BFA61BA46020BF3C34829508F9D06D1553CD987AAC380D86F168843BA3904DE5F7058A41B4CD388BC9CE3ABA7EE7139B7FC9E5B8CFAAA38990BD4A5DB32E2613E7EC4F5F8B1292A38C6F4FF5A40490D76B126652FCF86E245235D636C65CD102B01E22781A72918C",
305        k: "7264BDE5C6CEC14849693E2C3C86E48F80958A4F6186FC69333A4148E6E497F3",
306    };
307
308    /// 断言字节序列的十六进制等于向量值(ACVP 向量为大写,本库编码为小写)。
309    fn assert_hex(bytes: &[u8], expected: &str) {
310        assert_eq!(hex_encode(bytes), expected.to_ascii_lowercase());
311    }
312
313    fn b32(hex: &str) -> B32 {
314        B32::try_from(hex_decode(hex).unwrap().as_slice()).unwrap()
315    }
316
317    /// 从种子确定性生成密钥对,与向量逐字节一致。
318    fn keygen_kat<K: KemCore>(kat: &Kat) {
319        let (dk, ek) = K::generate_deterministic(&b32(kat.d), &b32(kat.z));
320        assert_hex(&ek.as_bytes(), kat.gen_ek);
321        assert_hex(&dk.as_bytes(), kat.gen_dk);
322    }
323
324    /// 确定性封装:同一 (ek, m) 得到向量中的 (c, k)。
325    fn encapsulation_kat<K: KemCore>(kat: &Kat) {
326        let ek = K::EncapsulationKey::from_bytes(
327            &parse_encoded::<K::EncapsulationKey>(kat.encap_ek, "KAT").unwrap(),
328        );
329        let (c, k) = ek.encapsulate_deterministic(&b32(kat.m)).unwrap();
330        assert_hex(&c, kat.c);
331        assert_hex(&k, kat.k);
332    }
333
334    /// 解封装:向量中的 (dk, c) 得到向量中的 k。
335    fn decapsulation_kat<K: KemCore>(kat: &Kat) {
336        let dk = K::DecapsulationKey::from_bytes(
337            &parse_encoded::<K::DecapsulationKey>(kat.encap_dk, "KAT").unwrap(),
338        );
339        let c = parse_ciphertext::<K>(kat.c, "KAT").unwrap();
340        let k = dk.decapsulate(&c).unwrap();
341        assert_hex(&k, kat.k);
342    }
343
344    #[test]
345    fn acvp_keygen_kat() {
346        keygen_kat::<MlKem512>(&KAT_512);
347        keygen_kat::<MlKem768>(&KAT_768);
348        keygen_kat::<MlKem1024>(&KAT_1024);
349    }
350
351    #[test]
352    fn acvp_encapsulation_kat() {
353        encapsulation_kat::<MlKem512>(&KAT_512);
354        encapsulation_kat::<MlKem768>(&KAT_768);
355        encapsulation_kat::<MlKem1024>(&KAT_1024);
356    }
357
358    #[test]
359    fn acvp_decapsulation_kat() {
360        decapsulation_kat::<MlKem512>(&KAT_512);
361        decapsulation_kat::<MlKem768>(&KAT_768);
362        decapsulation_kat::<MlKem1024>(&KAT_1024);
363    }
364
365    /// 三参数集 roundtrip:封装端共享密钥 == 解封装端共享密钥;随机源生效。
366    #[test]
367    fn roundtrip_all_parameter_sets() {
368        roundtrip(&MlKem512Kem::new(), "ml-kem-512", 1600, 3264, 1536);
369        roundtrip(&MlKem768Kem::new(), "ml-kem-768", 2368, 4800, 2176);
370        roundtrip(&MlKem1024Kem::new(), "ml-kem-1024", 3136, 6336, 3136);
371    }
372
373    fn roundtrip(
374        kem: &impl KeyEncapsulation,
375        identifier: &str,
376        ek_len: usize,
377        dk_len: usize,
378        ct_len: usize,
379    ) {
380        assert_eq!(kem.identifier(), identifier);
381
382        // generate 的公钥能被 encapsulate、私钥能被 decapsulate。
383        let (ek, dk) = kem.generate().unwrap();
384        assert_eq!(ek.len(), ek_len);
385        assert_eq!(dk.len(), dk_len);
386
387        let (ct, sender) = kem.encapsulate(&ek).unwrap();
388        assert_eq!(ct.len(), ct_len);
389        assert_eq!(sender.len(), 64);
390        assert_eq!(kem.decapsulate(&ct, &dk).unwrap(), sender);
391
392        // 两次封装的密文与共享密钥互不相同(m 每次取自系统 CSPRNG)。
393        let (ct2, sender2) = kem.encapsulate(&ek).unwrap();
394        assert_ne!(ct, ct2);
395        assert_ne!(sender, sender2);
396    }
397
398    /// 隐式拒绝(FIPS 203 §7.3):密文被篡改后解封装**成功返回**,但共享密钥不同。
399    #[test]
400    fn tampered_ciphertext_is_implicitly_rejected() {
401        let kem = MlKem768Kem::new();
402        let (ek, dk) = kem.generate().unwrap();
403        let (ct, sender) = kem.encapsulate(&ek).unwrap();
404
405        let mut tampered = ct.into_bytes();
406        let last = tampered.len() - 1;
407        tampered[last] = if tampered[last] == b'0' { b'1' } else { b'0' };
408        let tampered = String::from_utf8(tampered).unwrap();
409
410        let receiver = kem.decapsulate(&tampered, &dk).unwrap();
411        assert_eq!(receiver.len(), 64);
412        assert_ne!(receiver, sender);
413    }
414
415    /// 私钥与公钥不配对同属隐式拒绝:解封装成功,但共享密钥与封装端不同。
416    #[test]
417    fn wrong_private_key_is_implicitly_rejected() {
418        let kem = MlKem512Kem::new();
419        let (ek, _dk) = kem.generate().unwrap();
420        let (_other_ek, other_dk) = kem.generate().unwrap();
421        let (ct, sender) = kem.encapsulate(&ek).unwrap();
422
423        let receiver = kem.decapsulate(&ct, &other_dk).unwrap();
424        assert_ne!(receiver, sender);
425    }
426
427    /// 畸形输入:hex 非法 → InvalidHex;密钥长度不符 → InvalidKey;密文长度不符 → InvalidKeyLength。
428    #[test]
429    fn malformed_inputs_are_rejected() {
430        const LABEL: &str = "ML-KEM-768";
431        let kem = MlKem768Kem::new();
432        let (ek, dk) = kem.generate().unwrap();
433        let (ct, _) = kem.encapsulate(&ek).unwrap();
434
435        // 十六进制非法(含非十六进制字符 / 奇数长度)。
436        assert_eq!(kem.encapsulate("zz").unwrap_err(), Error::InvalidHex);
437        assert_eq!(
438            kem.encapsulate(&ek[..ek.len() - 1]).unwrap_err(),
439            Error::InvalidHex
440        );
441        assert_eq!(kem.decapsulate("xyz", &dk).unwrap_err(), Error::InvalidHex);
442        assert_eq!(kem.decapsulate(&ct, "abc").unwrap_err(), Error::InvalidHex);
443
444        // 密钥长度不符(十六进制合法,字节数不对)。
445        assert_eq!(
446            kem.encapsulate("").unwrap_err(),
447            Error::InvalidKey { label: LABEL }
448        );
449        assert_eq!(
450            kem.encapsulate(&ek[..2]).unwrap_err(),
451            Error::InvalidKey { label: LABEL }
452        );
453        let mut longer = dk.clone();
454        longer.push_str("ab");
455        assert_eq!(
456            kem.decapsulate(&ct, &longer).unwrap_err(),
457            Error::InvalidKey { label: LABEL }
458        );
459
460        // 密文长度不符(十六进制合法)。
461        assert_eq!(
462            kem.decapsulate(&ct[..2], &dk).unwrap_err(),
463            Error::InvalidKeyLength {
464                label: "ML-KEM-768 ciphertext",
465                expected: 1088,
466                got: 1,
467            }
468        );
469    }
470
471    /// 隐式拒绝的强度:不只末位 nibble——中段篡改与全随机密文同样「成功返回但密钥不同」。
472    #[test]
473    fn arbitrary_ciphertext_corruption_is_implicitly_rejected() {
474        use rand_core::RngCore;
475
476        let kem = MlKem768Kem::new();
477        let (ek, dk) = kem.generate().unwrap();
478        let (ct, sender) = kem.encapsulate(&ek).unwrap();
479
480        // 中段一字节翻转。
481        let mut mid = ct.clone().into_bytes();
482        let mid_idx = mid.len() / 2;
483        mid[mid_idx] = if mid[mid_idx] == b'0' { b'1' } else { b'0' };
484        let mid = String::from_utf8(mid).unwrap();
485        let receiver = kem.decapsulate(&mid, &dk).unwrap();
486        assert_eq!(receiver.len(), 64);
487        assert_ne!(receiver, sender);
488
489        // 同长度全随机密文:长度合法 → 走隐式拒绝路径(Ok 且密钥不同)。
490        let mut random = vec![0u8; ct.len() / 2];
491        OsRng.fill_bytes(&mut random);
492        let receiver_random = kem.decapsulate(&hex_encode(&random), &dk).unwrap();
493        assert_ne!(receiver_random, sender);
494    }
495
496    /// FIPS 203 §7.2 modulus check:ek 的 t̂ 系数 ≥ q 的非规范编码必须被拒——
497    /// 封装端与解封装端(dk 内嵌 ek)都要拦住。ml-kem 0.2.3 自身只查长度。
498    #[test]
499    fn non_canonical_ek_fails_modulus_check() {
500        const LABEL: &str = "ML-KEM-768";
501        let kem = MlKem768Kem::new();
502        let (ek, dk) = kem.generate().unwrap();
503
504        // 把 ek 的第一个 12 位系数改成 0xFFF(4095 ≥ q = 3329)。
505        let mut ek_bytes = hex_decode(&ek).unwrap();
506        ek_bytes[0] = 0xff;
507        ek_bytes[1] = 0xff;
508        ek_bytes[2] = 0xff;
509        assert_eq!(
510            kem.encapsulate(&hex_encode(&ek_bytes)).unwrap_err(),
511            Error::InvalidKey { label: LABEL }
512        );
513
514        // dk = dkPKE(1152) ‖ ek(1184) ‖ H(ek)(32) ‖ z(32):内嵌 ek 同样被检查。
515        let mut dk_bytes = hex_decode(&dk).unwrap();
516        let ek_offset = dk_bytes.len() - 64 - 1184;
517        dk_bytes[ek_offset] = 0xff;
518        dk_bytes[ek_offset + 1] = 0xff;
519        dk_bytes[ek_offset + 2] = 0xff;
520        let (ct, _) = kem.encapsulate(&ek).unwrap();
521        assert_eq!(
522            kem.decapsulate(&ct, &hex_encode(&dk_bytes)).unwrap_err(),
523            Error::InvalidKey { label: LABEL }
524        );
525    }
526
527    /// §7.3 hash check:dk 尾部存储的 h 与 H(内嵌 ek) 不符时必须拒绝
528    ///(ml-kem 0.2.3 不做此检查,本库补上)。
529    #[test]
530    fn corrupted_hash_in_dk_fails_hash_check() {
531        const LABEL: &str = "ML-KEM-768";
532        let kem = MlKem768Kem::new();
533        let (ek, dk) = kem.generate().unwrap();
534        let (ct, _) = kem.encapsulate(&ek).unwrap();
535
536        // dk = dkPKE ‖ ek ‖ h(32) ‖ z(32):翻转 h 的一个字节。
537        let mut dk_bytes = hex_decode(&dk).unwrap();
538        let h_idx = dk_bytes.len() - 64;
539        dk_bytes[h_idx] ^= 0x01;
540        assert_eq!(
541            kem.decapsulate(&ct, &hex_encode(&dk_bytes)).unwrap_err(),
542            Error::InvalidKey { label: LABEL }
543        );
544    }
545
546    /// 门面(KeyEncapsulationManager)按默认标识与显式标识两组方法工作。
547    #[test]
548    fn manager_roundtrip() {
549        let mut registry: Registry<Box<dyn KeyEncapsulation>> = Registry::new("key encapsulation");
550        registry
551            .register(Box::new(MlKem1024Kem::new()))
552            .register(Box::new(MlKem768Kem::new()));
553        let manager = KeyEncapsulationManager::new(registry, "ml-kem-1024").unwrap();
554
555        let (ek, dk) = manager.generate().unwrap();
556        let (ct, sender) = manager.encapsulate(&ek).unwrap();
557        assert_eq!(manager.decapsulate(&ct, &dk).unwrap(), sender);
558
559        // 显式指定另一实现。
560        let (ek768, dk768) = manager.generate_with("ml-kem-768").unwrap();
561        assert_eq!(ek768.len(), 2368);
562        let (ct768, sender768) = manager.encapsulate_with("ml-kem-768", &ek768).unwrap();
563        assert_eq!(
564            manager
565                .decapsulate_with("ml-kem-768", &ct768, &dk768)
566                .unwrap(),
567            sender768
568        );
569
570        // 未注册标识 → UnknownIdentifier。
571        assert_eq!(
572            manager.generate_with("ml-kem-999").unwrap_err(),
573            Error::UnknownIdentifier {
574                kind: "key encapsulation",
575                identifier: "ml-kem-999".to_string(),
576            }
577        );
578    }
579}