libsmx 0.3.0

Pure-Rust, no_std, constant-time SM2/SM3/SM4/SM9 Chinese cryptography (GB/T 32918/32905/32907/38635)
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
//! SM2 椭圆曲线公钥密码算法(GB/T 32918.1-5-2016)
//!
//! 实现内容:
//! - 密钥生成(§6.1)
//! - Z 值与消息摘要计算(§5.5)
//! - 数字签名与验签(§6.2, §6.3)
//! - 公钥加密与解密(§7.1, §7.2)
//!
//! # 合规说明
//! 签名必须使用 `SM3(Z||M)` 作为消息摘要,而非直接 `SM3(M)`。
//! 所有公开签名接口均要求调用方提供用户 ID(或已计算好的 Z 值)。

pub mod der;
pub mod ec;
pub mod field;
pub mod kdf;
pub mod key_exchange;

#[cfg(feature = "alloc")]
use alloc::vec::Vec;

use crypto_bigint::{Zero, U256};
use rand_core::RngCore;
use subtle::ConstantTimeEq;
use zeroize::{Zeroize, ZeroizeOnDrop};

use crate::error::Error;
use crate::sm2::ec::{multi_scalar_mul, AffinePoint, JacobianPoint};
use crate::sm2::field::{
    fn_add, fn_inv, fn_mul, fn_sub, fp_to_bytes, Fn, CURVE_A, CURVE_B, GROUP_ORDER,
    GROUP_ORDER_MINUS_1, GX, GY,
};
use crate::sm3::Sm3Hasher;

/// SM2 默认用户可辨别标识(GB/T 32918.2-2016 §A.2 示例值)
///
/// 当调用方无自定义 ID 时,应使用此常量作为 `sign_message` / `verify_message` 的 `id` 参数。
pub const DEFAULT_ID: &[u8] = b"1234567812345678";

// ── 私钥类型 ──────────────────────────────────────────────────────────────────

/// SM2 私钥(32 字节,离开作用域自动清零)
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
pub struct PrivateKey {
    bytes: [u8; 32],
}

impl PrivateKey {
    /// 从字节构造私钥(验证 d ∈ [1, n-2])
    pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, Error> {
        let d = U256::from_be_slice(bytes);
        if bool::from(d.is_zero()) || d >= GROUP_ORDER_MINUS_1 {
            return Err(Error::InvalidPrivateKey);
        }
        Ok(PrivateKey { bytes: *bytes })
    }

    /// 以字节引用访问私钥(不泄露值所有权)
    pub fn as_bytes(&self) -> &[u8; 32] {
        &self.bytes
    }

    /// 计算对应公钥(65 字节,04||x||y)
    pub fn public_key(&self) -> [u8; 65] {
        let d = U256::from_be_slice(&self.bytes);
        let pub_jac = JacobianPoint::scalar_mul_g(&d);
        // Reason: 私钥合法性已在构造时验证,scalar_mul_g 结果不会是无穷远点
        let pub_aff = pub_jac
            .to_affine()
            .expect("valid private key produces valid public key");
        pub_aff.to_bytes()
    }
}

// ── 密钥生成 ──────────────────────────────────────────────────────────────────

/// 生成 SM2 密钥对(私钥 + 公钥 65 字节)
///
/// 符合 GB/T 32918.1-2016 §6.1
/// 需要提供 `rand_core::RngCore` 实现(如 `rand::rngs::OsRng`)。
pub fn generate_keypair<R: RngCore>(rng: &mut R) -> (PrivateKey, [u8; 65]) {
    loop {
        let mut d_bytes = [0u8; 32];
        rng.fill_bytes(&mut d_bytes);
        let d = U256::from_be_slice(&d_bytes);
        // 私钥 d ∈ [1, n-2]
        if bool::from(d.is_zero()) || d >= GROUP_ORDER_MINUS_1 {
            d_bytes.zeroize();
            continue;
        }
        // Reason: 私钥满足范围约束,PrivateKey::from_bytes 不会失败
        let priv_key = PrivateKey { bytes: d_bytes };
        let pub_key = priv_key.public_key();
        return (priv_key, pub_key);
    }
}

