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:
pub fn sign(&self, z: FieldElement) -> Signature {
let params = Secp256k1Param::new();
let k = BigInt::from(get_rndm(¶ms.n()));
let k = FieldElement {
num: k,
prime: params.prime(),
};
let r = params.generator().multiply(&k);
let k_inv = k.num().modpow(&(params.n().sub(2)), ¶ms.n());
let s = (k_inv * (&z.num + (&r.x.num() * &self.prk))) % ¶ms.n();
let s = FieldElement {
num: s,
prime: params.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();
let h = hash(&z.num().to_string(), None).num();
let left_side = params.generator().multiply(&FieldElement::new(h * &signature.s.num().modpow(&(params.n().sub(2)), ¶ms.n()), params.prime()));
let right_side = signature.r.multiply(&FieldElement::new(signature.s.num().modpow(&(params.n().sub(2)), ¶ms.n()) * &self.pk(), params.prime()));
let r2 = left_side.add(&right_side);
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!("signature is invalid");
}