Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
duyuefeng0708
GitHub Repository: duyuefeng0708/Cryptography-From-First-Principle
Path: blob/main/foundations/01-modular-arithmetic-groups/rust/src/lib.rs
483 views
unlisted
1
//! # Module 01: Modular Arithmetic and Groups — Exercises
2
//!
3
//! Work through these after completing the SageMath notebooks.
4
//! Implement each function, then remove `#[ignore]` from its tests to verify.
5
//!
6
//! ## Progression
7
//! 1. `mod_exp` — Guided (loop structure provided)
8
//! 2. `gcd` — Guided (algorithm outline provided)
9
//! 3. `is_generator` — Scaffolded (signature + hints)
10
//! 4. `element_order` — Scaffolded (signature + hints)
11
//! 5. `find_all_generators` — Independent (just the signature)
12
13
/// Compute `base^exp mod modulus` using repeated squaring.
14
///
15
/// # Example
16
/// ```
17
/// # use mod_arith_groups::mod_exp;
18
/// assert_eq!(mod_exp(2, 10, 1000), 24);
19
/// ```
20
pub fn mod_exp(base: u64, exp: u64, modulus: u64) -> u64 {
21
// Square-and-multiply algorithm:
22
// result = 1, base = base % modulus
23
// While exp > 0:
24
// if exp is odd: result = result * base mod modulus
25
// exp = exp / 2
26
// base = base * base mod modulus
27
//
28
// Watch out for overflow: cast to u128 before multiplying.
29
let mut result: u64 = 1;
30
let mut base = base % modulus;
31
let mut exp = exp;
32
while exp > 0 {
33
if exp % 2 == 1 {
34
// TODO: multiply result by base (mod modulus)
35
todo!("result = result * base mod modulus")
36
}
37
exp /= 2;
38
// TODO: square base (mod modulus)
39
todo!("base = base * base mod modulus")
40
}
41
result
42
}
43
44
/// Compute gcd(a, b) using the Euclidean algorithm.
45
///
46
/// # Example
47
/// ```
48
/// # use mod_arith_groups::gcd;
49
/// assert_eq!(gcd(48, 18), 6);
50
/// ```
51
pub fn gcd(a: u64, b: u64) -> u64 {
52
// Euclidean algorithm:
53
// while b != 0: (a, b) = (b, a % b)
54
// return a
55
let mut a = a;
56
let mut b = b;
57
loop {
58
if b == 0 {
59
return a;
60
}
61
// TODO: one step — set (a, b) = (b, a % b)
62
todo!("Update a and b")
63
}
64
}
65
66
/// Check whether `g` is a generator of (Z/pZ)*.
67
///
68
/// `g` is a generator iff for every prime factor `q` of `p - 1`,
69
/// `g^((p-1)/q) ≢ 1 (mod p)`.
70
///
71
/// Assume `p` is prime.
72
pub fn is_generator(g: u64, p: u64) -> bool {
73
// Hint: first find the prime factors of p - 1.
74
// Then for each factor q, check that mod_exp(g, (p-1)/q, p) != 1.
75
todo!("Check if g generates (Z/pZ)*")
76
}
77
78
/// Compute the multiplicative order of `a` in (Z/nZ)*.
79
///
80
/// Returns `None` if gcd(a, n) != 1 (a is not in the group).
81
///
82
/// Hint: try successive powers of `a` until you reach 1.
83
pub fn element_order(a: u64, n: u64) -> Option<u64> {
84
// Hint: if gcd(a, n) != 1, return None.
85
// Otherwise, compute a, a^2, a^3, ... mod n until you get 1.
86
todo!("Find the smallest k where a^k ≡ 1 (mod n)")
87
}
88
89
/// Find all generators of (Z/pZ)*, returned as a sorted Vec.
90
///
91
/// Assume `p` is prime. There are exactly φ(p-1) generators.
92
pub fn find_all_generators(p: u64) -> Vec<u64> {
93
todo!("Return all generators of (Z/pZ)*")
94
}
95
96
#[cfg(test)]
97
mod tests {
98
use super::*;
99
100
// ── mod_exp ──
101
102
#[test]
103
#[ignore]
104
fn test_mod_exp_basic() {
105
assert_eq!(mod_exp(2, 10, 1000), 24);
106
}
107
108
#[test]
109
#[ignore]
110
fn test_mod_exp_large() {
111
assert_eq!(mod_exp(3, 100, 1_000_000_007), 981_147_432);
112
}
113
114
#[test]
115
#[ignore]
116
fn test_mod_exp_edge_cases() {
117
assert_eq!(mod_exp(5, 0, 13), 1);
118
assert_eq!(mod_exp(0, 5, 13), 0);
119
}
120
121
// ── gcd ──
122
123
#[test]
124
#[ignore]
125
fn test_gcd_basic() {
126
assert_eq!(gcd(48, 18), 6);
127
assert_eq!(gcd(100, 75), 25);
128
}
129
130
#[test]
131
#[ignore]
132
fn test_gcd_coprime() {
133
assert_eq!(gcd(17, 13), 1);
134
}
135
136
#[test]
137
#[ignore]
138
fn test_gcd_with_zero() {
139
assert_eq!(gcd(42, 0), 42);
140
assert_eq!(gcd(0, 42), 42);
141
}
142
143
// ── is_generator ──
144
145
#[test]
146
#[ignore]
147
fn test_is_generator_true() {
148
assert!(is_generator(3, 7));
149
}
150
151
#[test]
152
#[ignore]
153
fn test_is_generator_false() {
154
assert!(!is_generator(2, 7));
155
}
156
157
// ── element_order ──
158
159
#[test]
160
#[ignore]
161
fn test_element_order_generator() {
162
assert_eq!(element_order(3, 7), Some(6));
163
}
164
165
#[test]
166
#[ignore]
167
fn test_element_order_non_generator() {
168
assert_eq!(element_order(2, 7), Some(3));
169
}
170
171
#[test]
172
#[ignore]
173
fn test_element_order_not_in_group() {
174
assert_eq!(element_order(4, 8), None);
175
}
176
177
// ── find_all_generators ──
178
179
#[test]
180
#[ignore]
181
fn test_find_all_generators_7() {
182
assert_eq!(find_all_generators(7), vec![3, 5]);
183
}
184
185
#[test]
186
#[ignore]
187
fn test_find_all_generators_13() {
188
assert_eq!(find_all_generators(13), vec![2, 6, 7, 11]);
189
}
190
}
191
192