// ── Z 值计算(GB/T 32918.2-2016 §5.5)────────────────────────────────────────

/// 计算用户标识的 Z 值
///
/// Z = SM3(ENTL || ID || a || b || Gx || Gy || Px || Py)
///
/// # 参数
/// - `id`: 用户可辨别标识(通常使用 `b"1234567812345678"` 作为���认值)
/// - `pub_key`: 用户公钥(65 字节,04||x||y)
pub fn get_z(id: &[u8], pub_key: &[u8; 65]) -> [u8; 32] {
    // ENTL:ID 长度(比特数),2 字节大端
    let entl = (id.len() * 8) as u16;
    let mut h = Sm3Hasher::new();
    h.update(&entl.to_be_bytes());
    h.update(id);
    h.update(&fp_to_bytes(&CURVE_A));
    h.update(&fp_to_bytes(&CURVE_B));
    h.update(&fp_to_bytes(&GX));
    h.update(&fp_to_bytes(&GY));
    h.update(&pub_key[1..33]); // Px
    h.update(&pub_key[33..65]); // Py
    h.finalize()
}

/// 计算消息摘要 e = SM3(Z || M)
///
/// 符合 GB/T 32918.2-2016 §5.5
pub fn get_e(z: &[u8; 32], msg: &[u8]) -> [u8; 32] {
    let mut h = Sm3Hasher::new();
    h.update(z);
    h.update(msg);
    h.finalize()
}

// ── 数字签名(GB/T 32918.2-2016 §6.2)───────────────────────────────────────

/// SM2 签名(使用指定随机数 k,用于确定性测试和标准向量验证)
///
/// # 参数
/// - `e`: 消息摘要 e = SM3(Z||M)(32 字节)
/// - `pri_key`: 私钥
/// - `k`: 随机数 k ∈ [1, n-1]
///
/// # 返回
/// 64 字节签名 r||s,或错误码
pub fn sign_with_k(e: &[u8; 32], pri_key: &PrivateKey, k: &U256) -> Result<[u8; 64], Error> {
    let d = U256::from_be_slice(pri_key.as_bytes());

    // 步骤 2:计算 (x1, y1) = k·G
    let kg_aff = JacobianPoint::scalar_mul_g(k)
        .to_affine()
        .map_err(|_| Error::InvalidSignature)?;
    let x1 = fp_to_bytes(&kg_aff.x);

    // 步骤 3:r = (e + x1) mod n
    let e_val = U256::from_be_slice(e);
    let x1_val = U256::from_be_slice(&x1);
    let r_fn = fn_add(&Fn::new(&e_val), &Fn::new(&x1_val));
    let r = r_fn.retrieve();

    // r == 0 或 r+k == n 时无效(此随机数不可用)
    if bool::from(r.is_zero()) {
        return Err(Error::InvalidSignature);
    }
    if fn_add(&r_fn, &Fn::new(k)).retrieve().is_zero().into() {
        return Err(Error::InvalidSignature);
    }

    // 步骤 4:s = (1+d)^-1 · (k - r·d) mod n
    let d_fn = Fn::new(&d);
    let one_plus_d = fn_add(&Fn::ONE, &d_fn);
    let inv = fn_inv(&one_plus_d).ok_or(Error::InvalidPrivateKey)?;
    let rd = fn_mul(&r_fn, &d_fn);
    let s_fn = fn_mul(&inv, &fn_sub(&Fn::new(k), &rd));
    let s = s_fn.retrieve();

    if bool::from(s.is_zero()) {
        return Err(Error::InvalidSignature);
    }

    let mut sig = [0u8; 64];
    sig[..32].copy_from_slice(&r.to_be_bytes());
    sig[32..].copy_from_slice(&s.to_be_bytes());
    Ok(sig)
}

