Clean up and consider BigUint as alternative to BigNum for RSA implementation

This commit is contained in:
2023-01-29 12:57:03 -05:00
parent 6abf32c361
commit edbe2144ae
7 changed files with 190 additions and 140 deletions

View File

@@ -1,36 +1,13 @@
use crate::utils::bnclone;
use num_bigint::BigInt;
use num_bigint::BigUint;
use num_bigint::RandBigInt;
use num_bigint::ToBigInt;
use openssl::bn::BigNum;
use openssl::bn::BigNumContext;
use openssl::bn::MsbOption;
use openssl::error::ErrorStack;
use openssl::sha::sha256;
#[derive(Clone)]
pub struct PublicKey(pub BigUint);
#[derive(Clone)]
pub struct PrivateKey(pub BigUint);
#[derive(Clone)]
pub struct Keypair {
pub private: PrivateKey,
pub public: PublicKey,
}
impl Keypair {
pub fn make(p: &BigUint, g: &BigUint) -> Self {
let mut rng = rand::thread_rng();
let private = rng.gen_biguint_below(p);
let public = g.modpow(&private, p);
Self {
private: PrivateKey(private),
public: PublicKey(public),
}
}
}
pub struct RsaPublicKey {
pub e: BigNum,
pub n: BigNum,
@@ -51,7 +28,10 @@ fn generate_random_prime(bits: i32) -> Result<BigNum, ErrorStack> {
Ok(p)
}
pub fn rsa_gen_keys_with_size(p_bits: i32, q_bits: i32) -> Result<(RsaPublicKey, RsaPrivateKey), ErrorStack> {
pub fn rsa_gen_keys_with_size(
p_bits: i32,
q_bits: i32,
) -> Result<(RsaPublicKey, RsaPrivateKey), ErrorStack> {
let mut ctx = BigNumContext::new()?;
loop {
@@ -87,6 +67,43 @@ pub fn rsa_gen_keys() -> Result<(RsaPublicKey, RsaPrivateKey), ErrorStack> {
rsa_gen_keys_with_size(512, 512)
}
fn extended_gcd(a: &BigUint, b: &BigUint) -> (BigInt, BigInt, BigInt) {
// https://brilliant.org/wiki/extended-euclidean-algorithm/
assert!(a < b, "a has to be smaller than b for extended GCD");
let mut a: BigInt = a.clone().into();
let mut b: BigInt = b.clone().into();
let mut x: BigInt = 0_i32.into();
let mut y: BigInt = 1_i32.into();
let mut u: BigInt = 1_i32.into();
let mut v: BigInt = 0_i32.into();
while a != 0_u32.into() {
let (q, r) = (&b / &a, &b % &a);
let m = &x - &u * &q;
let n = &y - &v * &q;
b = a;
a = r;
x = u;
y = v;
u = m;
v = n;
}
(b, x, y)
}
pub fn invmod_biguint(a: &BigUint, n: &BigUint) -> Option<BigUint> {
let r = extended_gcd(a, n);
match r {
(_, _, v1) if v1 == 0_i32.into() => None,
(_, u1, _) => {
let n = n.clone().to_bigint()?;
let r = ((&u1 % &n) + &n) % &n;
r.to_biguint()
}
}
}
pub fn invmod(a: &BigNum, n: &BigNum) -> Result<BigNum, ErrorStack> {
fn extended_gcd(a: BigNum, b: BigNum) -> Result<(BigNum, BigNum, BigNum), ErrorStack> {
// credit: https://www.dcode.fr/extended-gcd