准备发布 v0.1.0
- 添加 Apache-2.0 许可证 - 添加 CHANGELOG.md 变更日志 - 添加 SECURITY.md 安全策略 - 添加 README.zh-CN.md 中文文档 - 添加 rustfmt.toml 代码格式配置 - 添加 scripts/pre_publish_check.sh 发布检查脚本 - 更新 Cargo.toml 元数据(分类、关键词、文档链接) - 完善 README.md 示例代码 - 优化 SM2/SM9 性能和测试覆盖率
This commit is contained in:
+85
-33
@@ -1,9 +1,9 @@
|
||||
//! SM9 BN256 六次/十二次扩域 Fp6 / Fp12
|
||||
//!
|
||||
//! 塔式扩域:
|
||||
//! Fp2 = Fp[u]/(u²+2)
|
||||
//! Fp6 = Fp2[v]/(v³-u) 即 v³ = u
|
||||
//! Fp12 = Fp6[w]/(w²-v) 即 w² = v
|
||||
//! `Fp2 = Fp[u]/(u²+2)`
|
||||
//! `Fp6 = Fp2[v]/(v³-u)` 即 v³ = u
|
||||
//! `Fp12 = Fp6[w]/(w²-v)` 即 w² = v
|
||||
//!
|
||||
//! Frobenius 系数为编译期常量,源自 GB/T 38635.1-2020 及参考实现。
|
||||
|
||||
@@ -527,7 +527,6 @@ pub fn fp12_mul_by_line(f: &Fp12, l: &LineEval) -> Fp12 {
|
||||
fp12_mul(f, &line_fp12)
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -592,15 +591,25 @@ mod tests {
|
||||
|
||||
/// 验证稀疏线函数乘法与全量 fp12_mul 结果一致
|
||||
#[test]
|
||||
fn test_fp12_mul_by_line_matches_full_mul() { // 构造一个非平凡的 f
|
||||
fn test_fp12_mul_by_line_matches_full_mul() {
|
||||
// 构造一个非平凡的 f
|
||||
let f = Fp12 {
|
||||
c0: Fp6 {
|
||||
c0: Fp2 { c0: Fp::ONE, c1: Fp::ONE },
|
||||
c1: Fp2 { c0: Fp::ONE, c1: Fp::ZERO },
|
||||
c0: Fp2 {
|
||||
c0: Fp::ONE,
|
||||
c1: Fp::ONE,
|
||||
},
|
||||
c1: Fp2 {
|
||||
c0: Fp::ONE,
|
||||
c1: Fp::ZERO,
|
||||
},
|
||||
c2: Fp2::ZERO,
|
||||
},
|
||||
c1: Fp6 {
|
||||
c0: Fp2 { c0: Fp::ZERO, c1: Fp::ONE },
|
||||
c0: Fp2 {
|
||||
c0: Fp::ZERO,
|
||||
c1: Fp::ONE,
|
||||
},
|
||||
c1: Fp2::ZERO,
|
||||
c2: Fp2::ZERO,
|
||||
},
|
||||
@@ -608,9 +617,18 @@ mod tests {
|
||||
|
||||
// 构造非零线函数
|
||||
let l = LineEval {
|
||||
a: Fp2 { c0: Fp::ONE, c1: Fp::ONE },
|
||||
b: Fp2 { c0: Fp::ONE, c1: Fp::ZERO },
|
||||
c: Fp2 { c0: Fp::ZERO, c1: Fp::ONE },
|
||||
a: Fp2 {
|
||||
c0: Fp::ONE,
|
||||
c1: Fp::ONE,
|
||||
},
|
||||
b: Fp2 {
|
||||
c0: Fp::ONE,
|
||||
c1: Fp::ZERO,
|
||||
},
|
||||
c: Fp2 {
|
||||
c0: Fp::ZERO,
|
||||
c1: Fp::ONE,
|
||||
},
|
||||
};
|
||||
|
||||
// 稀疏乘法结果
|
||||
@@ -619,8 +637,16 @@ mod tests {
|
||||
// 构造全量 Fp12 线函数并做全量乘法(与 fp12_mul_by_line slot 保持一致)
|
||||
// 槽位约定:a→c0.c0(1), b→c1.c1(vw), c→c1.c2(v²w)
|
||||
let line_full = Fp12 {
|
||||
c0: Fp6 { c0: l.a, c1: Fp2::ZERO, c2: Fp2::ZERO },
|
||||
c1: Fp6 { c0: Fp2::ZERO, c1: l.b, c2: l.c },
|
||||
c0: Fp6 {
|
||||
c0: l.a,
|
||||
c1: Fp2::ZERO,
|
||||
c2: Fp2::ZERO,
|
||||
},
|
||||
c1: Fp6 {
|
||||
c0: Fp2::ZERO,
|
||||
c1: l.b,
|
||||
c2: l.c,
|
||||
},
|
||||
};
|
||||
let full = fp12_mul(&f, &line_full);
|
||||
|
||||
@@ -632,17 +658,34 @@ mod tests {
|
||||
fn test_frob_w3_derivation() {
|
||||
// 验证 fp12 Frobenius 一致性:frob_p(frob_p(f)) == frob_p2(f)
|
||||
let f = Fp12 {
|
||||
c0: Fp6 { c0: Fp2 { c0: Fp::ONE, c1: Fp::ONE }, c1: Fp2::ONE, c2: Fp2::ZERO },
|
||||
c1: Fp6 { c0: Fp2::ONE, c1: Fp2::ZERO, c2: Fp2::ZERO },
|
||||
c0: Fp6 {
|
||||
c0: Fp2 {
|
||||
c0: Fp::ONE,
|
||||
c1: Fp::ONE,
|
||||
},
|
||||
c1: Fp2::ONE,
|
||||
c2: Fp2::ZERO,
|
||||
},
|
||||
c1: Fp6 {
|
||||
c0: Fp2::ONE,
|
||||
c1: Fp2::ZERO,
|
||||
c2: Fp2::ZERO,
|
||||
},
|
||||
};
|
||||
let fp1 = fp12_frobenius_p(&f);
|
||||
let fp1p1 = fp12_frobenius_p(&fp1); // frob_p^2(f)
|
||||
let fp1p1 = fp12_frobenius_p(&fp1); // frob_p^2(f)
|
||||
let fp2 = fp12_frobenius_p2(&f);
|
||||
assert_eq!(fp1p1, fp2, "frob_p(frob_p(f)) != frob_p2(f):fp12 Frobenius 不一致");
|
||||
assert_eq!(
|
||||
fp1p1, fp2,
|
||||
"frob_p(frob_p(f)) != frob_p2(f):fp12 Frobenius 不一致"
|
||||
);
|
||||
|
||||
let fp2p1 = fp12_frobenius_p(&fp2); // frob_p^3(f)
|
||||
let fp2p1 = fp12_frobenius_p(&fp2); // frob_p^3(f)
|
||||
let fp3 = fp12_frobenius_p3(&f);
|
||||
assert_eq!(fp2p1, fp3, "frob_p(frob_p2(f)) != frob_p3(f):fp12_frobenius_p3 系数错误");
|
||||
assert_eq!(
|
||||
fp2p1, fp3,
|
||||
"frob_p(frob_p2(f)) != frob_p3(f):fp12_frobenius_p3 系数错误"
|
||||
);
|
||||
}
|
||||
|
||||
/// 验证 Fp6 Frobenius 保持 ONE
|
||||
@@ -662,7 +705,10 @@ mod tests {
|
||||
fn test_frob_v1_squared() {
|
||||
use crate::sm9::fields::fp2::fp2_mul;
|
||||
let v1_sq = fp2_mul(&FROB_V1_0, &FROB_V1_0);
|
||||
assert_eq!(v1_sq, FROB_V1_1, "FROB_V1_0² 应等于 FROB_V1_1(fp6 Frobenius 一致性)");
|
||||
assert_eq!(
|
||||
v1_sq, FROB_V1_1,
|
||||
"FROB_V1_0² 应等于 FROB_V1_1(fp6 Frobenius 一致性)"
|
||||
);
|
||||
}
|
||||
|
||||
/// 计算 u^{(p-1)/3} 并与 FROB_V1_0 对比(验证常量正确性)
|
||||
@@ -671,14 +717,15 @@ mod tests {
|
||||
#[test]
|
||||
fn test_frob_v1_0_value_correct() {
|
||||
use crate::sm9::fields::fp::FIELD_MODULUS;
|
||||
use crate::sm9::fields::fp2::{fp2_mul, fp2_square};
|
||||
use subtle::ConditionallySelectable;
|
||||
use crate::sm9::fields::fp2::fp2_mul;
|
||||
// 计算 u^{(p-1)/3} 其中 u = (0, 1) ∈ Fp2
|
||||
let pm1 = FIELD_MODULUS.wrapping_sub(&crypto_bigint::U256::ONE);
|
||||
let (pm1_div3, rem) = pm1.div_rem(&crypto_bigint::NonZero::new(crypto_bigint::U256::from(3u32)).unwrap());
|
||||
let (pm1_div3, rem) =
|
||||
pm1.div_rem(&crypto_bigint::NonZero::new(crypto_bigint::U256::from(3u32)).unwrap());
|
||||
assert_eq!(rem, crypto_bigint::U256::ZERO, "(p-1) 应被 3 整除");
|
||||
|
||||
let (pm1_div6, _) = pm1.div_rem(&crypto_bigint::NonZero::new(crypto_bigint::U256::from(6u32)).unwrap());
|
||||
let (pm1_div6, _) =
|
||||
pm1.div_rem(&crypto_bigint::NonZero::new(crypto_bigint::U256::from(6u32)).unwrap());
|
||||
|
||||
fn fp2_pow_exp(base: &Fp2, exp: &crypto_bigint::U256) -> Fp2 {
|
||||
use crate::sm9::fields::fp2::{fp2_mul, fp2_square};
|
||||
@@ -696,7 +743,10 @@ mod tests {
|
||||
result
|
||||
}
|
||||
|
||||
let u = Fp2 { c0: crate::sm9::fields::fp::Fp::ZERO, c1: crate::sm9::fields::fp::Fp::ONE };
|
||||
let u = Fp2 {
|
||||
c0: crate::sm9::fields::fp::Fp::ZERO,
|
||||
c1: crate::sm9::fields::fp::Fp::ONE,
|
||||
};
|
||||
// 正确的 γ_{1,1} = u^{(p-1)/3}
|
||||
let correct_v1_0 = fp2_pow_exp(&u, &pm1_div3);
|
||||
// 正确的 δ_{1,1} = u^{(p-1)/6}(FROB_W1)
|
||||
@@ -708,7 +758,8 @@ mod tests {
|
||||
|
||||
// 打印正确的常量值(以标准 32 字节大端 hex 格式,供直接写入代码)
|
||||
assert_eq!(
|
||||
correct_v1_0, FROB_V1_0,
|
||||
correct_v1_0,
|
||||
FROB_V1_0,
|
||||
"FROB_V1_0 需更新:正确值={:02X?}, FROB_W1 正确值 c0={:02X?} c1={:02X?}",
|
||||
correct_v1_0.c0.retrieve().to_be_bytes(),
|
||||
correct_w1.c0.retrieve().to_be_bytes(),
|
||||
@@ -743,24 +794,25 @@ mod g2_frob_tests {
|
||||
|
||||
let p = FIELD_MODULUS;
|
||||
let pm1 = p.wrapping_sub(&crypto_bigint::U256::ONE);
|
||||
let u = Fp2 { c0: Fp::ZERO, c1: Fp::ONE };
|
||||
let u = Fp2 {
|
||||
c0: Fp::ZERO,
|
||||
c1: Fp::ONE,
|
||||
};
|
||||
|
||||
let pm1_div2 = pm1.wrapping_shr(1);
|
||||
let u_pm1_div2 = fp2_pow_exp(&u, &pm1_div2);
|
||||
|
||||
let (pm1_div3, _) = pm1.div_rem(&crypto_bigint::NonZero::new(crypto_bigint::U256::from(3u32)).unwrap());
|
||||
let (pm1_div3, _) =
|
||||
pm1.div_rem(&crypto_bigint::NonZero::new(crypto_bigint::U256::from(3u32)).unwrap());
|
||||
let u_pm1_div3 = fp2_pow_exp(&u, &pm1_div3);
|
||||
|
||||
let pp1 = p.wrapping_add(&crypto_bigint::U256::ONE);
|
||||
let u_pm21_div3 = fp2_pow_exp(&u_pm1_div3, &pp1);
|
||||
let u_pm21_div2 = fp2_pow_exp(&u_pm1_div2, &pp1);
|
||||
|
||||
// Reason: 验证 G2 Frobenius 修正常量与计算值一致
|
||||
// u^{(p-1)/2} 应等于 G2_FROB_Y1
|
||||
assert_eq!(u_pm1_div2, G2_FROB_Y1,
|
||||
"u^(p-1)/2 应等于 G2_FROB_Y1");
|
||||
assert_eq!(u_pm1_div2, G2_FROB_Y1, "u^(p-1)/2 应等于 G2_FROB_Y1");
|
||||
// u^{(p²-1)/3} 应等于 G2_FROB_X2
|
||||
assert_eq!(u_pm21_div3, G2_FROB_X2,
|
||||
"u^(p2-1)/3 应等于 G2_FROB_X2");
|
||||
assert_eq!(u_pm21_div3, G2_FROB_X2, "u^(p2-1)/3 应等于 G2_FROB_X2");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user