Skip to main content

binius_field/fields/
rijndael.rs

1// Copyright 2024-2025 Irreducible Inc.
2// Copyright 2026 The Binius Developers
3
4use std::{
5	fmt::{Debug, Display, Formatter},
6	iter::{Product, Sum},
7	ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
8};
9
10use bytemuck::{Pod, Zeroable};
11
12use crate::{
13	ExtensionField, Field,
14	binary_field::{BinaryField, BinaryField1b, binary_field, impl_field_extension},
15	underlier::U1,
16};
17
18// These fields represent a tower based on AES GF(2^8) field (GF(256)/x^8+x^4+x^3+x+1)
19// that is isomorphically included into binary tower, i.e.:
20//  - AESTowerField16b is GF(2^16) / (x^2 + x * x_2 + 1) where `x_2` is 0x10 from
21// BinaryField8b isomorphically projected to Rijndael8b.
22//  - AESTowerField32b is GF(2^32) / (x^2 + x * x_3 + 1), where `x_3` is 0x1000 from
23//    AESTowerField16b.
24//  ...
25// `1 << 5` is the lowest single-bit element of trace 1; `1 << 7` is the only other one.
26binary_field!(pub Rijndael8b(u8), 0xD0, 1 << 5);
27
28impl Rijndael8b {
29	pub const fn new(value: u8) -> Self {
30		Self(value)
31	}
32}
33
34unsafe impl Pod for Rijndael8b {}
35
36impl_field_extension!(BinaryField1b(U1) < @3 => Rijndael8b(u8));
37
38#[cfg(test)]
39mod tests {
40	use binius_utils::{DeserializeBytes, SerializeBytes, bytes::BytesMut};
41	use proptest::{arbitrary::any, proptest};
42	use rand::prelude::*;
43
44	use super::*;
45	use crate::{Random, binary_field::tests::is_binary_field_valid_generator};
46
47	fn check_square(f: impl Field) {
48		assert_eq!(f.square(), f * f);
49	}
50
51	proptest! {
52		#[test]
53		fn test_square_8(a in any::<u8>()) {
54			check_square(Rijndael8b::from(a));
55		}
56	}
57
58	fn check_invert(f: impl Field) {
59		let inversed = f.invert_or_zero();
60		if f.is_zero() {
61			assert!(inversed.is_zero());
62		} else {
63			assert_eq!(inversed * f, Field::ONE);
64		}
65	}
66
67	proptest! {
68		#[test]
69		fn test_invert_8(a in any::<u8>()) {
70			check_invert(Rijndael8b::from(a));
71		}
72	}
73
74	fn check_mul_by_one<F: Field>(f: F) {
75		assert_eq!(F::ONE * f, f);
76		assert_eq!(f * F::ONE, f);
77	}
78
79	fn check_commutative<F: Field>(f_1: F, f_2: F) {
80		assert_eq!(f_1 * f_2, f_2 * f_1);
81	}
82
83	fn check_associativity_and_lineraity<F: Field>(f_1: F, f_2: F, f_3: F) {
84		assert_eq!(f_1 * (f_2 * f_3), (f_1 * f_2) * f_3);
85		assert_eq!(f_1 * (f_2 + f_3), f_1 * f_2 + f_1 * f_3);
86	}
87
88	fn check_mul<F: Field>(f_1: F, f_2: F, f_3: F) {
89		check_mul_by_one(f_1);
90		check_mul_by_one(f_2);
91		check_mul_by_one(f_3);
92
93		check_commutative(f_1, f_2);
94		check_commutative(f_1, f_3);
95		check_commutative(f_2, f_3);
96
97		check_associativity_and_lineraity(f_1, f_2, f_3);
98		check_associativity_and_lineraity(f_1, f_3, f_2);
99		check_associativity_and_lineraity(f_2, f_1, f_3);
100		check_associativity_and_lineraity(f_2, f_3, f_1);
101		check_associativity_and_lineraity(f_3, f_1, f_2);
102		check_associativity_and_lineraity(f_3, f_2, f_1);
103	}
104
105	proptest! {
106		#[test]
107		fn test_mul_8(a in any::<u8>(), b in any::<u8>(), c in any::<u8>()) {
108			check_mul(Rijndael8b::from(a), Rijndael8b::from(b), Rijndael8b::from(c));
109		}
110	}
111
112	#[test]
113	fn test_multiplicative_generators() {
114		assert!(is_binary_field_valid_generator::<Rijndael8b>());
115	}
116
117	#[test]
118	fn test_serialization() {
119		let mut buffer = BytesMut::new();
120		let mut rng = StdRng::seed_from_u64(0);
121		let aes8 = Rijndael8b::random(&mut rng);
122
123		SerializeBytes::serialize(&aes8, &mut buffer).unwrap();
124
125		let mut read_buffer = buffer.freeze();
126
127		assert_eq!(Rijndael8b::deserialize(&mut read_buffer).unwrap(), aes8);
128	}
129}