#![allow(missing_docs)]
#![allow(unused_must_use)]
#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(non_camel_case_types)]
use crate::number::{ SmallUInt, BigUInt, BigUInt_Modular, BigUInt_Prime };
use crate::random::Random;
pub type RSA_4096_u128 = RSA_Generic<32, u128>;
pub type RSA_2048_u128 = RSA_Generic<16, u128>;
pub type RSA_1024_u128 = RSA_Generic<8, u128>;
pub type RSA_4096_u64 = RSA_Generic<64, u64>;
pub type RSA_2048_u64 = RSA_Generic<32, u64>;
pub type RSA_1024_u64 = RSA_Generic<16, u64>;
pub type RSA_4096_u32 = RSA_Generic<128, u32>;
pub type RSA_2048_u32 = RSA_Generic<64, u32>;
pub type RSA_1024_u32 = RSA_Generic<32, u32>;
pub type RSA_4096_u16 = RSA_Generic<256, u16>;
pub type RSA_2048_u16 = RSA_Generic<128, u16>;
pub type RSA_1024_u16 = RSA_Generic<64, u16>;
pub type RSA_4096_u8 = RSA_Generic<512, u8>;
pub type RSA_2048_u8 = RSA_Generic<256, u8>;
pub type RSA_1024_u8 = RSA_Generic<128, u8>;
pub type RSA_4096 = RSA_4096_u32;
pub type RSA_2048 = RSA_2048_u32;
pub type RSA_1024 = RSA_1024_u32;
pub struct RSA_Generic<const N: usize, T, const MR: usize = 7>
where T: SmallUInt
{
modulus: BigUInt<T, N>,
key_public: BigUInt<T, N>,
key_private: BigUInt<T, N>,
}
impl<const N: usize, T, const MR: usize> RSA_Generic<N, T, MR>
where T: SmallUInt
{
#[inline]
pub fn new() -> Self
{
Self
{
modulus: BigUInt::<T, N>::new(),
key_public: BigUInt::<T, N>::new(),
key_private: BigUInt::<T, N>::new(),
}
}
pub fn new_with_automatic_keys() -> Self
{
let mut rsa = Self
{
modulus: BigUInt::<T, N>::new(),
key_public: BigUInt::<T, N>::new(),
key_private: BigUInt::<T, N>::new(),
};
rsa.find_keys();
rsa
}
#[inline]
pub fn new_with_keys(key_public: BigUInt<T, N>, key_private: BigUInt<T, N>, modulus: BigUInt<T, N>) -> Self
{
Self
{
modulus,
key_public,
key_private,
}
}
pub fn new_with_primes(prime_1: BigUInt<T, N>, prime_2: BigUInt<T, N>) -> Self
{
let mut rsa = Self
{
modulus: BigUInt::<T, N>::new(),
key_public: BigUInt::<T, N>::new(),
key_private: BigUInt::<T, N>::new(),
};
rsa.calculate_keys(prime_1, prime_2);
rsa
}
pub fn new_with_prepared_keys() -> Self
{
let length = T::size_in_bytes() as usize * N;
let mut rand = Random::new();
let prime_1: BigUInt<T, N> = rand.prepared_random_prime_with_half_length();
let mut prime_2 = rand.prepared_random_prime_with_half_length();
while prime_1 == prime_2
{ prime_2 = rand.prepared_random_prime_with_half_length(); }
Self::new_with_primes(prime_1, prime_2)
}
#[inline]
pub fn get_public_key(&self) -> BigUInt<T, N>
{
self.key_public.clone()
}
#[inline]
pub fn get_private_key(&self) -> BigUInt<T, N>
{
self.key_private.clone()
}
#[inline]
pub fn get_modulus(&self) -> BigUInt<T, N>
{
self.modulus.clone()
}
#[inline]
pub fn set_public_key(&mut self, key_public: BigUInt<T, N>)
{
self.key_public = key_public;
}
#[inline]
pub fn set_private_key(&mut self, key_private: BigUInt<T, N>)
{
self.key_private = key_private;
}
#[inline]
pub fn set_modulus(&mut self, modulus: BigUInt<T, N>)
{
self.modulus = modulus;
}
#[inline]
fn choose_prime_numbers() -> (BigUInt<T, N>, BigUInt<T, N>)
{
crate::random::Random::new().random_prime_with_half_length_using_rsa_biguint(MR)
}
pub fn find_keys(&mut self)
{
let (prime_1, prime_2) = Self::choose_prime_numbers();
self.calculate_keys(prime_1, prime_2);
}
pub fn calculate_keys(&mut self, prime_1: BigUInt<T, N>, prime_2: BigUInt<T, N>)
{
self.modulus = prime_1.wrapping_mul(&prime_2);
let phi = prime_1.wrapping_sub_uint(1_u8).wrapping_mul(&prime_2.wrapping_sub_uint(1_u8));
self.key_public = BigUInt::<T, N>::from_uint(2_u8);
let mut one: BigUInt<T, N>;
(one, self.key_private, _) = self.key_public.extended_gcd(&phi);
while !one.is_one()
{
self.key_public.wrapping_add_assign_uint(1_u8);
(one, self.key_private, _) = self.key_public.extended_gcd(&phi);
}
if self.key_private.is_underflow()
{ self.key_private = phi.wrapping_sub(&BigUInt::<T, N>::zero().wrapping_sub(&self.key_private)).wrapping_rem(&phi); }
else
{ self.key_private.wrapping_rem_assign(&phi); }
}
#[inline]
pub fn encrypt_biguint(&self, message: &BigUInt<T, N>) -> BigUInt<T, N>
{
message.modular_pow(&self.key_public, &self.modulus)
}
#[inline]
pub fn decrypt_biguint(&self, cipher: &BigUInt<T, N>) -> BigUInt<T, N>
{
cipher.modular_pow(&self.key_private, &self.modulus)
}
pub fn encrypt_array_biguint<const M: usize>(&self, message: &[BigUInt<T, N>; M]) -> [BigUInt<T, N>; M]
{
let mut cipher = message.clone();
for i in 0..M
{ cipher[i] = self.encrypt_biguint(&message[i]); }
cipher
}
pub fn decrypt_array_biguint<const M: usize>(&self, cipher: &[BigUInt<T, N>; M]) -> [BigUInt<T, N>; M]
{
let mut message = cipher.clone();
for i in 0..M
{ message[i] = self.decrypt_biguint(&cipher[i]); }
message
}
pub fn encrypt_unit(&self, message: &[T; N]) -> [T; N]
{
let mut m = BigUInt::<T, N>::from_array(message.clone());
m.to_be_assign();
let mut c = self.encrypt_biguint(&m);
c.to_be_assign();
*c.get_number()
}
#[inline]
pub fn decrypt_unit(&self, cipher: &[T; N]) -> [T; N]
{
let mut c = BigUInt::<T, N>::from_array(cipher.clone());
c.to_be_assign();
let mut m = self.decrypt_biguint(&c);
m.to_be_assign();
*m.get_number()
}
pub fn encrypt_array_unit<const M: usize>(&self, message: &[[T; N]; M]) -> [[T; N]; M]
{
let mut cipher = [[T::zero(); N]; M];
for i in 0..M
{ cipher[i] = self.encrypt_unit(&message[i]); }
cipher
}
#[inline]
pub fn decrypt_array_unit<const M: usize>(&self, cipher: &[[T; N]; M]) -> [[T; N]; M]
{
let mut message = [[T::zero(); N]; M];
for i in 0..M
{ message[i] = self.decrypt_unit(&cipher[i]); }
message
}
}