From b292cec08876c76075e7abb17e13a1b516a23476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=88=AA=E5=AE=87?= <3364451258@qq.com> Date: Tue, 16 Jun 2026 23:31:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20GF(2^8)=20Galois=20=E5=9F=9F=E8=BF=90?= =?UTF-8?q?=E7=AE=97=20+=20=E9=A2=84=E8=AE=A1=E7=AE=97=20exp/log=20?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/src/ecc/galois.rs | 167 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 1 deletion(-) diff --git a/core/src/ecc/galois.rs b/core/src/ecc/galois.rs index 6fe9484..0130542 100644 --- a/core/src/ecc/galois.rs +++ b/core/src/ecc/galois.rs @@ -1 +1,166 @@ -// FIXME: GF(2⁸) Galois 域运算 — Task 2 +/// GF(2⁸) Galois 域运算 +/// 本原多项式: x⁸ + x⁴ + x³ + x² + 1 = 0x11D +/// 生成元 α = 0x02 + +use std::sync::OnceLock; + +fn exp_table() -> &'static [u8; 512] { + static TABLE: OnceLock<[u8; 512]> = OnceLock::new(); + TABLE.get_or_init(|| { + let mut table = [0u8; 512]; + let mut x = 1u8; + for i in 0..255 { + table[i] = x; + table[i + 255] = x; // 双倍长度避免 % 255 + let next = (x as u16) << 1; + x = if next >= 0x100 { + (next ^ 0x1D) as u8 + } else { + next as u8 + }; + } + table[510] = table[255]; + table[511] = table[256]; + table + }) +} + +fn log_table() -> &'static [u8; 256] { + static TABLE: OnceLock<[u8; 256]> = OnceLock::new(); + TABLE.get_or_init(|| { + let mut table = [0u8; 256]; + let mut x = 1u8; + for i in 0..255 { + table[x as usize] = i; + let next = (x as u16) << 1; + x = if next >= 0x100 { + (next ^ 0x1D) as u8 + } else { + next as u8 + }; + } + table + }) +} + +/// GF(2⁸) 加法 = 异或 +#[inline] +pub fn add(a: u8, b: u8) -> u8 { + a ^ b +} + +/// GF(2⁸) 减法 = 异或(同加法) +#[inline] +pub fn sub(a: u8, b: u8) -> u8 { + a ^ b +} + +/// GF(2⁸) 乘法:a * b +pub fn mul(a: u8, b: u8) -> u8 { + if a == 0 || b == 0 { + return 0; + } + let log_a = log_table()[a as usize] as usize; + let log_b = log_table()[b as usize] as usize; + exp_table()[log_a + log_b] +} + +/// GF(2⁸) 除法:a / b +pub fn div(a: u8, b: u8) -> u8 { + if a == 0 { + return 0; + } + if b == 0 { + panic!("GF(2⁸) 除以零"); + } + let log_a = log_table()[a as usize] as usize; + let log_b = log_table()[b as usize] as usize; + let diff = (log_a + 255 - log_b) % 255; + exp_table()[diff] +} + +/// GF(2⁸) 幂运算:base^exp +pub fn pow(base: u8, exp: usize) -> u8 { + if exp == 0 { + return 1; + } + if base == 0 { + return 0; + } + let log_b = log_table()[base as usize] as usize; + exp_table()[(log_b * exp) % 255] +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_mul_basic() { + // 2 * 3 = 6 in GF(2^8) + assert_eq!(mul(2, 3), 6); + // 0xFF * 0x01 = 0xFF + assert_eq!(mul(0xFF, 1), 0xFF); + // 任何数乘 0 = 0 + assert_eq!(mul(0xA5, 0), 0); + } + + #[test] + fn test_mul_commutative() { + for a in 0..=255u8 { + for b in (a..=255u8).step_by(17) { + assert_eq!(mul(a, b), mul(b, a), + "交换律失败: {:02X} * {:02X}", a, b); + } + } + } + + #[test] + fn test_mul_associative() { + let cases = [(3, 5, 7), (0xFF, 2, 4), (1, 1, 1), (0x80, 0x40, 0x20)]; + for (a, b, c) in cases { + assert_eq!(mul(mul(a, b), c), mul(a, mul(b, c)), + "结合律失败: {:02X} * {:02X} * {:02X}", a, b, c); + } + } + + #[test] + fn test_div_inverse() { + for a in 1..=255u8 { + let inv = div(1, a); + assert_eq!(mul(a, inv), 1, + "逆元失败: {:02X} * {:02X} != 1", a, inv); + } + } + + #[test] + fn test_div_mul_consistency() { + for a in 1..=255u8 { + for b in (1..=255u8).step_by(17) { + let q = div(a, b); + assert_eq!(mul(q, b), a, + "除乘一致性失败: {:02X} / {:02X} = {:02X}", a, q, b); + } + } + } + + #[test] + fn test_add_sub() { + for a in 0..=255u8 { + for b in 0..=255u8 { + assert_eq!(add(a, b), sub(a, b)); + assert_eq!(sub(add(a, b), b), a); + } + } + } + + #[test] + fn test_pow() { + // α^0 = 1 + assert_eq!(pow(2, 0), 1); + // α^1 = 2 + assert_eq!(pow(2, 1), 2); + // α^7 * α^2 = α^9 + assert_eq!(mul(pow(2, 7), pow(2, 2)), pow(2, 9)); + } +}