/// SM2 签名(标准接口,随机 k)
///
/// # 合规说明
/// 此函数接受预计算好的消息摘要 `e = SM3(Z||M)`。
/// 调用方应先用 `get_z` + `get_e` 计算 e,确保满足 GB/T 32918.2-2016 §5.5。
/// SM2 签名(便捷接口,自动计算 Z 值与消息摘要)
///
/// 等同于 `get_z` + `get_e` + `sign` 的组合,适合不需要手动管理摘要的场景。
///
/// # 参数
/// - `msg`: 原始消息
/// - `id`: 用户可辨别标识(通常使用 `b"1234567812345678"`)
/// - `pri_key`: 私钥
/// - `rng`: 随机数生成器
///
/// # 合规说明
/// 内部自动计算 `Z = SM3(ENTL||ID||a||b||Gx||Gy||Px||Py)` 和 `e = SM3(Z||M)`,
/// 符合 GB/T 32918.2-2016 §5.5。
pub fn sign_message<R: RngCore>(
    msg: &[u8],
    id: &[u8],
    pri_key: &PrivateKey,
    rng: &mut R,
) -> [u8; 64] {
    let pub_key = pri_key.public_key();
    let z = get_z(id, &pub_key);
    let e = get_e(&z, msg);
    sign(&e, pri_key, rng)
}

/// SM2 验签(便捷接口,自动计算 Z 值与消息摘要)
///
/// 等同于 `get_z` + `get_e` + `verify` 的组合。
///
/// # 参数
/// - `msg`: 原始消息
/// - `id`: 用户可辨别标识
/// - `pub_key`: 公钥(65 字节,04||x||y)
/// - `sig`: 签名(64 字节,r||s)
pub fn verify_message(
    msg: &[u8],
    id: &[u8],
    pub_key: &[u8; 65],
    sig: &[u8; 64],
) -> Result<(), Error> {
    let z = get_z(id, pub_key);
    let e = get_e(&z, msg);
    verify(&e, pub_key, sig)
}

/// SM2 签名(标准接口,随机 k)
///
/// # 合规说明
/// 此函数接受预计算好的消息摘要 `e = SM3(Z||M)`。
/// 调用方应先用 `get_z` + `get_e` 计算 e,确保满足 GB/T 32918.2-2016 §5.5。
pub fn sign<R: RngCore>(e: &[u8; 32], pri_key: &PrivateKey, rng: &mut R) -> [u8; 64] {
    loop {
        let mut k_bytes = [0u8; 32];
        rng.fill_bytes(&mut k_bytes);
        let k = U256::from_be_slice(&k_bytes);
        k_bytes.zeroize();
        if bool::from(k.is_zero()) || k >= GROUP_ORDER {
            continue;
        }
        if let Ok(sig) = sign_with_k(e, pri_key, &k) {
            return sig;
        }
    }
}

// ── 签名验证(GB/T 32918.2-2016 §6.3)───────────────────────────────────────

/// SM2 验签
///
/// # 参数
/// - `e`: 消息摘要 e = SM3(Z||M)(32 字节)
/// - `pub_key`: 公钥(65 字节,04||x||y)
/// - `sig`: 签名(64 字��,r||s)
///
/// # 返回
/// 验证通过返回 `Ok(())`,否则返回错误码
pub fn verify(e: &[u8; 32], pub_key: &[u8; 65], sig: &[u8; 64]) -> Result<(), Error> {
    let r = U256::from_be_slice(&sig[..32]);
    let s = U256::from_be_slice(&sig[32..]);
    let n = GROUP_ORDER;

    // 步骤 1:r, s ∈ [1, n-1]
    if bool::from(r.is_zero()) || r >= n || bool::from(s.is_zero()) || s >= n {
        return Err(Error::InvalidSignature);
    }

    // 步骤 2:t = (r + s) mod n,t ≠ 0
    let t_fn = fn_add(&Fn::new(&r), &Fn::new(&s));
    let t = t_fn.retrieve();
    if bool::from(t.is_zero()) {
        return Err(Error::VerifyFailed);
    }

    // 步骤 3:P = s·G + t·PA
    let pa = AffinePoint::from_bytes(pub_key)?;
    let point = multi_scalar_mul(&s, &t, &pa)?;

    // 步骤 4:R = (e + P.x) mod n,验证 R == r
    let e_val = U256::from_be_slice(e);
    let px_val = U256::from_be_slice(&fp_to_bytes(&point.x));
    let r_check = fn_add(&Fn::new(&e_val), &Fn::new(&px_val)).retrieve();

    // 常量时间比较防时序侧信道
    // Reason: r 和 r_check 都是 U256(32 字节),ct_eq 是字节级常量时间操作
    if r.to_be_bytes().ct_eq(&r_check.to_be_bytes()).unwrap_u8() != 1 {
        return Err(Error::VerifyFailed);
    }
    Ok(())
}

