Last active
March 26, 2021 19:15
-
-
Save MAGANER/918193ac5c9e5b60e9f63b52154d7239 to your computer and use it in GitHub Desktop.
RSA example in RUST
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use rand::prelude::*; | |
use modinverse::modinverse; | |
fn is_prime(n: u32) -> bool | |
{ | |
//checks is number prime | |
let limit = (n as f64).sqrt() as u32; | |
for i in 2..=limit { | |
if n % i == 0 { | |
return false; | |
} | |
} | |
true | |
} | |
fn generate_prime_numbers(max:u32) -> Vec<u32> | |
{ | |
//it generates big prime numbers, required with RSA | |
let mut numbers = Vec::new(); | |
for n in 2..max+1 | |
{ | |
if is_prime(n) | |
{ | |
numbers.push(n); | |
} | |
} | |
numbers | |
} | |
fn get_random_prime_numbers(numbers:&Vec<u32>) -> (u32,u32) | |
{ | |
//get two random prime numbers | |
let mut rng = thread_rng(); | |
let q = rng.gen_range(0..numbers.len()); | |
let p = rng.gen_range(0..numbers.len()); | |
(numbers[q as usize],numbers[p as usize]) | |
} | |
pub fn get_modulus(numbers:(u32,u32)) -> u32 | |
{ | |
numbers.0*numbers.1 | |
} | |
fn compute_euler_fn(p:u32,q:u32) -> u32 | |
{ | |
(p-1)*(q-1) | |
} | |
fn gcd(_a:u32,_b:u32) -> u32 | |
{ | |
//Euclidean algorithm | |
let mut a = _a; | |
let mut b = _b; | |
while a != 0 && b != 0 | |
{ | |
if a > b | |
{ | |
a = a % b; | |
} else { | |
b = b % a; | |
} | |
} | |
a + b | |
} | |
fn get_open_exponent(random_pair:(u32,u32),numbers:&Vec<u32>) -> u32 | |
{ | |
let euler_fn_val = compute_euler_fn(random_pair.0,random_pair.1); | |
let mut _numbers:Vec<u32> = Vec::new(); | |
let mut prime = 0; | |
let mut counter = 0; | |
while prime < euler_fn_val && counter < numbers.len() | |
{ | |
prime = numbers[counter as usize]; | |
if gcd(prime,euler_fn_val) == 1 | |
{ | |
_numbers.push(prime); | |
} | |
counter += 1; | |
} | |
let pos_to_get = thread_rng().gen_range(0.._numbers.len()); | |
_numbers[pos_to_get] | |
} | |
fn get_secret_key(exponent:u32,random_pair:(u32,u32)) -> Result<u32,String> | |
{ | |
let euler_fn_val = compute_euler_fn(random_pair.0,random_pair.1); | |
match modinverse(exponent as i32,euler_fn_val as i32) | |
{ | |
Some(val) => Ok(val.abs() as u32), | |
None => Err("can not get secret key!".to_string()) | |
} | |
} | |
fn main() | |
{ | |
let prime_numbers = generate_prime_numbers(100); | |
let random_pair = get_random_prime_numbers(&prime_numbers); | |
let n = get_modulus(random_pair); | |
let e = get_open_exponent(random_pair,&prime_numbers); | |
let d = match get_secret_key(e,random_pair) | |
{ | |
Ok(val) => val, | |
Err(eval)=> { | |
println!("{}",eval); | |
0 | |
} | |
}; | |
println!("{} and {} is open key",n,e); | |
println!("secret key :{}",d); | |
//example: how to encode single character | |
let a = 'h' as u32; | |
let power = power_big_int(a.to_bigint().unwrap(),e); | |
let code = power%n.to_bigint().unwrap(); | |
println!("encoded number is {}",code); | |
} | |
use num_bigint::*; | |
fn power_big_int(a:BigInt,pow:u32) -> BigInt | |
{ | |
let mut number = a; | |
for _ in 0..pow | |
{ | |
number = number.clone()*&number; | |
} | |
number | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment