1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| use num::BigInt; use rand::seq::index::sample; use rand::{thread_rng, Rng};
const SMALL_PRIMES: [u64; 50] = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, ];
#[derive(Debug)] struct KeyPair { private_key: u64, public_key: u64, modulus: u64, }
impl KeyPair { pub fn generate() -> Self { let mut rng = thread_rng(); let indices = sample(&mut rng, SMALL_PRIMES.len(), 2); let p = SMALL_PRIMES[indices.index(0)]; let q = SMALL_PRIMES[indices.index(1)]; let modulus = p * q; let phi = (p - 1) * (q - 1); let public_key = loop { let public_key = SMALL_PRIMES[thread_rng().gen_range(0..SMALL_PRIMES.len())]; if public_key < phi && gcd(public_key, phi) == 1 { break public_key; } };
let mut private_key = 1; while (public_key * private_key) % phi != 1 { private_key += 1; }
Self { private_key, public_key, modulus, } }
pub fn encrypt(&self, message: BigInt) -> BigInt { message.pow(self.public_key as u32) % self.modulus }
pub fn decrypt(&self, encrypted_message: BigInt) -> BigInt { encrypted_message.pow(self.private_key as u32) % self.modulus }
pub fn get_private_key(&self) -> (u64, u64) { (self.private_key, self.modulus) }
pub fn get_public_key(&self) -> (u64, u64) { (self.public_key, self.modulus) }
pub fn get_modulus(&self) -> u64 { self.modulus } }
fn gcd(p0: u64, p1: u64) -> u64 { let mut p0 = p0; let mut p1 = p1; while p1 != 0 { let temp = p1; p1 = p0 % p1; p0 = temp; } p0 }
#[cfg(test)] mod tests { use super::*;
#[test] fn test_rsa() { for _ in 0..100 { let key_pair = KeyPair::generate(); let message = BigInt::from(rand::thread_rng().gen_range(6..key_pair.get_modulus())); let encrypted_message = key_pair.encrypt(message.clone()); let decrypted_message = key_pair.decrypt(encrypted_message.clone()); assert_eq!(decrypted_message, message); println!( "public key: ({}, {}), private key: ({}, {}), message: {}, encrypted: {}, decrypted: {}", key_pair.get_public_key().0, key_pair.get_public_key().1, key_pair.get_private_key().0, key_pair.get_private_key().1, message, encrypted_message, decrypted_message ) } } }
|