use cryptonum::signed::Signed; use cryptonum::traits::*; use std::ops::*; pub fn modinv<'a,T>(e: &T, phi: &T) -> T where T: Clone + CryptoNumBase + Ord, T: AddAssign + SubAssign + MulAssign + DivAssign, T: Add + Sub + Mul + Div, &'a T: Sub, T: 'a { let (_, mut x, _) = extended_euclidean(e, phi); let int_phi = Signed::::new(phi.clone()); while x.is_negative() { x += &int_phi; } x.abs() } pub fn modexp(b: &T, e: &T, m: &T) -> T { panic!("modexp") } pub fn extended_euclidean(a: &T, b: &T) -> (Signed, Signed, Signed) where T: Clone + CryptoNumBase + Div + Mul + Sub { let posinta = Signed::::new(a.clone()); let posintb = Signed::::new(b.clone()); let (mut d, mut x, mut y) = egcd(&posinta, &posintb); if d.is_negative() { d.negate(); x.negate(); y.negate(); } (d, x, y) } pub fn egcd(a: &Signed, b: &Signed) -> (Signed,Signed,Signed) where T: Clone + CryptoNumBase + Div + Mul + Sub { let mut s = Signed::::zero(); let mut old_s = Signed::::from_u8(1); let mut t = Signed::::from_u8(1); let mut old_t = Signed::::zero(); let mut r = b.clone(); let mut old_r = a.clone(); while !r.is_zero() { let quotient = old_r.clone() / r.clone(); let prov_r = r.clone(); let prov_s = s.clone(); let prov_t = t.clone(); r = old_r - (r * "ient); s = old_s - (s * "ient); t = old_t - (t * "ient); old_r = prov_r; old_s = prov_s; old_t = prov_t; } (old_r, old_s, old_t) }