use openssl::bn::{BigNum, BigNumContext}; use rust_util::XResult; #[derive(Debug)] pub struct RsaCrt { // n = p * q pub modulus: BigNum, // e pub public_exponent: BigNum, // d = e mod inverse ((p - 1) * (q - 1)) pub private_exponent: BigNum, // p pub prime1: BigNum, // q pub prime2: BigNum, // dp = d mod (pāˆ’1) pub exponent1: BigNum, // dq = d mod (qāˆ’1) pub exponent2: BigNum, // qinv = q^āˆ’1 mod p pub coefficient: BigNum, } impl RsaCrt { pub fn from(p: BigNum, q: BigNum, e: BigNum) -> XResult { Ok(opt_result!( inner_from(p, q, e), "Calc RsaCrt failed: {}")) } } pub fn clone_big_num(n: &BigNum) -> XResult { Ok(opt_result!(BigNum::from_slice(n.to_vec().as_slice()), "Clone big num:{}, failed: {}", n)) } fn inner_from(p: BigNum, q: BigNum, e: BigNum) -> XResult { let mut n = BigNum::new()?; n.checked_mul(&p, &q, &mut BigNumContext::new().unwrap())?; let mut p_m1 = clone_big_num(&p)?; p_m1.sub_word(1)?; let mut q_m1 = clone_big_num(&q)?; q_m1.sub_word(1)?; let mut m = BigNum::new()?; m.checked_mul(&p_m1, &q_m1, &mut BigNumContext::new().unwrap())?; let mut d = BigNum::new()?; d.mod_inverse(&e, &m, &mut BigNumContext::new().unwrap())?; let mut dp = BigNum::new()?; dp.nnmod(&d, &p_m1, &mut BigNumContext::new().unwrap())?; let mut dq = BigNum::new()?; dq.nnmod(&d, &q_m1, &mut BigNumContext::new().unwrap())?; let mut qinv = BigNum::new()?; qinv.mod_inverse(&q, &p, &mut BigNumContext::new().unwrap())?; Ok(RsaCrt { modulus: n, public_exponent: e, private_exponent: d, prime1: p, prime2: q, exponent1: dp, exponent2: dq, coefficient: qinv, }) }