rsa_rust/
types.rs

1//! Types
2use num_bigint::{BigUint, BigInt, ToBigInt, Sign};
3use crate::helpers::math::*;
4use crate::helpers::generics::*;
5use num::{Signed, One, Num};
6use std::fmt;
7use std::str::FromStr;
8use std::fs::File;
9use std::io::prelude::*;
10use std::path::Path;
11use std::thread;
12
13
14#[derive(Clone, PartialEq)]
15pub struct KeyPair {
16    pub pk: PublicKey,
17    pub sk: SecretKey,
18    pub size: u32,
19    pub threshold: u32
20}
21
22#[derive(Clone, PartialEq)]
23pub struct PublicKey {
24    pub n: BigUint,
25    pub e: BigUint
26}
27
28#[derive(Clone, PartialEq)]
29pub struct SecretKey {
30    pub n: BigUint,
31    pub d: BigUint
32}
33
34#[derive(Clone, Copy, PartialEq)]
35pub struct Threshold {
36    value: u32
37}
38
39impl From<u32> for Threshold {
40    /// Implement from<u32> for Threshold
41    fn from(val: u32) -> Self {
42        Threshold {
43            value: val
44        }
45    }
46}
47
48impl Default for Threshold {
49    /// Creates a Threshold with a default error probability of generating a prime of 4^-64
50    fn default() -> Self {
51        let threshold = Threshold {
52            value: 9 as u32
53        };
54        threshold
55    }
56}
57
58impl Threshold {
59    /// Creates a Threshold with a selected value as thresholf of P(err). P(err prime) = 4^-threshold. 
60    pub fn new(th: &u32) -> Self {
61        let th = Threshold {
62            value: *th
63        };
64        th
65    }
66
67    /// Gets the value of a Threshold and returns it as u32.
68    pub fn value(th: Self) -> u32 {
69        th.value
70    }
71}
72
73
74/// Implementation of Display for KeyPair Struct.
75impl fmt::Display for KeyPair {
76    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77        write!(f, "\nPublic Key: \n{}\nSecret Key: \n{}\nSize: {}\nThreshold: {} which gives a P(err_primes_gen) = 4^(-{})", self.pk, self.sk, self.size, self.threshold, self.threshold)
78    }
79}
80
81impl KeyPair {
82    /// Generate a new KeyPair Struct from scratch by giving the size of the key desired (in bits) and the threshold of P(err) while assuming that
83    /// a number is prime. Statistic methods are used to found that numbers. P(err) = 4^-threshold (As is demonstraded on the Rabin-Miller algorithm)
84    pub fn new(size: &'static u32, threshold: Threshold) -> Result<Self, &'static str> {
85        // Gen basic needed variables
86        let (_, one, _) = gen_basic_biguints();
87        // Gen p q primal base 
88        let p_comp = thread::spawn(move ||
89            gen_big_prime(size, threshold.value)
90        );
91        let q = gen_big_prime(size, threshold.value);
92        let p = p_comp.join().unwrap();
93        // Gen n and fi_n
94        let n = &p * &q;
95        let fi_n = (&p - &one) * (&q - &one);
96        // Find a positive integer minor than fi_n , co-prime with fi_n 
97        let e = find_e(&fi_n).unwrap();
98
99        // Building Pk Struct
100        let pk = PublicKey::new(&n, &e).unwrap();
101        // Finding d and building Secret Key Struct
102        let (_, _,mut d) = egcd(&mut fi_n.to_bigint().unwrap(), &mut e.to_bigint().unwrap());
103        while d.is_negative() {
104            // Modular inverse.
105            d = d + BigInt::from_biguint(Sign::Plus, fi_n.clone());
106        }
107        let sk = SecretKey::new(&n, &biguint_from_bigint(&d).unwrap()).unwrap();
108        //Building KeyPair struct
109        let kp = KeyPair {
110            pk: pk,
111            sk: sk,
112            size: size.to_owned(),
113            threshold: threshold.value.to_owned()
114        };
115        // Return the KeyPair struct
116        Ok(kp)
117    }
118
119    /// Saves the KeyPair on two separated documents on the project folder encoded as base64.
120    pub fn print(&self) -> Result<(), &'static str> {
121        let mut pk_file = File::create("rsa_pk.key").unwrap();
122        let mut sk_file = File::create("rsa_sk.key").unwrap();
123        //Ask for encoded params and write.
124        let (pk, sk) = prepare_to_print(&self).unwrap();
125        pk_file.write_all(pk.as_bytes()).unwrap();
126        sk_file.write_all(sk.as_bytes()).unwrap();
127        Ok(())
128    }
129}
130
131
132
133/// Implementation of Display for KeyPair Struct.
134impl fmt::Display for PublicKey {
135    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136        write!(f, "n: {}\ne: {}", self.n, self.e)
137    }
138}
139
140/// Allow to get a Public Key from different ways.
141impl From<&Path> for PublicKey {
142    /// Generate a Public Key from it's Keys path.
143    fn from(path: &Path) -> Self {
144        let pk_path = path.to_str().unwrap();
145        let _pk_file = match File::open(&pk_path) {
146            Ok(res) => {
147                return get_pk_params(&res).unwrap()
148            },
149            Err(_) => panic!("Failed to load Public Key from path: {}", pk_path)
150        };
151    }
152}
153
154/// Given n and e co-prime factors.
155/// Returns a PublictKey Struct (without checking it's correctness)
156impl From<(&BigUint, &BigUint)> for PublicKey {
157
158    fn from((n, d): (&BigUint, &BigUint)) -> Self {
159        let pk = PublicKey {
160            n: n.clone(),
161            e: d.clone()
162        };
163        pk
164    }
165} 
166
167impl PublicKey {
168    /// Generate a PublicKey struct from n and d co-prime factors.
169    pub fn new(_n: &BigUint, _e: &BigUint) -> Result<Self, &'static str> {
170        Ok(PublicKey {
171            n: _n.to_owned(),
172            e: _e.to_owned()
173        })
174    }
175    
176    /// Generate a PublicKey struct from n, fi_n and d params with the co-prime property checking.
177    pub fn new_from_fi_n_e(_n: &BigUint, _fi_n: &BigUint, _e: &BigUint) -> Result<Self, &'static str> {
178        let (_, _one, _) = gen_basic_bigints();
179
180        match egcd(&mut BigInt::from_biguint(Sign::Plus, _fi_n.to_owned()), &mut BigInt::from_biguint(Sign::Plus, _e.to_owned())) {
181            (possible_one, _, _) => {
182                if possible_one.is_one() {
183                    return  Ok(PublicKey {
184                                n: _n.to_owned(),
185                                e: _e.to_owned()
186                            }
187                        )
188                }else {
189                    return Err("Params passed to Sk builder haven't the right properties to be a Public Key")
190            
191                }            
192            }
193        }
194    }
195
196    /// Encrypts the data passed on the params.
197    pub fn encrypt(&self, msg: &str) -> Result<String, &'static str> {
198        if !msg.is_ascii(){
199            return Err("Message isn't ASCII like. Please remove non-ASCII characters.")
200        }else{
201            let res = BigUint::from_bytes_be(msg.as_bytes());
202            Ok(format!("{}", mod_exp_pow(&res, &self.e, &self.n).to_str_radix(16u32)))
203        }
204    }
205}
206
207
208
209
210/// Implementation of Display for KeyPair Struct.
211impl fmt::Display for SecretKey {
212    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
213        write!(f, "n: {}\nd: {}", self.n, self.d)
214    }
215}
216
217/// Gets a path to a Secret Key
218/// Returns a SecretKey Struct
219impl From<&Path> for SecretKey {
220    /// Generate a Secret Key from it's Keys folder path (Don't include the key name on the path).
221    fn from(path: &Path) -> Self {
222        let sk_path = path.to_str().unwrap();
223        let _pk_file = match File::open(&sk_path) {
224            Ok(res) => {
225                return get_sk_params(&res).unwrap()
226            },
227            Err(_) => panic!("Failed to load Public Key from path: {}", sk_path)
228        };
229    }
230}
231
232/// Given n and d co-prime factors.
233/// Returns a SecretKey Struct (without checking it's correctness)
234impl From<(&BigUint, &BigUint)> for SecretKey {
235
236    fn from((n, d): (&BigUint, &BigUint)) -> Self {
237        let sk = SecretKey {
238            n: n.clone(),
239            d: d.clone()
240        };
241        sk
242    }
243}
244
245impl SecretKey {
246    /// Generate a SecretKey struct from n and d co-prime factors.
247    pub fn new(_n: &BigUint, _d: &BigUint) -> Result<Self, &'static str> {
248        Ok(SecretKey {
249            n: _n.to_owned(),
250            d: _d.to_owned()
251        })
252    }
253
254    /// Generate a SecretKey struct from n, fi_n and d params with the co-prime property checking.
255    pub fn new_from_fi_n_d(_n: &BigUint, _fi_n: &BigUint, _d: &BigUint) -> Result<Self, &'static str> {
256        let (_, _one, _) = gen_basic_bigints();
257
258        match egcd(&mut BigInt::from_biguint(Sign::Plus, _fi_n.to_owned()), &mut BigInt::from_biguint(Sign::Plus, _d.to_owned())) {
259            (possible_one, _, _) => {
260                if possible_one.is_one() {
261                    return  Ok(SecretKey {
262                                n: _n.to_owned(),
263                                d: _d.to_owned()
264                            }
265                    )
266                }else {
267                    return Err("Params passed to Sk builder haven't the properties to be a Public Key")
268            
269                }            
270            }
271        }
272    }
273    
274    /// Decrypts the cyphertext giving back an &str
275    pub fn decrypt(&self, text: &String) -> Result<String, &'static str> {
276        let c = BigUint::from_str_radix(&text, 16u32).unwrap();
277        let result_as_bytes = mod_exp_pow(&c, &self.d, &self.n).to_bytes_be();
278        let res_decrypt = std::str::from_utf8(&result_as_bytes).unwrap();
279        Ok(format!("{}", res_decrypt))
280    }
281}
282