Implement invmod manually
This commit is contained in:
56
src/rsa.rs
56
src/rsa.rs
@@ -70,25 +70,53 @@ pub fn rsa_gen_keys() -> Result<(RsaPublicKey, RsaPrivateKey), ErrorStack> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn invmod(a: &BigNum, n: &BigNum) -> Result<BigNum, ErrorStack> {
|
pub fn invmod(a: &BigNum, n: &BigNum) -> Result<BigNum, ErrorStack> {
|
||||||
//let zero = BigNum::from_u32(0)?;
|
fn extended_gcd(a: BigNum, b: BigNum) -> Result<(BigNum, BigNum, BigNum), ErrorStack> {
|
||||||
|
// credit: https://www.dcode.fr/extended-gcd
|
||||||
|
// r1 = b, r2 = a, u1 = 0, v1 = 1, u2 = 1, v2 = 0
|
||||||
|
let mut r1 = b;
|
||||||
|
let mut r2 = a;
|
||||||
|
let mut u1 = BigNum::from_u32(0)?;
|
||||||
|
let mut v1 = BigNum::from_u32(1)?;
|
||||||
|
let mut u2 = BigNum::from_u32(1)?;
|
||||||
|
let mut v2 = BigNum::from_u32(0)?;
|
||||||
|
|
||||||
//let gcd_extended = |a: &mut BigNum, b: &mut BigNum| -> (BigNum, BigNum, BigNum) {
|
// while (r2! = 0) do
|
||||||
// if *a == zero {
|
while r2.num_bits() != 0 {
|
||||||
// return (
|
// q = r1 ÷ r2 (integer division)
|
||||||
// BigNum::from_u32(0).unwrap(),
|
let q = &r1 / &r2;
|
||||||
// BigNum::from_u32(1).unwrap(),
|
|
||||||
// b);
|
// r3 = r1, u3 = u1, v3 = v1,
|
||||||
// }
|
let r3 = r1;
|
||||||
// (
|
let u3 = u1;
|
||||||
// BigNum::from_u32(0).unwrap(),
|
let v3 = v1;
|
||||||
// BigNum::from_u32(1).unwrap(),
|
|
||||||
// b)
|
// r1 = r2, u1 = u2, v1 = v2,
|
||||||
//}
|
r1 = r2;
|
||||||
|
u1 = u2;
|
||||||
|
v1 = v2;
|
||||||
|
|
||||||
|
// r2 = r3 - q * r2, u2 = u3 - q * u2, v2 = v3 - q * v2
|
||||||
|
r2 = &r3 - &(&q * &r1);
|
||||||
|
u2 = &u3 - &(&q * &u1);
|
||||||
|
v2 = &v3 - &(&q * &v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return (r1, u1, v1) (r1 natural integer and u1, v1 rational integers)
|
||||||
|
Ok((r1, u1, v1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// No, couldn't think of a worse way to do that.
|
||||||
|
let a_cloned = BigNum::from_hex_str(&a.to_hex_str()?)?;
|
||||||
|
let n_cloned = BigNum::from_hex_str(&n.to_hex_str()?)?;
|
||||||
|
|
||||||
|
let (_, u1, _) = extended_gcd(a_cloned, n_cloned)?;
|
||||||
|
let r_manual = &(&(&u1 % n) + n) % n;
|
||||||
|
|
||||||
let mut ctx = BigNumContext::new()?;
|
let mut ctx = BigNumContext::new()?;
|
||||||
let mut r = BigNum::new()?;
|
let mut r = BigNum::new()?;
|
||||||
r.mod_inverse(&a, &n, &mut ctx)?;
|
r.mod_inverse(&a, &n, &mut ctx)?;
|
||||||
Ok(r)
|
assert_eq!(r_manual, r, "invmod implementation incorrect");
|
||||||
|
Ok(r_manual)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rsa_encrypt(m: &BigNum, p: &RsaPublicKey) -> Result<BigNum, ErrorStack> {
|
pub fn rsa_encrypt(m: &BigNum, p: &RsaPublicKey) -> Result<BigNum, ErrorStack> {
|
||||||
|
|||||||
Reference in New Issue
Block a user