Skip to main content

ferritls_core/
sign.rs

1//! 数字签名:ECDSA(P-256/P-384,RFC 6979 确定性 nonce)、Ed25519
2//! (RFC 8032)、RSA(PKCS#1 v1.5 / PSS,M4b 落地)。
3//!
4//! 批准状态:ECDSA P-256/384 与 RSA 为 FIPS 批准;**Ed25519 非批准**
5//! (FIPS 186-5 不含 EdDSA)。
6//!
7//! **显式省略**:Ed448(需 Goldilocks 域 GF(2^448−2^224−1) 与
8//! SHAKE-256,域类型不存在)与 `ecdsa_secp521r1_sha512`(依赖 P-521,
9//! 见 [`crate::ecdh`] 省略注记)——均未进入原始里程碑范围,候选余项
10//! 出口条件见 docs/ROADMAP.md「M8 发布后方向」。
11//!
12//! 签名 API:`sign` 接收**未哈希**消息,内部按算法完成哈希(与 rustls
13//! `Signer::sign` 约定一致)。
14//!
15//! 向量:RFC 6979 A.2.5(P-256 "sample")、RFC 8032 §7.1(Ed25519
16//! TEST 1/2),人工录入并与官方原文核对;RSA 向量在 M4b。
17//!
18//! 安全:
19//! - ECDSA nonce 一律 RFC 6979 确定性生成(FIPS 186-5 允许);标量乘
20//!   经 ecdh 模块统一盲化;
21//! - 验证路径一切失败归一化为同一错误,不泄露失败阶段;
22//! - 私钥材料 ZeroizeOnDrop。
23
24use crate::fields::{Fp256Scalar, Fp384Scalar, Fp25519};
25use crate::sha2::Sha512;
26use std::sync::OnceLock;
27
28/// 最小长度 BE 整数的 DER INTEGER 编码。
29fn der_integer(value_be: &[u8]) -> Vec<u8> {
30    let mut m = value_be;
31    while m.len() > 1 && m[0] == 0 {
32        m = &m[1..];
33    }
34    let mut content = Vec::with_capacity(m.len() + 1);
35    if m[0] & 0x80 != 0 {
36        content.push(0x00);
37    }
38    content.extend_from_slice(m);
39    let mut out = Vec::with_capacity(content.len() + 2);
40    out.push(0x02);
41    out.push(content.len() as u8);
42    out.extend_from_slice(&content);
43    out
44}
45
46/// 编码 ECDSA-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER }。
47pub fn encode_der_sig(r_be: &[u8], s_be: &[u8]) -> Vec<u8> {
48    let r = der_integer(r_be);
49    let s = der_integer(s_be);
50    let mut out = Vec::with_capacity(r.len() + s.len() + 5);
51    out.push(0x30);
52    out.push((r.len() + s.len()) as u8);
53    out.extend_from_slice(&r);
54    out.extend_from_slice(&s);
55    out
56}
57
58/// 生成一条曲线的 ECDSA 模块。
59macro_rules! ecdsa_curve {
60    ($modname:ident, $curve:ident, $sfield:ident, $coordlen:expr, $hash:ident, $hmac:ident, $doc:expr) => {
61        #[doc = $doc]
62        pub mod $modname {
63            use super::*;
64            use crate::ecdh::$curve as crv;
65            use crate::hmac::$hmac;
66            use crate::sha2::$hash;
67
68            type S = $sfield;
69
70            const SEED_LEN: usize = $coordlen;
71            const HLEN: usize = $hmac::OUTPUT_LEN;
72
73            /// 私钥(模 n 规范标量,`ZeroizeOnDrop`)。
74            #[derive(Clone)]
75            pub struct SigningKey {
76                d: [u64; S::LIMBS],
77            }
78
79            impl SigningKey {
80                /// 本算法在 FIPS 140-3 下的批准状态。
81                pub const APPROVAL: crate::Approval = crate::Approval::Approved;
82
83                /// 由种子确定性构造(int2octets(x),mod n 归约)。
84                pub fn from_seed(seed: [u8; SEED_LEN]) -> Self {
85                    let d = S::from_bytes_be_mod(&seed);
86                    Self { d: d.to_raw() }
87                }
88
89                /// 公钥(未压缩 SEC1:0x04 || X || Y)。
90                pub fn public_key_sec1(&self) -> [u8; 1 + 2 * SEED_LEN] {
91                    let (x, y) = crv::mul_base(&self.d);
92                    let mut out = [0u8; 1 + 2 * SEED_LEN];
93                    out[0] = 0x04;
94                    out[1..1 + SEED_LEN].copy_from_slice(&x.to_bytes_be());
95                    out[1 + SEED_LEN..].copy_from_slice(&y.to_bytes_be());
96                    out
97                }
98
99                /// 对消息签名:返回 DER 编码的 ECDSA-Sig-Value。
100                /// nonce 按 RFC 6979 确定性生成。
101                pub fn sign(&self, message: &[u8]) -> Result<Vec<u8>, crate::Error> {
102                    let digest = $hash::one_shot(message);
103                    let z = S::from_bytes_be_mod(&digest);
104                    let d_m = S::from_raw(self.d);
105                    let x_oct = S::from_raw(self.d).to_bytes_be();
106                    let z_oct = z.to_bytes_be();
107
108                    // RFC 6979 §3.2 步骤 b–g:V = 0x01^hlen,K = 0x00^hlen;
109                    // K = HMAC_K(V || {0x00,0x01} || int2octets(x) || bits2octets(h1)),
110                    // 每次 K 更新后先 V = HMAC_K(V)。两次输入仅分隔字节不同,复用 buf。
111                    let mut v = [0x01u8; HLEN];
112                    let mut k = [0u8; HLEN];
113                    let mut buf = [0u8; HLEN + 1 + 2 * SEED_LEN];
114                    buf[..HLEN].copy_from_slice(&v);
115                    buf[HLEN] = 0x00;
116                    buf[HLEN + 1..HLEN + 1 + SEED_LEN].copy_from_slice(&x_oct);
117                    buf[HLEN + 1 + SEED_LEN..].copy_from_slice(&z_oct);
118                    k = $hmac::one_shot(&k, &buf); // d
119                    v = $hmac::one_shot(&k, &v); // e
120                    buf[..HLEN].copy_from_slice(&v); // f 必须用更新后的 V
121                    buf[HLEN] = 0x01;
122                    k = $hmac::one_shot(&k, &buf); // f
123                    v = $hmac::one_shot(&k, &v); // g
124
125                    loop {
126                        // h:V = HMAC_K(V);候选 k = bits2int(V)——按 RFC 与 q
127                        // 比较拒绝(不取模);k = 0(V 全零)同样拒绝。
128                        v = $hmac::one_shot(&k, &v);
129                        let n_be = n_bytes_be();
130                        let mut ge_n = false;
131                        for i in 0..SEED_LEN {
132                            if v[i] < n_be[i] {
133                                break;
134                            }
135                            if v[i] > n_be[i] {
136                                ge_n = true;
137                                break;
138                            }
139                        }
140                        let mut nonzero = false;
141                        for &b in &v {
142                            if b != 0 {
143                                nonzero = true;
144                                break;
145                            }
146                        }
147                        let k_s = S::from_bytes_be_mod(&v); // v < n 时无损
148                        let (x, _) = crv::mul_base(&k_s.to_raw());
149                        let r_s = S::from_bytes_be_mod(&x.to_bytes_be());
150                        let s = k_s.invert().mul(&z.add(&r_s.mul(&d_m)));
151                        if nonzero && !ge_n && !r_s.is_zero() && !s.is_zero() {
152                            let r_be = r_s.to_bytes_be();
153                            let s_be = s.to_bytes_be();
154                            return Ok(encode_der_sig(&r_be, &s_be));
155                        }
156                        // h.5 重试:K = HMAC_K(V || 0x00);V = HMAC_K(V)
157                        let mut b2 = [0u8; HLEN + 1];
158                        b2[..HLEN].copy_from_slice(&v);
159                        b2[HLEN] = 0x00;
160                        k = $hmac::one_shot(&k, &b2);
161                        v = $hmac::one_shot(&k, &v);
162                    }
163                }
164            }
165
166            /// 模数 n 的规范 BE 字节(S::P 即 n 的普通形式 limbs;
167            /// 严禁经 from_raw/to_raw 转换——模数在 mod n 下映射为 0)。
168            fn n_bytes_be() -> [u8; SEED_LEN] {
169                let mut out = [0u8; SEED_LEN];
170                for j in 0..S::LIMBS {
171                    out[(S::LIMBS - 1 - j) * 8..(S::LIMBS - j) * 8]
172                        .copy_from_slice(&S::P[j].to_be_bytes());
173                }
174                out
175            }
176
177            /// 解析 DER 签名并返回 (r, s) 的定长 BE 形式。
178            fn parse_sig(
179                signature_der: &[u8],
180            ) -> Result<([u8; SEED_LEN], [u8; SEED_LEN]), crate::Error> {
181                let (rs_body, rest) = crate::der::sequence(signature_der)?;
182                if !rest.is_empty() {
183                    return Err(crate::Error::InvalidInput);
184                }
185                let (r_bytes, rest) = crate::der::integer(rs_body)?;
186                let (s_bytes, rest2) = crate::der::integer(rest)?;
187                if !rest2.is_empty() || r_bytes.len() > SEED_LEN || s_bytes.len() > SEED_LEN {
188                    return Err(crate::Error::VerificationFailed);
189                }
190                let mut rb = [0u8; SEED_LEN];
191                rb[SEED_LEN - r_bytes.len()..].copy_from_slice(r_bytes);
192                let mut sb = [0u8; SEED_LEN];
193                sb[SEED_LEN - s_bytes.len()..].copy_from_slice(s_bytes);
194                // r、s 必须严格小于 n:与 n 的规范 BE 字节逐字节比较
195                let n_bytes = n_bytes_be();
196                for i in 0..SEED_LEN {
197                    if rb[i] < n_bytes[i] {
198                        break;
199                    }
200                    if rb[i] > n_bytes[i] {
201                        return Err(crate::Error::VerificationFailed);
202                    }
203                }
204                for i in 0..SEED_LEN {
205                    if sb[i] < n_bytes[i] {
206                        break;
207                    }
208                    if sb[i] > n_bytes[i] {
209                        return Err(crate::Error::VerificationFailed);
210                    }
211                }
212                if rb == [0u8; SEED_LEN] || sb == [0u8; SEED_LEN] {
213                    return Err(crate::Error::VerificationFailed);
214                }
215                Ok((rb, sb))
216            }
217
218            /// ECDSA 验证公钥。
219            ///
220            /// 唯一构造路径 [`VerifyKey::from_sec1_point`]:输入必须是
221            /// **未压缩 SEC1 点**(`0x04 ‖ X ‖ Y`,RFC 5480),不含
222            /// SPKI/AlgorithmIdentifier 包装——X.509 剥离由调用方完成
223            /// (rustls 适配层直接透传 webpki 的 `key_value`)。
224            pub struct VerifyKey {
225                qx: crv::F,
226                qy: crv::F,
227            }
228
229            impl VerifyKey {
230                /// 解析未压缩 SEC1 点(含规范性与在曲线校验)。
231                pub fn from_sec1_point(bytes: &[u8]) -> Result<Self, crate::Error> {
232                    let (qx, qy) = crv::parse_public(bytes)?;
233                    Ok(Self { qx, qy })
234                }
235
236                /// 验证 DER 编码的 ECDSA 签名。
237                pub fn verify(
238                    &self,
239                    message: &[u8],
240                    signature_der: &[u8],
241                ) -> Result<(), crate::Error> {
242                    let (rb, sb) = parse_sig(signature_der)?;
243                    let digest = $hash::one_shot(message);
244                    let z = S::from_bytes_be_mod(&digest);
245                    let r_s = S::from_bytes_be_mod(&rb);
246                    let s_s = S::from_bytes_be_mod(&sb);
247
248                    let w = s_s.invert();
249                    let u1 = z.mul(&w);
250                    let u2 = r_s.mul(&w);
251
252                    let g = (crv::gx(), crv::gy());
253                    let p1 = crv::mul_point_pub(&u1.to_raw(), &g.0, &g.1);
254                    if p1.is_infinity() {
255                        return Err(crate::Error::VerificationFailed);
256                    }
257                    let p2 = crv::mul_point_pub(&u2.to_raw(), &self.qx, &self.qy);
258                    if p2.is_infinity() {
259                        return Err(crate::Error::VerificationFailed);
260                    }
261                    let (x, _) = crv::add_points_affine_pub(
262                        &crv::to_affine_pub(&p1),
263                        &crv::to_affine_pub(&p2),
264                    )?;
265                    let r_prime = S::from_bytes_be_mod(&x.to_bytes_be());
266                    if r_prime == r_s {
267                        Ok(())
268                    } else {
269                        Err(crate::Error::VerificationFailed)
270                    }
271                }
272            }
273        }
274    };
275}
276
277pub mod ecdsa {
278    // 宏展开在模块作用域内需要可见的项
279    use super::{Fp256Scalar, Fp384Scalar, encode_der_sig};
280
281    ecdsa_curve!(
282        p256,
283        p256,
284        Fp256Scalar,
285        32,
286        Sha256,
287        HmacSha256,
288        "P-256 ECDSA(SHA-256,RFC 6979 确定性 nonce)。"
289    );
290
291    ecdsa_curve!(
292        p384,
293        p384,
294        Fp384Scalar,
295        48,
296        Sha384,
297        HmacSha384,
298        "P-384 ECDSA(SHA-384,RFC 6979 确定性 nonce)。"
299    );
300}
301
302// ---------------------------------------------------------------------------
303// Ed25519(RFC 8032)——FIPS 非批准
304// ---------------------------------------------------------------------------
305
306/// Ed25519 命名空间。
307pub mod ed25519 {
308    use super::*;
309    use crate::fields::Fp25519ScalarL as ScL;
310
311    /// 私钥种子字节数。
312    pub const SEED_LEN: usize = 32;
313    /// 公钥字节数。
314    pub const PUBLIC_KEY_LEN: usize = 32;
315    /// 签名字节数。
316    pub const SIGNATURE_LEN: usize = 64;
317
318    /// 基点压缩编码(RFC 8032:y = 4/5,x 为偶)。
319    pub(crate) const G_COMPRESSED: [u8; 32] = [
320        0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
321        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
322        0x66, 0x66,
323    ];
324
325    /// 扭曲 Edwards 曲线参数 d(= −121665/121666),首次调用时推导、
326    /// 之后缓存(`OnceLock`)。派生含一次 Fermat 模逆(~253 次平方 +
327    /// ~250 次乘法)——旧形态每次调用重算,而每次点加法都要用 2d,
328    /// 256 轮 double-and-add 即 ~1024 次重推导(Ed25519 sign/verify
329    /// 26 ms 的主导项,2026-09 性能修复)。d 是公开的曲线常数(非
330    /// 秘密),缓存无零化/常数时间顾虑;值由同一派生式计算,与旧
331    /// 实现逐位一致。
332    pub(crate) fn curve_d() -> &'static Fp25519 {
333        static D: OnceLock<Fp25519> = OnceLock::new();
334        D.get_or_init(|| {
335            let um = Fp25519::from_raw([121665, 0, 0, 0]);
336            let vm = Fp25519::from_raw([121666, 0, 0, 0]);
337            um.neg().mul(&vm.invert())
338        })
339    }
340
341    /// 扩展坐标点 (X : Y : Z : T),恒等元 = (0, 1, 1, 0)。
342    #[derive(Clone, Copy)]
343    pub(crate) struct Point {
344        pub(crate) x: Fp25519,
345        pub(crate) y: Fp25519,
346        pub(crate) z: Fp25519,
347        pub(crate) t: Fp25519,
348    }
349
350    impl Point {
351        pub(crate) fn identity() -> Self {
352            Self {
353                x: Fp25519::zero(),
354                y: Fp25519::one(),
355                z: Fp25519::one(),
356                t: Fp25519::zero(),
357            }
358        }
359
360        /// 统一加法(add-2008-hwcd-3,a = −1)。
361        pub(crate) fn add(&self, other: &Self) -> Self {
362            let dd = curve_d().add(curve_d());
363            let a = self.y.sub(&self.x).mul(&other.y.sub(&other.x));
364            let b = self.y.add(&self.x).mul(&other.y.add(&other.x));
365            let c = self.t.mul(&other.t).mul(&dd);
366            let d = self.z.add(&self.z).mul(&other.z);
367            let e = b.sub(&a);
368            let f = d.sub(&c);
369            let g = d.add(&c);
370            let h = b.add(&a);
371            Self {
372                x: e.mul(&f),
373                y: g.mul(&h),
374                z: f.mul(&g),
375                t: e.mul(&h),
376            }
377        }
378
379        fn double(&self) -> Self {
380            self.add(self)
381        }
382
383        /// 压缩编码。
384        pub(crate) fn compress(&self) -> [u8; 32] {
385            // 扩展坐标仿射转换:x = X/Z,y = Y/Z(不是 Jacobian 的 Z²/Z³)
386            let zinv = self.z.invert();
387            let x = self.x.mul(&zinv);
388            let y = self.y.mul(&zinv);
389            let mut out = y.to_bytes_le();
390            // 符号位 = 仿射 x(规范普通形式)的奇偶;必须先转出 Montgomery 形式
391            out[31] |= ((x.to_raw()[0] & 1) as u8) << 7;
392            out
393        }
394    }
395
396    /// 从 32 字节压缩编码恢复点(含在曲线校验)。
397    pub(crate) fn decompress(bytes: &[u8; 32]) -> Result<Point, crate::Error> {
398        let mut y_bytes = *bytes;
399        let sign = y_bytes[31] >> 7;
400        y_bytes[31] &= 127;
401        let y = {
402            let mut limbs = [0u64; 4];
403            for j in 0..4 {
404                let mut w = [0u8; 8];
405                w.copy_from_slice(&y_bytes[j * 8..j * 8 + 8]);
406                limbs[j] = u64::from_le_bytes(w);
407            }
408            // 非规范编码拒绝(RFC 8032 §5.1.3 步骤 2/3;与 dalek 严格
409            // 模式一致):y ∈ [p, 2^255) 不是合法编码,宽容归约会给同一
410            // 签名/公钥留下第二种编码(malleability 面)。
411            if Fp25519::geq_canonical(&limbs) {
412                return Err(crate::Error::VerificationFailed);
413            }
414            // 统一转换到 Montgomery 形式(后续运算均为 Montgomery 域)
415            Fp25519::from_raw(limbs)
416        };
417        // x² = (y² − 1) / (d·y² + 1),RFC 8032 §5.1.3 恢复配方
418        let d = curve_d();
419        let y2 = y.square();
420        let u = y2.sub(&Fp25519::one());
421        let v = d.mul(&y2).add(&Fp25519::one());
422        let v3 = v.square().mul(&v);
423        let v7 = v3.square().mul(&v);
424        let uv7 = u.mul(&v7);
425        let e = [
426            0xfffffffffffffffd,
427            0xffffffffffffffff,
428            0xffffffffffffffff,
429            0x0fffffffffffffff,
430        ]; // (q−5)/8
431        let pow_e = uv7.pow(&e);
432        let mut x = u.mul(&v3).mul(&pow_e);
433        let vx2 = v.mul(&x.square());
434        if vx2 == u {
435            // 有效
436        } else if vx2 == u.neg() {
437            // x *= 2^((q−1)/4)
438            let e2 = [
439                0xfffffffffffffffb,
440                0xffffffffffffffff,
441                0xffffffffffffffff,
442                0x1fffffffffffffff,
443            ]; // (q−1)/4 = 2^253 − 5
444            x = x.mul(&Fp25519::from_raw([2, 0, 0, 0]).pow(&e2));
445        } else {
446            return Err(crate::Error::VerificationFailed);
447        }
448        // 符号修正:比较仿射 x 的规范奇偶(to_raw 先出 Montgomery 形式)。
449        // RFC 8032 §5.1.3:奇偶必须与符号位一致——x=0 且 sign=1 无法通过
450        // 取负满足(-0 = 0,奇偶仍为 0),必须拒绝解码。
451        let neg = ((x.to_raw()[0] ^ u64::from(sign)) & 1).wrapping_neg();
452        x = Fp25519::select(neg, &x.neg(), &x);
453        if (x.to_raw()[0] ^ u64::from(sign)) & 1 == 1 {
454            return Err(crate::Error::VerificationFailed);
455        }
456        Ok(Point {
457            x,
458            y,
459            z: Fp25519::one(),
460            t: x.mul(&y),
461        })
462    }
463
464    /// 标量乘(倍加 + 统一加法,天然处理所有例外输入)。
465    pub(crate) fn scalar_mult(k_bytes: &[u8; 32], base: &Point) -> Point {
466        let mut acc = Point::identity();
467        for i in (0..256).rev() {
468            acc = acc.double();
469            let bit = ((k_bytes[i / 8] >> (i % 8)) & 1) as u64;
470            let bit_mask = bit.wrapping_neg();
471            let sum = acc.add(base);
472            acc = Point {
473                x: Fp25519::select(bit_mask, &sum.x, &acc.x),
474                y: Fp25519::select(bit_mask, &sum.y, &acc.y),
475                z: Fp25519::select(bit_mask, &sum.z, &acc.z),
476                t: Fp25519::select(bit_mask, &sum.t, &acc.t),
477            };
478        }
479        acc
480    }
481
482    /// 标准基点 G(`G_COMPRESSED` 解压,首次调用后缓存——解压含一次
483    /// 模幂(sqrt),旧形态每次 public_key/sign/verify 都重做)。G 是
484    /// 公开曲线常数,缓存无零化/常数时间顾虑。
485    pub(crate) fn base_point() -> Point {
486        static G: OnceLock<Point> = OnceLock::new();
487        *G.get_or_init(|| decompress(&G_COMPRESSED).expect("standard base point"))
488    }
489
490    /// 私钥种子(`ZeroizeOnDrop`)。
491    #[derive(Clone)]
492    pub struct SigningKey {
493        seed: [u8; 32],
494    }
495
496    impl SigningKey {
497        /// 本算法在 FIPS 140-3 下的批准状态。
498        pub const APPROVAL: crate::Approval = crate::Approval::NonApproved;
499
500        /// 生成新密钥(OS 熵直读;M5 起批准模式走边界内 CTR-DRBG)。
501        pub fn generate() -> Result<Self, crate::Error> {
502            let mut seed = [0u8; 32];
503            crate::entropy::fill(&mut seed)?;
504            Ok(Self { seed })
505        }
506
507        /// 由种子构造(测试/向量入口)。
508        pub fn from_seed(seed: [u8; 32]) -> Self {
509            Self { seed }
510        }
511
512        /// 公钥(32 字节压缩)。
513        pub fn public_key(&self) -> [u8; 32] {
514            let h = Sha512::one_shot(&self.seed);
515            let mut a = [0u8; 32];
516            a.copy_from_slice(&h[..32]);
517            a[0] &= 248;
518            a[31] &= 127;
519            a[31] |= 64;
520            scalar_mult(&a, &base_point()).compress()
521        }
522
523        /// 对消息签名(PureEdDSA,64 字节:R || S)。
524        pub fn sign(&self, message: &[u8]) -> [u8; 64] {
525            let h = Sha512::one_shot(&self.seed);
526            let mut a = [0u8; 32];
527            a.copy_from_slice(&h[..32]);
528            a[0] &= 248;
529            a[31] &= 127;
530            a[31] |= 64;
531            let a_s = ScL::from_bytes_le_mod(&a);
532            let prefix = &h[32..64];
533
534            // r = H(prefix || M) mod L
535            let mut rh = Sha512::new();
536            rh.update(prefix);
537            rh.update(message);
538            let r_digest = rh.finalize();
539            let r = ScL::from_bytes_le_mod(&r_digest);
540            let big_r = scalar_mult(&r.to_bytes_le(), &base_point()).compress();
541
542            // k = H(R || A || M) mod L
543            let mut kh = Sha512::new();
544            kh.update(&big_r);
545            kh.update(&self.public_key());
546            kh.update(message);
547            let k_digest = kh.finalize();
548            let k = ScL::from_bytes_le_mod(&k_digest);
549
550            // S = (r + k·a) mod L
551            let s = r.add(&k.mul(&a_s));
552            let s_le = s.to_bytes_le();
553
554            let mut sig = [0u8; 64];
555            sig[..32].copy_from_slice(&big_r);
556            sig[32..].copy_from_slice(&s_le);
557            sig
558        }
559    }
560
561    impl Drop for SigningKey {
562        fn drop(&mut self) {
563            self.seed.fill(0);
564        }
565    }
566
567    impl std::fmt::Debug for SigningKey {
568        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
569            f.write_str("ed25519::SigningKey")
570        }
571    }
572
573    /// Ed25519 验证公钥。
574    ///
575    /// 唯一构造路径 [`VerifyKey::from_raw_bytes`]:输入是 32 字节
576    /// 压缩编码(RFC 8032 §5.1.5,含规范性与在曲线校验)。
577    #[derive(Clone, Copy)]
578    pub struct VerifyKey {
579        bytes: [u8; 32],
580    }
581
582    impl std::fmt::Debug for VerifyKey {
583        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
584            f.write_str("ed25519::VerifyKey")
585        }
586    }
587
588    impl VerifyKey {
589        /// 解析 32 字节压缩公钥编码。
590        pub fn from_raw_bytes(public_key: &[u8]) -> Result<Self, crate::Error> {
591            if public_key.len() != PUBLIC_KEY_LEN {
592                return Err(crate::Error::InvalidInput);
593            }
594            let mut bytes = [0u8; PUBLIC_KEY_LEN];
595            bytes.copy_from_slice(public_key);
596            // 构造期校验规范性与在曲线(验证期 decompress 确定性地成功)
597            decompress(&bytes)?;
598            Ok(Self { bytes })
599        }
600
601        /// 验证 64 字节 Ed25519 签名。
602        pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), crate::Error> {
603            if signature.len() != SIGNATURE_LEN {
604                return Err(crate::Error::InvalidInput);
605            }
606            let a_bytes = self.bytes;
607            let a_pt = decompress(&a_bytes)?;
608
609            let mut r_bytes = [0u8; 32];
610            r_bytes.copy_from_slice(&signature[..32]);
611            let r_pt = decompress(&r_bytes)?;
612
613            // S 必须规范(0 ≤ S < L):LE 字节自最高位比较;全部相等(S == L)也拒绝
614            let l_bytes: [u8; 32] = [
615                0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9,
616                0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10,
617            ];
618            let mut s_lt_l = false;
619            for i in (0..32).rev() {
620                if signature[32 + i] < l_bytes[i] {
621                    s_lt_l = true;
622                    break;
623                }
624                if signature[32 + i] > l_bytes[i] {
625                    return Err(crate::Error::VerificationFailed);
626                }
627            }
628            if !s_lt_l {
629                return Err(crate::Error::VerificationFailed);
630            }
631            let mut s_bytes = [0u8; 32];
632            s_bytes.copy_from_slice(&signature[32..]);
633            let s_s = ScL::from_bytes_le_mod(&s_bytes);
634
635            let mut kh = Sha512::new();
636            kh.update(&signature[..32]);
637            kh.update(&a_bytes);
638            kh.update(message);
639            let k_digest = kh.finalize();
640            let k = ScL::from_bytes_le_mod(&k_digest);
641
642            // [S]G == R + [k]A
643            let lhs = scalar_mult(&s_s.to_bytes_le(), &base_point());
644            let ka = scalar_mult(&k.to_bytes_le(), &a_pt);
645            let rhs = r_pt.add(&ka);
646            if lhs.compress() == rhs.compress() {
647                Ok(())
648            } else {
649                Err(crate::Error::VerificationFailed)
650            }
651        }
652    }
653}
654
655// ---------------------------------------------------------------------------
656// RSA(M4b/M4c:固定宽度大数模幂 + CRT + 盲化 + PKCS#1 v1.5/PSS,RFC 8017)
657// ---------------------------------------------------------------------------
658
659/// RSA 签名/验证(RSASSA-PKCS1-v1_5 与 RSASSA-PSS,RFC 8017)。
660///
661/// 批准状态:FIPS 批准(FIPS 186-5 RSASSA;TLS 1.3 首选 PSS)。
662///
663/// 安全:
664/// - 私钥运算走 CRT(p/q 各自模幂,Garner 重组),指数位经掩码选择,
665///   对秘密指数常数时间(见 `rsabig` 模块);Garner 回绕修正为
666///   常数时间掩码选择;
667/// - 乘法盲化(Kocher,M4c):每次签名取单次使用随机 r ∈ [1, n)
668///   (OS 熵 + 拒绝采样),先算 EM′ = EM·rᵉ mod n 的 CRT 私钥运算,
669///   再乘 r⁻¹ 去盲——CRT 内全部中间值随 r 随机化,秘密与观测
670///   时序/访存解耦;r⁻¹ 经变量时间 binary xgcd 求得,输入为单次
671///   随机值与公开模数,时序不泄露可利用信息(Go/OpenSSL 同实践,
672///   见 `rsabig::mod_inverse_odd`);r 与盲化中间值退出前零化;
673/// - 验证 padding 检查严格,一切失败归一化为
674///   [`Error::VerificationFailed`](crate::Error::VerificationFailed);
675/// - 模长 < 2048 位拒绝([`crate::sign::rsa::MIN_MODULUS_LEN`]),
676///   > 4096 位拒绝(受 `rsabig::MAX_LIMBS` 限制);
677/// - 密钥装载做结构校验:p·q = n、q·qInv ≡ 1 (mod p)、dp < p、
678///   dq < q、qInv < p、n/p/q 为奇数、e ≥ 3 且为奇数;不做素性检测
679///   (密钥来源为本机信任输入,素性由密钥生成方保证)。
680pub mod rsa {
681    use crate::ct::zeroize::Zeroize;
682    use crate::rsabig;
683    use crate::sha2::{Sha256, Sha384, Sha512};
684
685    /// 盲化因子采样/求逆的最大尝试次数。每轮拒绝概率 ≤ 1/2
686    /// (n 顶位为 1),128 轮全部失败概率 ≤ 2⁻¹²⁸,视为熵源异常。
687    const BLIND_ATTEMPTS: usize = 128;
688
689    /// 最短允许的模长字节数(2048 位)。
690    pub const MIN_MODULUS_LEN: usize = 256;
691    /// 最长支持的模长字节数(4096 位)。
692    pub const MAX_MODULUS_LEN: usize = rsabig::MAX_LIMBS * 8;
693
694    /// RSA 私钥(CRT 参数;`Drop` 零化秘密分量)。
695    #[derive(Clone)]
696    pub struct SigningKey {
697        n_len: usize,
698        n_bytes: usize,
699        em_mask: u8,
700        // 公开参数(盲化的预乘 rᵉ 与去盲 r⁻¹ 在 mod n 下进行)
701        n: Vec<u64>,
702        e: Vec<u64>,
703        e_bits: usize,
704        n0_n: u64,
705        r2_n: Vec<u64>,
706        // 秘密参数(CRT)
707        p: Vec<u64>,
708        q: Vec<u64>,
709        dp: Vec<u64>,
710        dq: Vec<u64>,
711        qinv: Vec<u64>,
712        n0_p: u64,
713        r2_p: Vec<u64>,
714        n0_q: u64,
715        r2_q: Vec<u64>,
716        pl: usize,
717    }
718
719    impl SigningKey {
720        /// 本算法在 FIPS 140-3 下的批准状态。
721        pub const APPROVAL: crate::Approval = crate::Approval::Approved;
722
723        /// 从 PKCS#8 DER(内层 PKCS#1 RSAPrivateKey)解析。模长 < 2048 位
724        /// 返回 [`Error::Unsupported`](crate::Error::Unsupported)。
725        pub fn from_pkcs8_der(der: &[u8]) -> Result<Self, crate::Error> {
726            match crate::der::parse_pkcs8_private_key(der)? {
727                crate::der::ParsedPrivateKey::RsaPkcs1(pkcs1) => Self::from_pkcs1_der(&pkcs1),
728                _ => Err(crate::Error::InvalidInput),
729            }
730        }
731
732        /// 解析 PKCS#1 RSAPrivateKey DER 并做结构一致性校验
733        ///(rustls KeyProvider 的 PKCS#1 入口)。
734        pub fn from_pkcs1_der(der: &[u8]) -> Result<Self, crate::Error> {
735            let (seq, rest) = crate::der::sequence(der)?;
736            if !rest.is_empty() {
737                return Err(crate::Error::InvalidInput);
738            }
739            let (version, rest) = crate::der::integer(seq)?;
740            if version.len() != 1 || version[0] != 0 {
741                return Err(crate::Error::InvalidInput);
742            }
743            // RSAPrivateKey ::= SEQUENCE { version, n, e, d, p, q,
744            //   d mod p-1, d mod q-1, qInv, otherPrimeInfos [0] OPTIONAL }
745            let (n_b, rest) = crate::der::integer(rest)?;
746            let (e_b, rest) = crate::der::integer(rest)?;
747            let (_d_b, rest) = crate::der::integer(rest)?; // CRT 路径不使用 d
748            let (p_b, rest) = crate::der::integer(rest)?;
749            let (q_b, rest) = crate::der::integer(rest)?;
750            let (dp_b, rest) = crate::der::integer(rest)?;
751            let (dq_b, rest) = crate::der::integer(rest)?;
752            let (qinv_b, rest) = crate::der::integer(rest)?;
753            // 多素数扩展不支持
754            if !rest.is_empty() {
755                return Err(crate::Error::InvalidInput);
756            }
757
758            // 模长范围
759            let n_bytes = n_b.len();
760            if n_bytes < MIN_MODULUS_LEN {
761                return Err(crate::Error::Unsupported);
762            }
763            if n_bytes > MAX_MODULUS_LEN {
764                return Err(crate::Error::InvalidInput);
765            }
766            let n_len = n_bytes.div_ceil(8);
767            let pl = n_len.div_ceil(2);
768            // EM 左端必须清零的位数 = 8·emLen − emBits(emBits = modBits − 1)
769            let n_bitlen = 8 * n_bytes - n_b[0].leading_zeros() as usize;
770            let em_left_bits = 8 * n_bytes + 1 - n_bitlen;
771            let em_mask: u8 = (0xffu32 >> em_left_bits) as u8;
772
773            let mut n = vec![0u64; n_len];
774            rsabig::os2ip_be(n_b, &mut n);
775            if n[0] & 1 == 0 {
776                return Err(crate::Error::InvalidInput); // n 必须为奇
777            }
778
779            // e:≤ 8 字节、奇数且 ≥ 3
780            if e_b.is_empty() || e_b.len() > 8 {
781                return Err(crate::Error::InvalidInput);
782            }
783            let mut e = vec![0u64; 1];
784            rsabig::os2ip_be(e_b, &mut e);
785            if e[0] < 3 || e[0] & 1 == 0 {
786                return Err(crate::Error::InvalidInput);
787            }
788
789            // p、q:≤ pl limbs、奇数
790            if p_b.len() > pl * 8 || q_b.len() > pl * 8 {
791                return Err(crate::Error::InvalidInput);
792            }
793            let mut p = vec![0u64; pl];
794            let mut q = vec![0u64; pl];
795            rsabig::os2ip_be(p_b, &mut p);
796            rsabig::os2ip_be(q_b, &mut q);
797            if p[0] & 1 == 0
798                || q[0] & 1 == 0
799                || p.iter().all(|&x| x == 0)
800                || q.iter().all(|&x| x == 0)
801            {
802                return Err(crate::Error::InvalidInput);
803            }
804
805            // dp < p、dq < q、qInv < p
806            if dp_b.len() > pl * 8 || dq_b.len() > pl * 8 || qinv_b.len() > pl * 8 {
807                return Err(crate::Error::InvalidInput);
808            }
809            let mut dp = vec![0u64; pl];
810            let mut dq = vec![0u64; pl];
811            let mut qinv = vec![0u64; pl];
812            rsabig::os2ip_be(dp_b, &mut dp);
813            rsabig::os2ip_be(dq_b, &mut dq);
814            rsabig::os2ip_be(qinv_b, &mut qinv);
815            if rsabig::geq(&dp, &p) || rsabig::geq(&dq, &q) || rsabig::geq(&qinv, &p) {
816                return Err(crate::Error::InvalidInput);
817            }
818
819            // p·q = n
820            let pq = rsabig::mul_full(&p, &q);
821            if pq[..n_len] != n[..] || pq[n_len..].iter().any(|&x| x != 0) {
822                return Err(crate::Error::InvalidInput);
823            }
824
825            // Montgomery 常数(CRT 侧 + 盲化用的 n 侧)
826            let n0_p = rsabig::n0_inv(p[0]);
827            let n0_q = rsabig::n0_inv(q[0]);
828            let r2_p = rsabig::compute_r2(&p);
829            let r2_q = rsabig::compute_r2(&q);
830            let n0_n = rsabig::n0_inv(n[0]);
831            let r2_n = rsabig::compute_r2(&n);
832            let e_bits = 64 - e[0].leading_zeros() as usize;
833
834            // q·qInv ≡ 1 (mod p)
835            let mut mq = vec![0u64; pl];
836            let mut mqinv = vec![0u64; pl];
837            rsabig::to_mont(&q, &r2_p, &p, n0_p, &mut mq);
838            rsabig::to_mont(&qinv, &r2_p, &p, n0_p, &mut mqinv);
839            let mut chk = vec![0u64; pl];
840            rsabig::mont_mul(&mq, &mqinv, &p, n0_p, &mut chk);
841            rsabig::from_mont(&mut chk, &p, n0_p);
842            if chk[0] != 1 || chk[1..].iter().any(|&x| x != 0) {
843                return Err(crate::Error::InvalidInput);
844            }
845
846            Ok(Self {
847                n_len,
848                n_bytes,
849                em_mask,
850                n,
851                e,
852                e_bits,
853                n0_n,
854                r2_n,
855                p,
856                q,
857                dp,
858                dq,
859                qinv,
860                n0_p,
861                r2_p,
862                n0_q,
863                r2_q,
864                pl,
865            })
866        }
867
868        /// 均匀采样 r ∈ [1, n):OS 熵 + 拒绝采样(n 顶位为 1,每轮
869        /// 拒绝概率 ≤ 1/2)。任何失败路径上 `out` 与采样缓冲均已零化。
870        fn sample_blinding_factor(&self, out: &mut [u64]) -> Result<(), crate::Error> {
871            debug_assert_eq!(out.len(), self.n_len);
872            let mut buf = vec![0u8; self.n_bytes];
873            for _ in 0..BLIND_ATTEMPTS {
874                if let Err(e) = crate::entropy::fill(&mut buf) {
875                    buf.zeroize();
876                    out.zeroize();
877                    return Err(e);
878                }
879                rsabig::os2ip_be(&buf, out);
880                let zero = out.iter().all(|&w| w == 0);
881                if !zero && !rsabig::geq(out, &self.n) {
882                    buf.zeroize();
883                    return Ok(());
884                }
885            }
886            buf.zeroize();
887            out.zeroize();
888            Err(crate::Error::EntropyFailed)
889        }
890
891        /// CRT 私钥运算:m^d mod n(m 为普通形式 limbs 且 m < n,
892        /// 返回 n_len limbs)。本函数的输入应为**盲化后**的值——
893        /// 内部中间值(mp/mq/sp/sq/h 等)随盲化因子随机化;
894        /// 秘密中间缓冲退出前零化。
895        fn crt(&self, m: &[u64]) -> Vec<u64> {
896            let l = self.pl;
897            let nl = self.n_len;
898
899            let mut mp = vec![0u64; l];
900            rsabig::reduce_limbs(m, &self.p, &mut mp);
901            let mut mq = vec![0u64; l];
902            rsabig::reduce_limbs(m, &self.q, &mut mq);
903
904            // sp = m^dp mod p、sq = m^dq mod q(Montgomery 域内完成)
905            let mut sp = vec![0u64; l];
906            let mut sq = vec![0u64; l];
907            {
908                let mut base = vec![0u64; l];
909                let mut res = vec![0u64; l];
910                rsabig::to_mont(&mp, &self.r2_p, &self.p, self.n0_p, &mut base);
911                rsabig::mont_exp(
912                    &base,
913                    &self.dp,
914                    64 * l,
915                    &self.p,
916                    self.n0_p,
917                    &self.r2_p,
918                    &mut res,
919                );
920                rsabig::from_mont(&mut res, &self.p, self.n0_p);
921                sp.copy_from_slice(&res);
922                rsabig::to_mont(&mq, &self.r2_q, &self.q, self.n0_q, &mut base);
923                rsabig::mont_exp(
924                    &base,
925                    &self.dq,
926                    64 * l,
927                    &self.q,
928                    self.n0_q,
929                    &self.r2_q,
930                    &mut res,
931                );
932                rsabig::from_mont(&mut res, &self.q, self.n0_q);
933                sq.copy_from_slice(&res);
934                base.zeroize();
935                res.zeroize();
936            }
937
938            // Garner(qInv = q⁻¹ mod p):h = (sp − sq)·qInv mod p;
939            // s′ = sq + q·h ≤ (q−1) + q(p−1) = n − 1 < n。
940            // 回绕修正无条件计算 diff + p,按借位掩码选取(常数时间;
941            // 借位为 1 时加法跨过 2^(64l) 恰一次,进位按同余定义丢弃,
942            // 结果落在 [0, p))。
943            let mut diff = vec![0u64; l];
944            let borrow = rsabig::sub_limbs(&sp, &sq, &mut diff);
945            let mut sum = vec![0u64; l];
946            {
947                let mut carry = 0u64;
948                for ((dv, pv), sv) in diff.iter().zip(self.p.iter()).zip(sum.iter_mut()) {
949                    let (v, c1) = dv.overflowing_add(*pv);
950                    let (v, c2) = v.overflowing_add(carry);
951                    *sv = v;
952                    carry = (c1 as u64) | (c2 as u64);
953                }
954            }
955            let mut fixed = vec![0u64; l];
956            rsabig::select(borrow.wrapping_neg(), &sum, &diff, &mut fixed);
957            sum.zeroize();
958            diff.copy_from_slice(&fixed); // 修正后的 (sp − sq) mod p
959            fixed.zeroize();
960            // h = diff·qInv mod p:diff 先入 Montgomery 域,与 raw qInv 相乘
961            // 的结果即为 raw(mont(diff)·qInv·R⁻¹ = diff·qInv)
962            let mut hm = vec![0u64; l];
963            rsabig::to_mont(&diff, &self.r2_p, &self.p, self.n0_p, &mut hm);
964            let mut h = vec![0u64; l];
965            rsabig::mont_mul(&hm, &self.qinv, &self.p, self.n0_p, &mut h);
966
967            let mut qh = rsabig::mul_full(&self.q, &h); // 2l limbs
968            qh.truncate(nl);
969            let mut sqx = vec![0u64; nl];
970            sqx[..l].copy_from_slice(&sq);
971            let mut sres = vec![0u64; nl];
972            rsabig::add_limbs(&sqx, &qh, &mut sres); // < n,无进位
973
974            for v in [
975                &mut mp, &mut mq, &mut sp, &mut sq, &mut diff, &mut hm, &mut h, &mut qh, &mut sqx,
976            ] {
977                v.zeroize();
978            }
979            sres
980        }
981
982        /// 对消息代表元 EM 私钥运算(乘法盲化 + CRT + Garner 重组),
983        /// 返回定长签名。
984        ///
985        /// 盲化(M4c):单次随机 r ∈ [1, n),s = (EM·rᵉ)^d·r⁻¹ mod n
986        /// ——盲化在数学上精确抵消,签名结果与无盲化实现逐字节一致
987        /// (PKCS#1 v1.5 的 openssl 逐字节锚定与 selftest KAT 即为
988        /// 盲化正确性的回归门)。
989        fn sign_em(&self, em: &[u8]) -> Result<Vec<u8>, crate::Error> {
990            debug_assert_eq!(em.len(), self.n_bytes);
991            let nl = self.n_len;
992
993            let mut m = vec![0u64; nl];
994            rsabig::os2ip_be(em, &mut m);
995
996            let mut r = vec![0u64; nl];
997            let mut rinv = vec![0u64; nl];
998            let mut re = vec![0u64; nl]; // rᵉ(Montgomery 域)
999            let mut t = vec![0u64; nl];
1000            let mut t2 = vec![0u64; nl];
1001            let mut sig = vec![0u64; nl];
1002            let mut ok = false;
1003            let mut err = None;
1004            'blind: for _ in 0..BLIND_ATTEMPTS {
1005                if let Err(e) = self.sample_blinding_factor(&mut r) {
1006                    err = Some(e);
1007                    break 'blind;
1008                }
1009                // gcd(r, n) ≠ 1:合法密钥(n = p·q,p/q 为大素数)下
1010                // 概率 ~2⁻¹⁰²³;换 r 重试
1011                match rsabig::mod_inverse_odd(&r, &self.n) {
1012                    Some(inv) => rinv.copy_from_slice(&inv),
1013                    None => continue,
1014                }
1015                // re = rᵉ mod n(e 为公开指数,mont_exp 对其常数时间)
1016                rsabig::to_mont(&r, &self.r2_n, &self.n, self.n0_n, &mut t);
1017                rsabig::mont_exp(
1018                    &t,
1019                    &self.e,
1020                    self.e_bits,
1021                    &self.n,
1022                    self.n0_n,
1023                    &self.r2_n,
1024                    &mut re,
1025                );
1026                // m′ = m·rᵉ mod n
1027                rsabig::to_mont(&m, &self.r2_n, &self.n, self.n0_n, &mut t);
1028                rsabig::mont_mul(&t, &re, &self.n, self.n0_n, &mut t2);
1029                rsabig::from_mont(&mut t2, &self.n, self.n0_n);
1030                // s′ = CRT(m′);s = s′·r⁻¹ mod n(去盲)
1031                let mut s_blind = self.crt(&t2);
1032                rsabig::to_mont(&s_blind, &self.r2_n, &self.n, self.n0_n, &mut t);
1033                rsabig::to_mont(&rinv, &self.r2_n, &self.n, self.n0_n, &mut t2);
1034                rsabig::mont_mul(&t, &t2, &self.n, self.n0_n, &mut sig);
1035                rsabig::from_mont(&mut sig, &self.n, self.n0_n);
1036                s_blind.zeroize();
1037                ok = true;
1038                break 'blind;
1039            }
1040            // 零化盲化因子与中间值(成功/失败路径统一覆盖)
1041            for v in [&mut m, &mut r, &mut rinv, &mut re, &mut t, &mut t2] {
1042                v.zeroize();
1043            }
1044            if let Some(e) = err {
1045                return Err(e);
1046            }
1047            if !ok {
1048                // 全部尝试的 r 均与 n 不互素:模数不是半素数(结构异常)
1049                return Err(crate::Error::Unsupported);
1050            }
1051            let mut out = vec![0u8; self.n_bytes];
1052            rsabig::i2osp_be(&sig, &mut out);
1053            sig.zeroize();
1054            Ok(out)
1055        }
1056
1057        /// RSA-PSS 签名(salt 长度 = 哈希长度;TLS 1.3 使用)。
1058        pub fn sign_pss(&self, hash_bits: u16, message: &[u8]) -> Result<Vec<u8>, crate::Error> {
1059            let mhash = hash_msg(hash_bits, message)?;
1060            let hlen = mhash.len();
1061            let emlen = self.n_bytes;
1062            // emLen ≥ hLen + sLen + 2(sLen = hLen)
1063            if emlen < 2 * hlen + 2 {
1064                return Err(crate::Error::InvalidInput);
1065            }
1066            let mut salt = vec![0u8; hlen];
1067            crate::entropy::fill(&mut salt)?;
1068            // M' = 0x00 × 8 || mHash || salt
1069            let mut mprime = vec![0u8; 8 + 2 * hlen];
1070            mprime[8..8 + hlen].copy_from_slice(&mhash);
1071            mprime[8 + hlen..].copy_from_slice(&salt);
1072            let h = hash_msg(hash_bits, &mprime)?;
1073            // DB = PS(0x00 × (emLen − hLen − sLen − 2)) || 0x01 || salt
1074            let dblen = emlen - hlen - 1;
1075            let mut db = vec![0u8; dblen];
1076            db[dblen - hlen - 1] = 0x01;
1077            db[dblen - hlen..].copy_from_slice(&salt);
1078            let mut dbmask = vec![0u8; dblen];
1079            mgf1(hash_bits, &h, &mut dbmask)?;
1080            for i in 0..dblen {
1081                db[i] ^= dbmask[i];
1082            }
1083            db[0] &= self.em_mask;
1084            let mut em = Vec::with_capacity(emlen);
1085            em.extend_from_slice(&db);
1086            em.extend_from_slice(&h);
1087            em.push(0xbc);
1088            self.sign_em(&em)
1089        }
1090
1091        /// RSA PKCS#1 v1.5 签名(TLS 1.2 遗留套件与证书链验证使用)。
1092        pub fn sign_pkcs1v15(
1093            &self,
1094            hash_bits: u16,
1095            message: &[u8],
1096        ) -> Result<Vec<u8>, crate::Error> {
1097            let mhash = hash_msg(hash_bits, message)?;
1098            let prefix = digestinfo_prefix(hash_bits)?;
1099            let tlen = prefix.len() + mhash.len();
1100            let emlen = self.n_bytes;
1101            if emlen < tlen + 11 {
1102                return Err(crate::Error::InvalidInput);
1103            }
1104            let mut em = vec![0u8; emlen];
1105            em[0] = 0x00;
1106            em[1] = 0x01;
1107            for b in em[2..emlen - tlen - 1].iter_mut() {
1108                *b = 0xff;
1109            }
1110            em[emlen - tlen - 1] = 0x00;
1111            em[emlen - tlen..emlen - mhash.len()].copy_from_slice(prefix);
1112            em[emlen - mhash.len()..].copy_from_slice(&mhash);
1113            self.sign_em(&em)
1114        }
1115    }
1116
1117    impl Drop for SigningKey {
1118        fn drop(&mut self) {
1119            // n/e 及其 Montgomery 常数(n0_n/r2_n)是公开钥分量,不零化;
1120            // r2_p/r2_q/n0_p/n0_q 派生自秘密素数,随秘密一并零化。
1121            for v in [
1122                &mut self.p,
1123                &mut self.q,
1124                &mut self.dp,
1125                &mut self.dq,
1126                &mut self.qinv,
1127                &mut self.r2_p,
1128                &mut self.r2_q,
1129            ] {
1130                for w in v.iter_mut() {
1131                    *w = 0;
1132                }
1133            }
1134            self.n0_p = 0;
1135            self.n0_q = 0;
1136        }
1137    }
1138
1139    impl std::fmt::Debug for SigningKey {
1140        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1141            f.write_str("rsa::SigningKey")
1142        }
1143    }
1144
1145    /// RSA 验证公钥(RSASSA-PKCS1-v1_5 / RSASSA-PSS,RFC 8017)。
1146    ///
1147    /// 两条显式命名的构造路径,名字即契约:
1148    /// - [`VerifyKey::from_rsapublickey_der`]:**裸 `RSAPublicKey` DER**
1149    ///   (`SEQUENCE { INTEGER n, INTEGER e }`)——X.509 之下的密钥本体;
1150    /// - [`VerifyKey::from_spki_der`]:完整 SPKI(`SEQUENCE { AlgId,
1151    ///   BIT STRING }`)——X.509 公钥包装,便利入口。
1152    ///
1153    /// X.509 剥离由调用方选择;rustls 适配层直接透传 webpki 的
1154    /// `key_value`(裸格式),见 `ferritls-rustls::verify`。
1155    #[derive(Clone)]
1156    pub struct VerifyKey {
1157        n: Vec<u64>,
1158        e: Vec<u64>,
1159        n0_n: u64,
1160        r2_n: Vec<u64>,
1161        n_len: usize,
1162        n_bytes: usize,
1163        e_len: usize,
1164        em_mask: u8,
1165    }
1166
1167    impl std::fmt::Debug for VerifyKey {
1168        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1169            f.write_str("rsa::VerifyKey")
1170        }
1171    }
1172
1173    impl VerifyKey {
1174        /// 解析裸 `RSAPublicKey` DER(`SEQUENCE { INTEGER n, INTEGER e }`,
1175        /// RFC 8017)。结构校验:外层 SEQUENCE 无尾字节、模长 2048–4096
1176        /// 位、n 奇、e ≥ 3 且为奇。
1177        pub fn from_rsapublickey_der(der: &[u8]) -> Result<Self, crate::Error> {
1178            let (keyseq, krest) = crate::der::sequence(der)?;
1179            if !krest.is_empty() {
1180                return Err(crate::Error::InvalidInput);
1181            }
1182            let (n_b, r) = crate::der::integer(keyseq)?;
1183            let (e_b, erest) = crate::der::integer(r)?;
1184            if !erest.is_empty() {
1185                return Err(crate::Error::InvalidInput);
1186            }
1187            if n_b.len() < MIN_MODULUS_LEN || n_b.len() > MAX_MODULUS_LEN {
1188                return Err(crate::Error::Unsupported);
1189            }
1190            if e_b.is_empty() || e_b.len() > 8 {
1191                return Err(crate::Error::InvalidInput);
1192            }
1193            let n_len = n_b.len().div_ceil(8);
1194            let n_bitlen = 8 * n_b.len() - n_b[0].leading_zeros() as usize;
1195            let em_left_bits = 8 * n_b.len() + 1 - n_bitlen;
1196            let mut n = vec![0u64; n_len];
1197            rsabig::os2ip_be(n_b, &mut n);
1198            if n[0] & 1 == 0 {
1199                return Err(crate::Error::InvalidInput);
1200            }
1201            let mut e = vec![0u64; 1];
1202            rsabig::os2ip_be(e_b, &mut e);
1203            if e[0] < 3 || e[0] & 1 == 0 {
1204                return Err(crate::Error::InvalidInput);
1205            }
1206            let n0_n = rsabig::n0_inv(n[0]);
1207            let r2_n = rsabig::compute_r2(&n);
1208            Ok(Self {
1209                n,
1210                e,
1211                n0_n,
1212                r2_n,
1213                n_len,
1214                n_bytes: n_b.len(),
1215                e_len: 1,
1216                em_mask: (0xffu32 >> em_left_bits) as u8,
1217            })
1218        }
1219
1220        /// 解析完整 SPKI(SubjectPublicKeyInfo,`SEQUENCE { AlgId,
1221        /// BIT STRING }`):校验 AlgorithmIdentifier 为 rsaEncryption,
1222        /// 再按裸 `RSAPublicKey` 解析 BIT STRING 内容。便利入口——
1223        /// 已持有 X.509 公钥包装的调用方(如自检 KAT 向量)可直用。
1224        pub fn from_spki_der(spki: &[u8]) -> Result<Self, crate::Error> {
1225            let (seq, rest) = crate::der::sequence(spki)?;
1226            if !rest.is_empty() {
1227                return Err(crate::Error::InvalidInput);
1228            }
1229            let (alg, rest) = crate::der::sequence(seq)?;
1230            let (oid, _params) = crate::der::object_identifier(alg)?;
1231            if oid != crate::der::oid::RSA_ENCRYPTION {
1232                return Err(crate::Error::InvalidInput);
1233            }
1234            let (keybits, rest) = crate::der::bit_string(rest)?;
1235            if !rest.is_empty() {
1236                return Err(crate::Error::InvalidInput);
1237            }
1238            Self::from_rsapublickey_der(keybits)
1239        }
1240
1241        /// s^e mod n,返回 I2OSP 定长编码(含签名长度与 s < n 校验)。
1242        fn public_exponentiate(&self, signature: &[u8]) -> Result<Vec<u8>, crate::Error> {
1243            if signature.len() != self.n_bytes {
1244                return Err(crate::Error::InvalidInput);
1245            }
1246            let mut s = vec![0u64; self.n_len];
1247            rsabig::os2ip_be(signature, &mut s);
1248            if rsabig::geq(&s, &self.n) {
1249                return Err(crate::Error::VerificationFailed);
1250            }
1251            let mut base = vec![0u64; self.n_len];
1252            rsabig::to_mont(&s, &self.r2_n, &self.n, self.n0_n, &mut base);
1253            let mut m = vec![0u64; self.n_len];
1254            rsabig::mont_exp(
1255                &base,
1256                &self.e,
1257                64 * self.e_len,
1258                &self.n,
1259                self.n0_n,
1260                &self.r2_n,
1261                &mut m,
1262            );
1263            rsabig::from_mont(&mut m, &self.n, self.n0_n);
1264            let mut out = vec![0u8; self.n_bytes];
1265            rsabig::i2osp_be(&m, &mut out);
1266            Ok(out)
1267        }
1268    }
1269
1270    fn hash_msg(hash_bits: u16, message: &[u8]) -> Result<Vec<u8>, crate::Error> {
1271        match hash_bits {
1272            256 => Ok(Sha256::one_shot(message).to_vec()),
1273            384 => Ok(Sha384::one_shot(message).to_vec()),
1274            512 => Ok(Sha512::one_shot(message).to_vec()),
1275            _ => Err(crate::Error::Unsupported),
1276        }
1277    }
1278
1279    /// DigestInfo 前缀(RFC 8017 §9.2 注 1)。
1280    fn digestinfo_prefix(hash_bits: u16) -> Result<&'static [u8], crate::Error> {
1281        match hash_bits {
1282            256 => Ok(&[
1283                0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
1284                0x01, 0x05, 0x00, 0x04, 0x20,
1285            ]),
1286            384 => Ok(&[
1287                0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
1288                0x02, 0x05, 0x00, 0x04, 0x30,
1289            ]),
1290            512 => Ok(&[
1291                0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
1292                0x03, 0x05, 0x00, 0x04, 0x40,
1293            ]),
1294            _ => Err(crate::Error::Unsupported),
1295        }
1296    }
1297
1298    /// MGF1(RFC 8017 附录 B.2.1)。
1299    fn mgf1(hash_bits: u16, seed: &[u8], mask: &mut [u8]) -> Result<(), crate::Error> {
1300        let mut counter = 0u32;
1301        let mut filled = 0usize;
1302        while filled < mask.len() {
1303            let mut input = Vec::with_capacity(seed.len() + 4);
1304            input.extend_from_slice(seed);
1305            input.extend_from_slice(&counter.to_be_bytes());
1306            let h = hash_msg(hash_bits, &input)?;
1307            let take = core::cmp::min(h.len(), mask.len() - filled);
1308            mask[filled..filled + take].copy_from_slice(&h[..take]);
1309            filled += take;
1310            counter += 1;
1311        }
1312        Ok(())
1313    }
1314
1315    impl VerifyKey {
1316        /// 验证 RSA-PSS 签名(RFC 8017 §9.1,salt 长度 = 哈希长度)。
1317        /// 重复验证同一把公钥时应复用 `VerifyKey`,模幂前的解析开销均摊。
1318        pub fn verify_pss(
1319            &self,
1320            hash_bits: u16,
1321            message: &[u8],
1322            signature: &[u8],
1323        ) -> Result<(), crate::Error> {
1324            let em = self.public_exponentiate(signature)?;
1325            let mhash = hash_msg(hash_bits, message)?;
1326            let hlen = mhash.len();
1327            let emlen = em.len();
1328            // 一切 padding 失败归一化为同一错误(不泄露失败阶段)
1329            if emlen < 2 * hlen + 2 || em[emlen - 1] != 0xbc {
1330                return Err(crate::Error::VerificationFailed);
1331            }
1332            if em[0] & !self.em_mask != 0 {
1333                return Err(crate::Error::VerificationFailed);
1334            }
1335            let h = &em[emlen - hlen - 1..emlen - 1];
1336            let dblen = emlen - hlen - 1;
1337            let mut db = em[..dblen].to_vec();
1338            let mut dbmask = vec![0u8; dblen];
1339            mgf1(hash_bits, h, &mut dbmask)?;
1340            for i in 0..dblen {
1341                db[i] ^= dbmask[i];
1342            }
1343            db[0] &= self.em_mask;
1344            let ps_len = dblen - hlen - 1;
1345            if db[..ps_len].iter().any(|&b| b != 0) || db[ps_len] != 0x01 {
1346                return Err(crate::Error::VerificationFailed);
1347            }
1348            let salt = &db[ps_len + 1..];
1349            let mut mprime = vec![0u8; 8 + 2 * hlen];
1350            mprime[8..8 + hlen].copy_from_slice(&mhash);
1351            mprime[8 + hlen..].copy_from_slice(salt);
1352            let h2 = hash_msg(hash_bits, &mprime)?;
1353            if h2[..] != *h {
1354                return Err(crate::Error::VerificationFailed);
1355            }
1356            Ok(())
1357        }
1358
1359        /// 验证 RSA PKCS#1 v1.5 签名(严格 padding 检查,防 Bleichenbacher)。
1360        pub fn verify_pkcs1v15(
1361            &self,
1362            hash_bits: u16,
1363            message: &[u8],
1364            signature: &[u8],
1365        ) -> Result<(), crate::Error> {
1366            let em = self.public_exponentiate(signature)?;
1367            let mhash = hash_msg(hash_bits, message)?;
1368            let prefix = digestinfo_prefix(hash_bits)?;
1369            let tlen = prefix.len() + mhash.len();
1370            let emlen = em.len();
1371            if emlen < tlen + 11 {
1372                return Err(crate::Error::VerificationFailed);
1373            }
1374            // 逐字节重构期望 EM 并全等比较(拒绝非规范 0xFF 串等一切变体)
1375            let mut expected = vec![0u8; emlen];
1376            expected[0] = 0x00;
1377            expected[1] = 0x01;
1378            for b in expected[2..emlen - tlen - 1].iter_mut() {
1379                *b = 0xff;
1380            }
1381            expected[emlen - tlen - 1] = 0x00;
1382            expected[emlen - tlen..emlen - mhash.len()].copy_from_slice(prefix);
1383            expected[emlen - mhash.len()..].copy_from_slice(&mhash);
1384            if em != expected {
1385                return Err(crate::Error::VerificationFailed);
1386            }
1387            Ok(())
1388        }
1389    }
1390}
1391
1392#[cfg(test)]
1393mod tests {
1394    use super::*;
1395
1396    /// 非规范压缩编码必须拒绝(RFC 8032 §5.1.3):y ∈ [p, 2^255) 的
1397    /// 32 字节编码不是合法点编码。此前实现会对 y 条件减 p 后静默接受,
1398    /// 给同一验证结果留下第二种签名/公钥编码(malleability 面)。
1399    #[test]
1400    fn ed25519_decompress_rejects_noncanonical_y() {
1401        // y' = p(2^255 − 19):LE 字节 = ed ff…ff 7f
1402        let mut b = [0xffu8; 32];
1403        b[0] = 0xed;
1404        b[31] = 0x7f;
1405        assert!(
1406            matches!(
1407                ed25519::decompress(&b),
1408                Err(crate::Error::VerificationFailed)
1409            ),
1410            "y == p must be rejected"
1411        );
1412        // y' = p + 18 = 2^255 − 1(该区间最大值)
1413        let mut b2 = [0xffu8; 32];
1414        b2[31] = 0x7f;
1415        assert!(ed25519::decompress(&b2).is_err());
1416        // 区间内其余值同样拒绝
1417        let mut b3 = [0xffu8; 32];
1418        b3[0] = 0xf0;
1419        b3[31] = 0x7f;
1420        assert!(ed25519::decompress(&b3).is_err());
1421    }
1422
1423    /// 严格化不得误伤:恒等元 (0,1) 的规范编码(y=1,x 偶)必须仍可
1424    /// 解码——验证方程允许 R = 恒等元。
1425    #[test]
1426    fn ed25519_decompress_accepts_canonical_identity() {
1427        let mut id = [0u8; 32];
1428        id[0] = 0x01;
1429        let p = ed25519::decompress(&id).expect("canonical identity decodes");
1430        // t = x·y = 0、z = 1
1431        assert!(p.x.is_zero());
1432        assert_eq!(p.compress(), id, "identity round-trips");
1433    }
1434
1435    /// 基点压缩编码往返(decompress 严格化后的规范路径回归)。
1436    #[test]
1437    fn ed25519_base_point_round_trip() {
1438        let g = ed25519::base_point();
1439        let enc = g.compress();
1440        assert_eq!(enc, ed25519::G_COMPRESSED);
1441        let back = ed25519::decompress(&enc).expect("base point decodes");
1442        assert_eq!(back.compress(), enc);
1443    }
1444}