From 3cd37a881d91663b2e3c5b488b554d26c2651904 Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Wed, 4 Apr 2018 18:47:02 -0400 Subject: [PATCH] First whack at modular inverses. --- src/cryptonum/mod.rs | 51 +++++++++++++++++++++++++++++++++++++++++ src/cryptonum/signed.rs | 16 +++++++++++++ 2 files changed, 67 insertions(+) diff --git a/src/cryptonum/mod.rs b/src/cryptonum/mod.rs index c570101..27cf935 100644 --- a/src/cryptonum/mod.rs +++ b/src/cryptonum/mod.rs @@ -7,3 +7,54 @@ mod unsigned; pub use self::signed::SCN; pub use self::unsigned::UCN; + +use std::ops::Neg; + +pub fn modinv(e: &UCN, phi: &UCN) -> UCN { + let (_, mut x, _) = extended_euclidean(&e, &phi); + let int_phi = SCN::from(phi.clone()); + while x.is_negative() { + x = x + &int_phi; + } + x.into() +} + +fn extended_euclidean(a: &UCN, b: &UCN) -> (SCN, SCN, SCN) { + let posinta = SCN::from(a.clone()); + let posintb = SCN::from(b.clone()); + let (d, x, y) = egcd(posinta, posintb); + + if d.is_negative() { + (d.neg(), x.neg(), y.neg()) + } else { + (d, x, y) + } +} + +fn egcd(a: SCN, b: SCN) -> (SCN, SCN, SCN) { + let mut s = SCN::zero(); + let mut old_s = SCN::from(1 as u8); + let mut t = SCN::from(1 as u8); + let mut old_t = SCN::zero(); + let mut r = b; + let mut old_r = a; + + 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) +} + diff --git a/src/cryptonum/signed.rs b/src/cryptonum/signed.rs index 8f115dd..a5901cd 100644 --- a/src/cryptonum/signed.rs +++ b/src/cryptonum/signed.rs @@ -20,6 +20,10 @@ impl SCN { self.value.is_zero() } + pub fn is_negative(&self) -> bool { + self.negative + } + pub fn from_str(x: &str) -> SCN { if x.get(0..1) == Some("-") { SCN{ negative: true, value: UCN::from_str(&x[1..]) } @@ -59,6 +63,18 @@ define_signed_into!(SCN, i16, u16); define_signed_into!(SCN, i32, u32); define_signed_into!(SCN, i64, u64); +impl From for SCN { + fn from(x: UCN) -> SCN { + SCN{ negative: false, value: x } + } +} + +impl Into for SCN { + fn into(self) -> UCN { + self.value + } +} + //------------------------------------------------------------------------------ // // Comparisons