Porting BSGS (ECDSA) on rust

107 Views Asked by At

Hi guys I'm porting Baby step Giant Step algorithm from examples displayed here to Rust programming language. https://github.com/ashutosh1206/Crypton the normal version is ported successfully without problems here is an example.

use serde::{Deserialize, Serialize};
use num_bigint::BigUint;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BSGS(String);
pub struct Parallel(String);


use rayon::prelude::*;
use num_traits::{One, Zero};
use std::collections::HashMap;
use std::sync::{Mutex, Arc};
// https://github.com/ashutosh1206/Crypton/blob/master/Discrete-Logarithm-Problem/Algo-Baby-Step-Giant-Step/bsgs.py




impl BSGS {
    // """
    // Reference:

    // To solve DLP: h = g^x % p and get the value of x.
    // We use the property that x = i*m + j, where m = ceil(sqrt(n))

    // :parameters:
    //     g : int/long
    //             Generator of the group
    //     h : int/long
    //             Result of g**x % p
    //     p : int/long
    //             Group over which DLP is generated. Commonly p is a prime number

    // :variables:
    //     m : int/long
    //             Upper limit of baby steps / giant steps
    //     x_poss : int/long
    //             Values calculated in each giant step
    //     c : int/long
    //             Giant Step pre-computation: c = g^(-m) % p
    //     i, j : int/long
    //             Giant Step, Baby Step variables
    //     lookup_table: dictionary
    //             Dictionary storing all the values computed in the baby step
    // """
    pub fn new(bsgs: String) -> Self {
        Self(bsgs)
    }
    


    pub fn run(g: &BigUint, h: &BigUint, p: &BigUint) -> Option<BigUint>  {
        let mod_size = p.bits();

        println!("[+] Using BSGS algorithm to solve DLP");
        println!("[+] Modulus size: {}. Warning! BSGS not space efficient\n", mod_size);
    
        let m = (*&p - BigUint::one()).sqrt() + BigUint::one();
        let mut lookup_table: HashMap<BigUint, BigUint> = HashMap::new();
    
        // Baby Step
        let mut j = BigUint::zero();
        while &j < &m {
            let key = g.modpow(&j, &p);
            lookup_table.insert(key.clone(), j.clone());
            j += BigUint::one();
        }

    
        // Giant Step pre-computation
        let c = g.modpow(&(&m * (*&p - BigUint::from(2u32))), &p);
    
        // Giant Steps
        let mut i = BigUint::zero();
        while &i < &m {
            let temp = &(h * &c.modpow(&i, &p)) % p;
            if let Some(j) = lookup_table.get(&temp) {
                // x found
                return Some(i * &m + j);
            }
            i += BigUint::one();
        }
    
        None
    }
}

but I'm having a hard time porting the Ecurve defined as:

from sage.all import *

def bsgs_ecdlp(P, Q, E):
    if Q == E((0, 1, 0)):
        return P.order()
    if Q == P:
        return 1
    m = ceil(sqrt(P.order()))
    lookup_table = {j*P: j for j in range(m)}
    for i in range(m):
        temp = Q - (i*m)*P
        if temp in lookup_table:
            return (i*m + lookup_table[temp]) % P.order()
    return None

if __name__ == "__main__":
    import random
    E = EllipticCurve(GF(17), [2, 2])
    try:
        for i in range(100):
            x = random.randint(2, 19)
            assert bsgs_ecdlp(E((5, 1)), x*E((5, 1)), E) == x
    except Exception as e:
        print e
        print "[-] Something's wrong!"

this part here is giving me headaches, as it is using sage to do the keys substraction. as the module secp256k1 in rust follow a different pattern what would be the optimal way to do it.

temp = Q - (i*m)*P

my intuition tells me that the (i*m)*P part is just

        let secp = Secp256k1::new();
        let pub_key = PublicKey::from_secret_key(&secp, &secret);

where secret is (i*m) operation. but how to do Q - New_Pub_Key_points in rust ?

0

There are 0 best solutions below