Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
duyuefeng0708
GitHub Repository: duyuefeng0708/Cryptography-From-First-Principle
Path: blob/main/foundations/03-galois-fields-aes/rust/src/lib.rs
483 views
unlisted
1
//! # Module 03: Galois Fields and AES — Exercises
2
//!
3
//! All GF(256) arithmetic uses the AES irreducible polynomial:
4
//! `x⁸ + x⁴ + x³ + x + 1` (0x11B in hex).
5
//!
6
//! ## Progression
7
//! 1. `gf256_add` — Guided (it's XOR)
8
//! 2. `gf256_mul` — Scaffolded (Russian peasant + reduction)
9
//! 3. `gf256_inv` — Scaffolded (hint: use extended Euclidean or Fermat)
10
//! 4. `aes_sbox` — Scaffolded (compose inverse + affine)
11
//! 5. `aes_mix_column` — Independent
12
13
/// The AES irreducible polynomial: x⁸ + x⁴ + x³ + x + 1.
14
const AES_POLY: u16 = 0x11B;
15
16
/// Add two elements in GF(256). This is just XOR.
17
///
18
/// # Example
19
/// ```
20
/// # use galois_fields_aes::gf256_add;
21
/// assert_eq!(gf256_add(0x57, 0x83), 0xD4);
22
/// ```
23
pub fn gf256_add(a: u8, b: u8) -> u8 {
24
// In GF(2^n), addition is XOR. That's it!
25
todo!("XOR a and b")
26
}
27
28
/// Multiply two elements in GF(256) using the AES irreducible polynomial.
29
///
30
/// Use the "Russian peasant" (shift-and-XOR) algorithm:
31
/// - Shift `a` left by 1 bit each iteration (multiply by x)
32
/// - If the shift overflows 8 bits, reduce by XORing with AES_POLY
33
/// - If the corresponding bit of `b` is set, XOR `a` into the result
34
pub fn gf256_mul(a: u8, b: u8) -> u8 {
35
// Hint: work with u16 to catch overflow past 8 bits.
36
// For each bit of b (from bit 0 to bit 7):
37
// if bit is set, result ^= a
38
// shift a left by 1
39
// if a overflows 8 bits (bit 8 set), reduce: a ^= AES_POLY
40
todo!("GF(256) multiplication with polynomial reduction")
41
}
42
43
/// Compute the multiplicative inverse of `a` in GF(256).
44
///
45
/// Returns 0 if `a == 0` (by convention for AES S-box).
46
///
47
/// Hint: By Fermat's little theorem in GF(2^8), a^(254) = a^(-1).
48
/// Alternatively, implement the extended Euclidean algorithm for polynomials.
49
pub fn gf256_inv(a: u8) -> u8 {
50
todo!("Multiplicative inverse in GF(256)")
51
}
52
53
/// Compute the AES S-box value for a single byte.
54
///
55
/// S-box(a) = affine_transform(gf256_inv(a))
56
///
57
/// The affine transform over GF(2) is:
58
/// b[i] = inv[i] ^ inv[(i+4)%8] ^ inv[(i+5)%8] ^ inv[(i+6)%8] ^ inv[(i+7)%8] ^ c[i]
59
/// where c = 0x63.
60
pub fn aes_sbox(byte: u8) -> u8 {
61
todo!("AES S-box: inverse then affine transform")
62
}
63
64
/// Apply the AES MixColumns transformation to a single column.
65
///
66
/// Multiplies the column vector by the fixed matrix in GF(256):
67
/// ```text
68
/// | 2 3 1 1 | | c0 |
69
/// | 1 2 3 1 | × | c1 |
70
/// | 1 1 2 3 | | c2 |
71
/// | 3 1 1 2 | | c3 |
72
/// ```
73
pub fn aes_mix_column(col: [u8; 4]) -> [u8; 4] {
74
todo!("MixColumns matrix multiplication in GF(256)")
75
}
76
77
#[cfg(test)]
78
mod tests {
79
use super::*;
80
81
#[test]
82
#[ignore]
83
fn test_gf256_add() {
84
assert_eq!(gf256_add(0x57, 0x83), 0xD4);
85
assert_eq!(gf256_add(0xFF, 0xFF), 0x00); // self-inverse
86
}
87
88
#[test]
89
#[ignore]
90
fn test_gf256_mul_basic() {
91
assert_eq!(gf256_mul(0x57, 0x83), 0xC1);
92
}
93
94
#[test]
95
#[ignore]
96
fn test_gf256_mul_identity() {
97
assert_eq!(gf256_mul(0x53, 0x01), 0x53); // multiply by 1
98
assert_eq!(gf256_mul(0x00, 0x53), 0x00); // multiply by 0
99
}
100
101
#[test]
102
#[ignore]
103
fn test_gf256_inv() {
104
// inv(0x53) × 0x53 should equal 1
105
let inv = gf256_inv(0x53);
106
assert_eq!(gf256_mul(inv, 0x53), 0x01);
107
assert_eq!(gf256_inv(0x00), 0x00); // special case
108
}
109
110
#[test]
111
#[ignore]
112
fn test_aes_sbox_known_values() {
113
assert_eq!(aes_sbox(0x00), 0x63);
114
assert_eq!(aes_sbox(0x01), 0x7C);
115
assert_eq!(aes_sbox(0x53), 0xED);
116
}
117
118
#[test]
119
#[ignore]
120
fn test_aes_mix_column() {
121
// FIPS 197 test vector
122
let input = [0xDB, 0x13, 0x53, 0x45];
123
let expected = [0x8E, 0x4D, 0xA1, 0xBC];
124
assert_eq!(aes_mix_column(input), expected);
125
}
126
}
127
128