// ── 公钥加密(GB/T 32918.4-2016 §7.1)──────────────────────────────────────

/// SM2 公钥加密
///
/// 输出格式:C1||C3||C2(新格式,GB/T 32918.4-2016 §6.1)
/// - C1:65 字节,04||x||y(随机点 k·G)
/// - C3:32 字节,SM3(x2||M||y2)
/// - C2:len(M) 字节,M ⊕ KDF(x2||y2, len(M))
///
/// 需要 `alloc` feature。
#[cfg(feature = "alloc")]
pub fn encrypt<R: RngCore>(
    pub_key: &[u8; 65],
    message: &[u8],
    rng: &mut R,
) -> Result<Vec<u8>, Error> {
    let pa = AffinePoint::from_bytes(pub_key)?;

    loop {
        // A1:生成随机 k ∈ [1, n-1]
        let mut k_bytes = [0u8; 32];
        rng.fill_bytes(&mut k_bytes);
        let k = U256::from_be_slice(&k_bytes);
        k_bytes.zeroize();
        if bool::from(k.is_zero()) || k >= GROUP_ORDER {
            continue;
        }

        // A2:C1 = k·G
        let c1_aff = match JacobianPoint::scalar_mul_g(&k).to_affine() {
            Ok(p) => p,
            Err(_) => continue,
        };
        let c1 = c1_aff.to_bytes();

        // A3:计算 k·PA
        let pa_jac = JacobianPoint::from_affine(&pa);
        let kpa_aff = match JacobianPoint::scalar_mul(&k, &pa_jac).to_affine() {
            Ok(p) => p,
            Err(_) => continue,
        };
        let x2 = fp_to_bytes(&kpa_aff.x);
        let y2 = fp_to_bytes(&kpa_aff.y);

        // A4:t = KDF(x2||y2, klen)
        let mut z_input = [0u8; 64];
        z_input[..32].copy_from_slice(&x2);
        z_input[32..].copy_from_slice(&y2);
        let t = kdf::kdf(&z_input, message.len());

        // t 全零时重新选 k
        if t.iter().all(|&b| b == 0) {
            continue;
        }

        // A5:C2 = M ⊕ t
        let c2: Vec<u8> = message.iter().zip(t.iter()).map(|(&m, &k)| m ^ k).collect();

        // A6:C3 = SM3(x2||M||y2)
        let mut h = Sm3Hasher::new();
        h.update(&x2);
        h.update(message);
        h.update(&y2);
        let c3 = h.finalize();

        // 输出 C1||C3||C2
        let mut output = Vec::with_capacity(65 + 32 + message.len());
        output.extend_from_slice(&c1);
        output.extend_from_slice(&c3);
        output.extend_from_slice(&c2);
        return Ok(output);
    }
}

// ── 公钥解密(GB/T 32918.4-2016 §7.2)──────────────────────────────────────

