1use std::{
5 fmt::{Debug, Display, Formatter},
6 iter::{Product, Sum},
7 marker::PhantomData,
8 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
9};
10
11use binius_utils::{
12 DeserializeBytes, FixedSizeSerializeBytes, SerializationError, SerializeBytes,
13 bytes::{Buf, BufMut},
14};
15use bytemuck::{Pod, Zeroable};
16
17use super::{
18 PackedExtension, PackedSubfield,
19 arithmetic_traits::InvertOrZero,
20 binary_field::{BinaryField, BinaryField1b, binary_field, impl_field_extension},
21 mul_by_binary_field_1b,
22};
23use crate::{
24 ExtensionField, Field, binary_field_arithmetic::impl_arithmetic_using_packed,
25 linear_transformation::Transformation, underlier::U1,
26};
27
28binary_field!(pub AESTowerField8b(u8), 0xD0);
36
37impl AESTowerField8b {
38 pub const fn new(value: u8) -> Self {
39 Self(value)
40 }
41}
42
43impl crate::arithmetic_traits::WideMul for AESTowerField8b {
48 type Output = Self;
49
50 #[inline]
51 fn wide_mul(a: Self, b: Self) -> Self {
52 Self::new(aes_mul_8b(a.val(), b.val()))
53 }
54
55 #[inline]
56 fn reduce(wide: Self) -> Self {
57 wide
58 }
59}
60
61#[inline]
65pub(crate) fn aes_mul_8b(lhs: u8, rhs: u8) -> u8 {
66 if lhs != 0 && rhs != 0 {
67 let log_index = AES_LOG_TABLE[lhs as usize] as usize + AES_LOG_TABLE[rhs as usize] as usize;
68 let log_index = if log_index > 254 {
71 log_index - 255
72 } else {
73 log_index
74 };
75 unsafe { *AES_EXP_TABLE.get_unchecked(log_index) }
77 } else {
78 0
79 }
80}
81
82#[rustfmt::skip]
83const AES_EXP_TABLE: [u8; 256] = [
84 0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, 0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35,
85 0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, 0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa,
86 0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26, 0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31,
87 0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, 0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd,
88 0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, 0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88,
89 0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f, 0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a,
90 0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, 0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3,
91 0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, 0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0,
92 0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2, 0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41,
93 0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, 0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75,
94 0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, 0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80,
95 0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf, 0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54,
96 0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, 0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca,
97 0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, 0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e,
98 0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c, 0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17,
99 0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, 0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x01,
100];
101
102#[rustfmt::skip]
103const AES_LOG_TABLE: [u8; 256] = [
104 0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
105 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
106 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
107 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
108 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
109 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
110 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
111 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
112 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
113 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
114 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
115 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
116 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
117 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
118 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
119 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07,
120];
121
122unsafe impl Pod for AESTowerField8b {}
123
124impl_field_extension!(BinaryField1b(U1) < @3 => AESTowerField8b(u8));
125
126mul_by_binary_field_1b!(AESTowerField8b);
127
128impl_arithmetic_using_packed!(AESTowerField8b);
129
130pub struct SubfieldTransformer<IF, OF, T> {
135 inner_transform: T,
136 _ip_pd: PhantomData<IF>,
137 _op_pd: PhantomData<OF>,
138}
139
140impl<IF, OF, IEP, OEP, T> Transformation<IEP, OEP> for SubfieldTransformer<IF, OF, T>
141where
142 IF: Field,
143 OF: Field,
144 IEP: PackedExtension<IF>,
145 OEP: PackedExtension<OF>,
146 T: Transformation<PackedSubfield<IEP, IF>, PackedSubfield<OEP, OF>>,
147{
148 fn transform(&self, input: &IEP) -> OEP {
149 OEP::cast_ext(self.inner_transform.transform(IEP::cast_base_ref(input)))
150 }
151}
152
153impl SerializeBytes for AESTowerField8b {
154 fn serialize(&self, write_buf: impl BufMut) -> Result<(), SerializationError> {
155 self.0.serialize(write_buf)
156 }
157}
158
159impl DeserializeBytes for AESTowerField8b {
160 fn deserialize(read_buf: impl Buf) -> Result<Self, SerializationError>
161 where
162 Self: Sized,
163 {
164 Ok(Self(DeserializeBytes::deserialize(read_buf)?))
165 }
166}
167
168impl FixedSizeSerializeBytes for AESTowerField8b {
169 const BYTE_SIZE: usize = 1;
170}
171
172#[cfg(test)]
173mod tests {
174 use binius_utils::{SerializeBytes, bytes::BytesMut};
175 use proptest::{arbitrary::any, proptest};
176 use rand::prelude::*;
177
178 use super::*;
179 use crate::{Random, binary_field::tests::is_binary_field_valid_generator};
180
181 fn check_square(f: impl Field) {
182 assert_eq!(f.square(), f * f);
183 }
184
185 proptest! {
186 #[test]
187 fn test_square_8(a in any::<u8>()) {
188 check_square(AESTowerField8b::from(a))
189 }
190 }
191
192 fn check_invert(f: impl Field) {
193 let inversed = f.invert_or_zero();
194 if f.is_zero() {
195 assert!(inversed.is_zero());
196 } else {
197 assert_eq!(inversed * f, Field::ONE);
198 }
199 }
200
201 proptest! {
202 #[test]
203 fn test_invert_8(a in any::<u8>()) {
204 check_invert(AESTowerField8b::from(a))
205 }
206 }
207
208 fn check_mul_by_one<F: Field>(f: F) {
209 assert_eq!(F::ONE * f, f);
210 assert_eq!(f * F::ONE, f);
211 }
212
213 fn check_commutative<F: Field>(f_1: F, f_2: F) {
214 assert_eq!(f_1 * f_2, f_2 * f_1);
215 }
216
217 fn check_associativity_and_lineraity<F: Field>(f_1: F, f_2: F, f_3: F) {
218 assert_eq!(f_1 * (f_2 * f_3), (f_1 * f_2) * f_3);
219 assert_eq!(f_1 * (f_2 + f_3), f_1 * f_2 + f_1 * f_3);
220 }
221
222 fn check_mul<F: Field>(f_1: F, f_2: F, f_3: F) {
223 check_mul_by_one(f_1);
224 check_mul_by_one(f_2);
225 check_mul_by_one(f_3);
226
227 check_commutative(f_1, f_2);
228 check_commutative(f_1, f_3);
229 check_commutative(f_2, f_3);
230
231 check_associativity_and_lineraity(f_1, f_2, f_3);
232 check_associativity_and_lineraity(f_1, f_3, f_2);
233 check_associativity_and_lineraity(f_2, f_1, f_3);
234 check_associativity_and_lineraity(f_2, f_3, f_1);
235 check_associativity_and_lineraity(f_3, f_1, f_2);
236 check_associativity_and_lineraity(f_3, f_2, f_1);
237 }
238
239 proptest! {
240 #[test]
241 fn test_mul_8(a in any::<u8>(), b in any::<u8>(), c in any::<u8>()) {
242 check_mul(AESTowerField8b::from(a), AESTowerField8b::from(b), AESTowerField8b::from(c))
243 }
244 }
245
246 #[test]
247 fn test_multiplicative_generators() {
248 assert!(is_binary_field_valid_generator::<AESTowerField8b>());
249 }
250
251 #[test]
252 fn test_serialization() {
253 let mut buffer = BytesMut::new();
254 let mut rng = StdRng::seed_from_u64(0);
255 let aes8 = AESTowerField8b::random(&mut rng);
256
257 SerializeBytes::serialize(&aes8, &mut buffer).unwrap();
258
259 let mut read_buffer = buffer.freeze();
260
261 assert_eq!(AESTowerField8b::deserialize(&mut read_buffer).unwrap(), aes8);
262 }
263}