Score:1

Troubleshooting ECDSA implementation in rust

lb flag

I'm trying to implement ECDSA for learning purposes and have generated public and private keys, which seem to be correct as I have compared them with those generated by an online tool called noble. However, my signing or verification algorithm (or both) is not working correctly and I am having difficulty debugging the code due to my lack of cryptographic or mathematical background. I have been trying to fix the issue for the past two days with no luck any second eye would really be appreciated. If there are any important details that I have missed in this description, please let me know and I will modify the post.

Btw I'm implementing The algorithms based on cryptobook nakov

this is my signing algorithm:

    // FieldElement struct is just num % prime
 pub fn sign(&self, z: FieldElement) -> Signature {
        // this struct contains all secp256k1 parameters
        let params = Secp256k1Param::new();
        // get a random 1 < k < n - 1
        let k = BigInt::from(get_rndm(&params.n()));
        // wrape it in a FieldElement to be able to multiply it with the generator
        // k % prime
        let k = FieldElement {
            num: k,
            prime: params.prime(),
        };
        // r = k * G
        let r = params.generator().multiply(&k);
        // k_inv = k^-1 = k^(n-2) mod n
        let k_inv = k.num().modpow(&(params.n().sub(2)), &params.n());
        // s = k^-1 * (z + r * d) mod n
        let s = (k_inv * (&z.num + (&r.x.num() * &self.prk))) % &params.n();
        // wrap s in a FieldElement
        let s = FieldElement {
            num: s,
            prime: params.prime(),
        };

        // signature is struct {r, s} where r is an EllipticPoint and s is a FieldElement
        // EllipticPoint {x, y, a, b}
        // FieldElement {num, prime}
        let sign = Signature { r, s };
        sign

and this is my verification algorithm:

    pub fn verify(&self, z: FieldElement, signature: Signature) -> bool {
        let params = Secp256k1Param::new();
        // calculating the hash of the message h = hash(z)
        let h = hash(&z.num().to_string(), None).num();
        // r' = (h * s^-1) * G + (r * s^-1 * pk)
        // (h * s^-1) * G  (I'm sure that multiplication method in EllipticPoint is correct since i used it in Public/private key generation and they're correct)
        let left_side =  params.generator().multiply(&FieldElement::new(h * &signature.s.num().modpow(&(params.n().sub(2)), &params.n()), params.prime()));
        // (r * s^-1 * pk)
        let right_side = signature.r.multiply(&FieldElement::new(signature.s.num().modpow(&(params.n().sub(2)), &params.n()) * &self.pk(), params.prime()));
        // r' = (h * s^-1) * G + (r * s^-1 * pk)
        let r2 = left_side.add(&right_side);
        // equality of two elliptic points is the equality of their x,y,a,b coordinates
        r2.eq(&signature.r)
    }

my tests are simply:

  let params = Secp256k1Param::new();
    let keys = ECDSA::new("my secret key".to_string());
    println!("private key: {}", keys.prk());
    println!("public key: {}", keys.pk());
    //
    let msg = "hello world";
    let msg_hash = hash(msg, None);
    println!("message hash: {}", msg_hash.num().to_str_radix(16));
    
    let signature = keys.sign(msg_hash.clone());
    if keys.verify(msg_hash, signature) == true {
        println!("signature is valid");
    } else {
        // println!("s: {}", signature.s.num().to_str_radix(16));
        println!("signature is invalid");
    }
fgrieu avatar
ng flag
There is no reason for $k$ to be viewed as an element of field $\mathbb F_p$. It's more useful to view it as an element of field $\mathbb F_n$, but neither allows "to multiply it with the generator". Same for $s$. The $r$ of your signature is $kG$, it should be the X coordinate of $kG$ reduced modulo $n$ (your linked reference forgets that reduction; it's NOT what causes the issue). Hashing is part of signing. I suggest using [this](https://www.secg.org/sec1-v2.pdf#subsection.4.1) as true reference for ECDSA, and [this](https://www.secg.org/sec2-v2.pdf#subsubsection.2.4.1) for secp256k1
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.