/// SM2 公钥解密(新格式 C1||C3||C2)
///
/// 解密后对 C3 进行常量时间验证,防止 padding oracle 攻击。
/// 需要 `alloc` feature。
#[cfg(feature = "alloc")]
pub fn decrypt(pri_key: &PrivateKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
    // 最短:C1(65) + C3(32) + C2(0+) = 97
    if ciphertext.len() < 97 {
        return Err(Error::InvalidInputLength);
    }

    let d = U256::from_be_slice(pri_key.as_bytes());

    // 解析 C1(65 字节)
    let c1_bytes: [u8; 65] = ciphertext[0..65].try_into().unwrap();
    let c1 = AffinePoint::from_bytes(&c1_bytes)?;

    // 解析 C3(32 字节)和 C2
    let c3_expected: [u8; 32] = ciphertext[65..97].try_into().unwrap();
    let c2 = &ciphertext[97..];

    // 计算 d·C1
    let c1_jac = JacobianPoint::from_affine(&c1);
    let dc1_aff = JacobianPoint::scalar_mul(&d, &c1_jac).to_affine()?;
    let x2 = fp_to_bytes(&dc1_aff.x);
    let y2 = fp_to_bytes(&dc1_aff.y);

    // t = KDF(x2||y2, klen)
    let mut z_input = [0u8; 64];
    z_input[..32].copy_from_slice(&x2);
    z_input[32..].copy_from_slice(&y2);
    let t = kdf::kdf(&z_input, c2.len());

    if t.iter().all(|&b| b == 0) {
        return Err(Error::DecryptFailed);
    }

    // 恢复候选明文 M' = C2 ⊕ t
    let m: Vec<u8> = c2.iter().zip(t.iter()).map(|(&c, &k)| c ^ k).collect();

    // 验证 C3 = SM3(x2||M'||y2)(常量时间比较)
    let mut h = Sm3Hasher::new();
    h.update(&x2);
    h.update(&m);
    h.update(&y2);
    let c3_computed = h.finalize();

    // Reason: 先验证 C3 再返回明文,防止 chosen-ciphertext 攻击
    if c3_expected.ct_eq(&c3_computed).unwrap_u8() != 1 {
        return Err(Error::DecryptFailed);
    }
    Ok(m)
}

#[cfg(test)]
mod tests {
    use super::*;

