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> {
|
||||
//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) {
|
||||
// if *a == zero {
|
||||
// return (
|
||||
// BigNum::from_u32(0).unwrap(),
|
||||
// BigNum::from_u32(1).unwrap(),
|
||||
// b);
|
||||
// }
|
||||
// (
|
||||
// BigNum::from_u32(0).unwrap(),
|
||||
// BigNum::from_u32(1).unwrap(),
|
||||
// b)
|
||||
//}
|
||||
// while (r2! = 0) do
|
||||
while r2.num_bits() != 0 {
|
||||
// q = r1 ÷ r2 (integer division)
|
||||
let q = &r1 / &r2;
|
||||
|
||||
// r3 = r1, u3 = u1, v3 = v1,
|
||||
let r3 = r1;
|
||||
let u3 = u1;
|
||||
let v3 = v1;
|
||||
|
||||
// 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 r = BigNum::new()?;
|
||||
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> {
|
||||
|
||||
Reference in New Issue
Block a user