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 ?