Skip to content

Instantly share code, notes, and snippets.

@RandyMcMillan
Forked from rust-play/playground.rs
Last active May 26, 2025 21:22
Show Gist options
  • Save RandyMcMillan/bca29838e4c79db9c3e2652e1783aafc to your computer and use it in GitHub Desktop.
Save RandyMcMillan/bca29838e4c79db9c3e2652e1783aafc to your computer and use it in GitHub Desktop.
rsa_example.rs
use num_bigint::{BigInt, BigUint, Sign};
use num_traits::{One, Zero};
use std::str::FromStr; // For parsing BigUint from strings (e.g., hex)
// --- RSA Core Functions ---
/// Performs modular exponentiation: base^exp % modulus
fn modpow(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
// This is the core of RSA. `num-bigint` provides an optimized `modpow` method.
base.modpow(exp, modulus)
}
// --- RSA Key Structure (Hardcoded for simplicity) ---
// In a real application, you'd generate these based on large random primes.
// Using small primes (p=61, q=53) for a tiny example.
// p = 61
// q = 53
// n = p * q = 61 * 53 = 3233
// phi = (p-1)*(q-1) = 60 * 52 = 3120
// e = 17 (a common choice, coprime with 3120)
// d = 17^-1 mod 3120 = 413 (modular multiplicative inverse)
const N_STR: &str = "3233"; // n = p * q
const E_STR: &str = "17"; // e = public exponent
const D_STR: &str = "413"; // d = private exponent
// --- Main Application Logic ---
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();
#[cfg(not(debug_assertions))]
if args.len() < 2 {
eprintln!("Usage: {} <encrypt|decrypt> <message_or_ciphertext_decimal>", args[0]);
eprintln!(" <message_or_ciphertext_decimal>: The number to encrypt/decrypt, in decimal.");
eprintln!("NOTE: This is a minimal, INSECURE RSA implementation for demonstration ONLY.");
eprintln!(" It does NOT use padding and should NOT be used for real cryptography.");
return Ok(());
}
#[cfg(not(debug_assertions))]
let command = &args[1];
let command = &"encrypt";
#[cfg(not(debug_assertions))]
let input_decimal_str = &args[2];
let input_decimal_str = &"333";
// Parse the pre-defined RSA parameters
let n = BigUint::from_str(N_STR).expect("Invalid N constant");
let e = BigUint::from_str(E_STR).expect("Invalid E constant");
let d = BigUint::from_str(D_STR).expect("Invalid D constant");
// Parse the input message/ciphertext
let input_num = BigUint::from_str(input_decimal_str)
.map_err(|_| "Input must be a valid decimal number")?;
match command.as_ref() {
"encrypt" => {
// Check if message is smaller than n (required for raw RSA)
if input_num >= n {
eprintln!("Error: Message ({}) must be smaller than the modulus N ({}).", input_num, n);
return Err("Message too large for raw RSA".into());
}
// C = M^e mod n
let ciphertext = modpow(&input_num, &e, &n);
println!("Ciphertext (decimal): {}", ciphertext);
}
"decrypt" => {
// M = C^d mod n
let decrypted_message = modpow(&input_num, &d, &n);
println!("Decrypted Message (decimal): {}", decrypted_message);
}
_ => {
eprintln!("Unknown command: {}", command);
eprintln!("Use 'encrypt' or 'decrypt'.");
}
}
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment