1use 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 fn from(val: u32) -> Self {
42 Threshold {
43 value: val
44 }
45 }
46}
47
48impl Default for Threshold {
49 fn default() -> Self {
51 let threshold = Threshold {
52 value: 9 as u32
53 };
54 threshold
55 }
56}
57
58impl Threshold {
59 pub fn new(th: &u32) -> Self {
61 let th = Threshold {
62 value: *th
63 };
64 th
65 }
66
67 pub fn value(th: Self) -> u32 {
69 th.value
70 }
71}
72
73
74impl 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 pub fn new(size: &'static u32, threshold: Threshold) -> Result<Self, &'static str> {
85 let (_, one, _) = gen_basic_biguints();
87 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 let n = &p * &q;
95 let fi_n = (&p - &one) * (&q - &one);
96 let e = find_e(&fi_n).unwrap();
98
99 let pk = PublicKey::new(&n, &e).unwrap();
101 let (_, _,mut d) = egcd(&mut fi_n.to_bigint().unwrap(), &mut e.to_bigint().unwrap());
103 while d.is_negative() {
104 d = d + BigInt::from_biguint(Sign::Plus, fi_n.clone());
106 }
107 let sk = SecretKey::new(&n, &biguint_from_bigint(&d).unwrap()).unwrap();
108 let kp = KeyPair {
110 pk: pk,
111 sk: sk,
112 size: size.to_owned(),
113 threshold: threshold.value.to_owned()
114 };
115 Ok(kp)
117 }
118
119 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 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
133impl 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
140impl From<&Path> for PublicKey {
142 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
154impl 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 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 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 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
210impl 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
217impl From<&Path> for SecretKey {
220 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
232impl 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 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 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 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