    struct FakeRng([u8; 32]);
    impl RngCore for FakeRng {
        fn next_u32(&mut self) -> u32 {
            0
        }
        fn next_u64(&mut self) -> u64 {
            0
        }
        fn fill_bytes(&mut self, dest: &mut [u8]) {
            for (i, b) in dest.iter_mut().enumerate() {
                *b = self.0[i % 32];
            }
        }
        fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
            self.fill_bytes(dest);
            Ok(())
        }
    }

    #[test]
    fn test_get_z_deterministic() {
        let pub_key = [0x04u8; 65];
        let z1 = get_z(DEFAULT_ID, &pub_key);
        let z2 = get_z(DEFAULT_ID, &pub_key);
        assert_eq!(z1, z2);
    }

    #[test]
    fn test_sign_verify_roundtrip() {
        // 使用 GB/T 32918 附录 A 的私钥示例(私钥需在 [1, n-2])
        let d_bytes: [u8; 32] = [
            0x39, 0x45, 0x20, 0x8f, 0x7b, 0x21, 0x44, 0xb1, 0x3f, 0x36, 0xe3, 0x8a, 0xc6, 0xd3,
            0x9f, 0x95, 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xb5, 0x1a, 0x42, 0xfb, 0x81, 0xef,
            0x4d, 0xf7, 0xc5, 0xb8,
        ];
        let pri_key = PrivateKey::from_bytes(&d_bytes).expect("私钥有效");
        let pub_key = pri_key.public_key();

        let msg = b"hello sm2";
        let z = get_z(DEFAULT_ID, &pub_key);
        let e = get_e(&z, msg);

        // 使用固定 k(仅测试用)—— k 必须 ∈ [1, n-1]
        let k_bytes: [u8; 32] = [
            0x59, 0x27, 0x6e, 0x27, 0xd5, 0x06, 0x86, 0x1a, 0x16, 0x68, 0x0f, 0x3a, 0xd9, 0xc0,
            0x2d, 0xcc, 0xef, 0x3c, 0xc1, 0xfa, 0x3c, 0xdb, 0xe4, 0xce, 0x6d, 0x54, 0xb8, 0x0d,
            0xea, 0xc1, 0xbc, 0x21,
        ];
        let k = U256::from_be_slice(&k_bytes);
        let sig = sign_with_k(&e, &pri_key, &k).expect("签名应成功");

        verify(&e, &pub_key, &sig).expect("验签应通过");
    }

    #[test]
    fn test_verify_rejects_tampered_sig() {
        let d_bytes: [u8; 32] = [
            0x39, 0x45, 0x20, 0x8f, 0x7b, 0x21, 0x44, 0xb1, 0x3f, 0x36, 0xe3, 0x8a, 0xc6, 0xd3,
            0x9f, 0x95, 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xb5, 0x1a, 0x42, 0xfb, 0x81, 0xef,
            0x4d, 0xf7, 0xc5, 0xb8,
        ];
        let pri_key = PrivateKey::from_bytes(&d_bytes).unwrap();
        let pub_key = pri_key.public_key();

        let msg = b"hello sm2";
        let z = get_z(DEFAULT_ID, &pub_key);
        let e = get_e(&z, msg);

        let k_bytes: [u8; 32] = [
            0x59, 0x27, 0x6e, 0x27, 0xd5, 0x06, 0x86, 0x1a, 0x16, 0x68, 0x0f, 0x3a, 0xd9, 0xc0,
            0x2d, 0xcc, 0xef, 0x3c, 0xc1, 0xfa, 0x3c, 0xdb, 0xe4, 0xce, 0x6d, 0x54, 0xb8, 0x0d,
            0xea, 0xc1, 0xbc, 0x21,
        ];
        let k = U256::from_be_slice(&k_bytes);
        let mut sig = sign_with_k(&e, &pri_key, &k).unwrap();

        // 篡改签名第一个字节
        sig[0] ^= 0x01;
        assert!(verify(&e, &pub_key, &sig).is_err());
    }

    #[cfg(feature = "alloc")]
    #[test]
    fn test_encrypt_decrypt_roundtrip() {
        let d_bytes: [u8; 32] = [
            0x39, 0x45, 0x20, 0x8f, 0x7b, 0x21, 0x44, 0xb1, 0x3f, 0x36, 0xe3, 0x8a, 0xc6, 0xd3,
            0x9f, 0x95, 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xb5, 0x1a, 0x42, 0xfb, 0x81, 0xef,
            0x4d, 0xf7, 0xc5, 0xb8,
        ];
        let pri_key = PrivateKey::from_bytes(&d_bytes).unwrap();
        let pub_key = pri_key.public_key();
        let msg = b"Hello, SM2 encryption!";

        // 使用固定随机数(测试专用)
        let mut rng = FakeRng([
            0x59, 0x27, 0x6e, 0x27, 0xd5, 0x06, 0x86, 0x1a, 0x16, 0x68, 0x0f, 0x3a, 0xd9, 0xc0,
            0x2d, 0xcc, 0xef, 0x3c, 0xc1, 0xfa, 0x3c, 0xdb, 0xe4, 0xce, 0x6d, 0x54, 0xb8, 0x0d,
            0xea, 0xc1, 0xbc, 0x21,
        ]);

        let ciphertext = encrypt(&pub_key, msg, &mut rng).expect("加密应成功");
        let plaintext = decrypt(&pri_key, &ciphertext).expect("解密应成功");
        assert_eq!(plaintext, msg);
    }

    #[test]
    fn test_sign_message_verify_message_roundtrip() {
        let d_bytes: [u8; 32] = [
            0x39, 0x45, 0x20, 0x8f, 0x7b, 0x21, 0x44, 0xb1, 0x3f, 0x36, 0xe3, 0x8a, 0xc6, 0xd3,
            0x9f, 0x95, 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xb5, 0x1a, 0x42, 0xfb, 0x81, 0xef,
            0x4d, 0xf7, 0xc5, 0xb8,
        ];
        let pri_key = PrivateKey::from_bytes(&d_bytes).unwrap();
        let pub_key = pri_key.public_key();

        let mut rng = FakeRng([
            0x59, 0x27, 0x6e, 0x27, 0xd5, 0x06, 0x86, 0x1a, 0x16, 0x68, 0x0f, 0x3a, 0xd9, 0xc0,
            0x2d, 0xcc, 0xef, 0x3c, 0xc1, 0xfa, 0x3c, 0xdb, 0xe4, 0xce, 0x6d, 0x54, 0xb8, 0x0d,
            0xea, 0xc1, 0xbc, 0x21,
        ]);

        let msg = b"hello sign_message";
        let sig = sign_message(msg, DEFAULT_ID, &pri_key, &mut rng);
        verify_message(msg, DEFAULT_ID, &pub_key, &sig).expect("便捷验签应通过");
    }

    #[test]
    fn test_verify_message_rejects_wrong_id() {
        let d_bytes: [u8; 32] = [
            0x39, 0x45, 0x20, 0x8f, 0x7b, 0x21, 0x44, 0xb1, 0x3f, 0x36, 0xe3, 0x8a, 0xc6, 0xd3,
            0x9f, 0x95, 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xb5, 0x1a, 0x42, 0xfb, 0x81, 0xef,
            0x4d, 0xf7, 0xc5, 0xb8,
        ];
        let pri_key = PrivateKey::from_bytes(&d_bytes).unwrap();
        let pub_key = pri_key.public_key();

        let mut rng = FakeRng([
            0x59, 0x27, 0x6e, 0x27, 0xd5, 0x06, 0x86, 0x1a, 0x16, 0x68, 0x0f, 0x3a, 0xd9, 0xc0,
            0x2d, 0xcc, 0xef, 0x3c, 0xc1, 0xfa, 0x3c, 0xdb, 0xe4, 0xce, 0x6d, 0x54, 0xb8, 0x0d,
            0xea, 0xc1, 0xbc, 0x21,
        ]);

        let msg = b"hello sign_message";
        let sig = sign_message(msg, DEFAULT_ID, &pri_key, &mut rng);
        // 用错误 ID 验签应失败
        assert!(verify_message(msg, b"wrong-id", &pub_key, &sig).is_err());
    }

    #[cfg(feature = "alloc")]
    #[test]
    fn test_decrypt_rejects_tampered_ciphertext() {
        let d_bytes: [u8; 32] = [
            0x39, 0x45, 0x20, 0x8f, 0x7b, 0x21, 0x44, 0xb1, 0x3f, 0x36, 0xe3, 0x8a, 0xc6, 0xd3,
            0x9f, 0x95, 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xb5, 0x1a, 0x42, 0xfb, 0x81, 0xef,
            0x4d, 0xf7, 0xc5, 0xb8,
        ];
        let pri_key = PrivateKey::from_bytes(&d_bytes).unwrap();
        let pub_key = pri_key.public_key();
        let msg = b"test message";

        let mut rng = FakeRng([
            0x59, 0x27, 0x6e, 0x27, 0xd5, 0x06, 0x86, 0x1a, 0x16, 0x68, 0x0f, 0x3a, 0xd9, 0xc0,
            0x2d, 0xcc, 0xef, 0x3c, 0xc1, 0xfa, 0x3c, 0xdb, 0xe4, 0xce, 0x6d, 0x54, 0xb8, 0x0d,
            0xea, 0xc1, 0xbc, 0x21,
        ]);

        let mut ciphertext = encrypt(&pub_key, msg, &mut rng).unwrap();
        // 篡改 C3 部分(字节 65..97)
        ciphertext[70] ^= 0xFF;
        assert!(decrypt(&pri_key, &ciphertext).is_err());
    }
}