Clean up and consider BigUint as alternative to BigNum for RSA implementation
This commit is contained in:
69
src/rsa.rs
69
src/rsa.rs
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user