Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
duyuefeng0708
GitHub Repository: duyuefeng0708/Cryptography-From-First-Principle
Path: blob/main/foundations/04-number-theory-rsa/rust/src/lib.rs
483 views
unlisted
1
//! # Module 04: Number Theory and RSA — Exercises
2
//!
3
//! ## Progression
4
//! 1. `extended_gcd` — Guided (recursive skeleton)
5
//! 2. `mod_inverse` — Scaffolded (use extended_gcd)
6
//! 3. `euler_totient` — Scaffolded (factorization hint)
7
//! 4. `rsa_keygen` — Scaffolded (from given primes)
8
//! 5. `rsa_encrypt_decrypt` — Independent
9
10
/// Compute the extended GCD: returns (gcd, x, y) such that a*x + b*y = gcd.
11
///
12
/// # Example
13
/// ```
14
/// # use number_theory_rsa::extended_gcd;
15
/// let (g, x, y) = extended_gcd(35, 15);
16
/// assert_eq!(g, 5);
17
/// assert_eq!(35_i64 * x + 15_i64 * y, 5);
18
/// ```
19
pub fn extended_gcd(a: i64, b: i64) -> (i64, i64, i64) {
20
// Base case: if b == 0, return (a, 1, 0).
21
// Recursive case:
22
// let (g, x1, y1) = extended_gcd(b, a % b);
23
// return (g, y1, x1 - (a / b) * y1);
24
//
25
// TODO: implement the recursion (or convert to iterative).
26
if b == 0 {
27
return (a, 1, 0);
28
}
29
todo!("Recursive step of extended GCD")
30
}
31
32
/// Compute the modular inverse of `a` mod `m`, if it exists.
33
///
34
/// Returns `Some(x)` where `a * x ≡ 1 (mod m)`, or `None` if gcd(a,m) != 1.
35
///
36
/// Hint: use `extended_gcd`. If gcd == 1, the inverse is `x mod m`.
37
pub fn mod_inverse(a: u64, m: u64) -> Option<u64> {
38
todo!("Use extended_gcd to find modular inverse")
39
}
40
41
/// Compute Euler's totient φ(n).
42
///
43
/// φ(n) = n × ∏(1 - 1/p) for each distinct prime factor p of n.
44
///
45
/// For RSA: if n = p*q, then φ(n) = (p-1)(q-1).
46
///
47
/// Hint: factor n by trial division up to √n.
48
pub fn euler_totient(n: u64) -> u64 {
49
todo!("Compute Euler's totient via trial division")
50
}
51
52
/// Generate RSA key components from two primes p and q.
53
///
54
/// Returns `(n, e, d)` where:
55
/// - `n = p * q`
56
/// - `e = 65537` (standard public exponent)
57
/// - `d = e^(-1) mod φ(n)`
58
///
59
/// Panics if e and φ(n) are not coprime.
60
pub fn rsa_keygen(p: u64, q: u64) -> (u64, u64, u64) {
61
todo!("Compute n, e=65537, d from primes p and q")
62
}
63
64
/// RSA encryption or decryption: compute `msg^key mod n`.
65
///
66
/// This works for both encryption (msg^e mod n) and decryption (ciphertext^d mod n).
67
pub fn rsa_encrypt_decrypt(msg: u64, key: u64, n: u64) -> u64 {
68
todo!("Modular exponentiation for RSA")
69
}
70
71
#[cfg(test)]
72
mod tests {
73
use super::*;
74
75
#[test]
76
#[ignore]
77
fn test_extended_gcd_basic() {
78
let (g, x, y) = extended_gcd(35, 15);
79
assert_eq!(g, 5);
80
assert_eq!(35 * x + 15 * y, 5);
81
}
82
83
#[test]
84
#[ignore]
85
fn test_extended_gcd_coprime() {
86
let (g, x, y) = extended_gcd(17, 13);
87
assert_eq!(g, 1);
88
assert_eq!(17 * x + 13 * y, 1);
89
}
90
91
#[test]
92
#[ignore]
93
fn test_mod_inverse_exists() {
94
assert_eq!(mod_inverse(3, 7), Some(5)); // 3*5 = 15 ≡ 1 mod 7
95
}
96
97
#[test]
98
#[ignore]
99
fn test_mod_inverse_none() {
100
assert_eq!(mod_inverse(6, 9), None); // gcd(6,9) = 3
101
}
102
103
#[test]
104
#[ignore]
105
fn test_euler_totient() {
106
assert_eq!(euler_totient(7), 6); // prime
107
assert_eq!(euler_totient(12), 4); // 12 = 2²×3, φ = 12(1-1/2)(1-1/3) = 4
108
assert_eq!(euler_totient(15), 8); // 15 = 3×5, φ = (3-1)(5-1) = 8
109
}
110
111
#[test]
112
#[ignore]
113
fn test_rsa_roundtrip() {
114
let (n, e, d) = rsa_keygen(61, 53);
115
assert_eq!(n, 3233);
116
117
let plaintext = 42_u64;
118
let ciphertext = rsa_encrypt_decrypt(plaintext, e, n);
119
let decrypted = rsa_encrypt_decrypt(ciphertext, d, n);
120
assert_eq!(decrypted, plaintext);
121
}
122
}
123
124