# tECDSA Signature Verification Returns Different Sender Address Each Time

**URL:** <https://forum.dfinity.org/t/tecdsa-signature-verification-returns-different-sender-address-each-time/26878>\
**Category:** Developers\
**Created:** [January 22, 2024, 7:39am UTC](https://forum.dfinity.org/t/tecdsa-signature-verification-returns-different-sender-address-each-time/26878 "2024-01-22T07:39:19Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![princess\_eth](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@princess\_eth](https://forum.dfinity.org/u/princess_eth)\
**Post date:** [January 22, 2024, 7:39am UTC](https://forum.dfinity.org/t/tecdsa-signature-verification-returns-different-sender-address-each-time/26878/1 "2024-01-22T07:39:19Z")

</div>

After reviewing the tECDSA documents and examples, I understand that the `sign_with_ecdsa` method is signing using the key from the canister root key or a key obtained through further derivation.

So in theory, as in the [tECDSA Rust example](https://github.com/dfinity/examples/tree/master/rust/threshold-ecdsa), this sign function:

```auto
async fn sign(message: String) -> Result<SignatureReply, String> {
    let request = SignWithECDSA {
        message_hash: sha256(&message).to_vec(),
        derivation_path: vec![],
        key_id: EcdsaKeyIds::TestKeyLocalDevelopment.to_key_id(),
    };

    let (response,): (SignWithECDSAReply,) = ic_cdk::api::call::call_with_payment(
        mgmt_canister_id(),
        "sign_with_ecdsa", 
        (request,),
        25_000_000_000,
    )
    .await
    .map_err(|e| format!("sign_with_ecdsa failed {}", e.1))?;

    Ok(SignatureReply {
        signature_hex: format!("0x{}", hex::encode(&response.signature)),
    })
}

```

should be signed using the public key generated by this `ecdsa_public_key` method, given that I am not changing the deviation path between the two functions and using them in the same canister.

```auto
async fn public_key() -> Result<PublicKeyReply, String> {
    let request = ECDSAPublicKey {
        canister_id: None,
        derivation_path: vec![],
        key_id: EcdsaKeyIds::TestKeyLocalDevelopment.to_key_id(),
    };

    let (res,): (ECDSAPublicKeyReply,) =
        ic_cdk::call(mgmt_canister_id(), "ecdsa_public_key", (request,))
            .await
            .map_err(|e| format!("ecdsa_public_key failed {}", e.1))?;

    Ok(PublicKeyReply {
        public_key_hex: hex::encode(&res.public_key),
    })
}

```

In my code, I convert the public key to an Ethereum address. However, when I deploy this and attempt to send an Ethereum transaction, I always receive an “insufficient funds to pay for gas” error. I initially assumed the Ethereum address of the public key generated by my canister did not have enough funds.

To confirm, I used `ethers` to verify a signature (received from the sign function) against the message I passed in (matching the one sent to the sign function). Surprisingly, this returned a different Ethereum address each time.

I assume that there could be a possibility that the sign function is signing a different public key each time.

1. Should I be explicit with the canister ID in the request to sign\_with\_ecdsa?
2. Is there anything else that I could be overlooking?

---

<div class="post-metadata">

**Author:** ![gregory-demay](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/gregory-demay/32/8165_2.png) [@gregory-demay](https://forum.dfinity.org/u/gregory-demay)\
**Post date:** [January 22, 2024, 3:51pm UTC](https://forum.dfinity.org/t/tecdsa-signature-verification-returns-different-sender-address-each-time/26878/2 "2024-01-22T15:51:34Z")

</div>

Hi @princess_eth

I will try to go over your points

> should be signed using the public key generated by this `ecdsa_public_key` method,

Here I would like to clarify a few things to ensure there is no misunderstanding. The public key doesn’t sign anything. What should be retrieved here is the public key whose corresponding “private key was used to sign the message” (what actually happens is that each replica uses its share of the private key to sign the message and then broadcast its signature share. Once a replica has enough signature shares it can combine them into a standard looking ECDSA signature).

> To confirm, I used `ethers` to verify a signature (received from the sign function) against the message I passed in (matching the one sent to the sign function). Surprisingly, this returned a different Ethereum address each time.

I’m not entirely sure what you mean here. Do you mean that the library you used (`ethers`) did validate the signature but it recognized the signed messages as being sent from a different Ethereum address each time? If that’s the case, then most likely this is because the public key changed between your different trials and that’s most likely the case because your canister ID changed. Did you maybe redeploy each time between your trials?

> I assume that there could be a possibility that the sign function is signing a different public key each time.

The public key should remain stable with your canister ID (and chosen curve). Could you maybe double check whether your canister ID changed between your trials?

> 1. Should I be explicit with the canister ID in the request to sign\_with\_ecdsa?

This should not be necessary, the [Rust doc](https://github.com/dfinity/cdk-rs/blob/main/src/ic-cdk/src/api/management_canister/ecdsa/types.rs#L11) states

```rust
pub struct EcdsaPublicKeyArgument {
    /// Canister id, default to the canister id of the caller if None.
    pub canister_id: Option<CanisterId>,
   ...
}

```

---

<div class="post-metadata">

**Author:** ![lastmjs](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/lastmjs/32/3406_2.png) [@lastmjs](https://forum.dfinity.org/u/lastmjs)\
**Post date:** [March 2, 2024, 12:22am UTC](https://forum.dfinity.org/t/tecdsa-signature-verification-returns-different-sender-address-each-time/26878/3 "2024-03-02T00:22:38Z")

</div>

Hey I am running into something that might not by the same, but similar. I have made sure that my canister id is the same always by using specified\_id, and I am calling `ecdsa_public_key` with the same derivation path each time and an empty canister\_id.

I get a different address every time I start dfx with `--clean`…why is this? Is there anyway to stop this from happening? It’s going to make testing difficult, and I would also like to understand why this is the case.

---

<div class="post-metadata">

**Author:** ![domwoe](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/domwoe/32/5165_2.png) [@domwoe](https://forum.dfinity.org/u/domwoe)\
**Post date:** [March 2, 2024, 6:10am UTC](https://forum.dfinity.org/t/tecdsa-signature-verification-returns-different-sender-address-each-time/26878/4 "2024-03-02T06:10:40Z")

</div>

You can think of using —clean as setting up a fresh instance of the IC with new master keys (both BLS and ECDSA). Hence, your canister’s derived key will be different each time.

---

<div class="post-metadata">

**Author:** ![lastmjs](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/lastmjs/32/3406_2.png) [@lastmjs](https://forum.dfinity.org/u/lastmjs)\
**Post date:** [March 2, 2024, 6:27am UTC](https://forum.dfinity.org/t/tecdsa-signature-verification-returns-different-sender-address-each-time/26878/5 "2024-03-02T06:27:40Z")

</div>

It would be nice to be able to seed those keys somehow for reproducibility

---

<div class="post-metadata">

**Author:** ![Rachit2323](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/rachit2323/32/19417_2.png) [@Rachit2323](https://forum.dfinity.org/u/Rachit2323)\
**Post date:** [September 17, 2024, 9:30am UTC](https://forum.dfinity.org/t/tecdsa-signature-verification-returns-different-sender-address-each-time/26878/6 "2024-09-17T09:30:18Z")

</div>

Have you solved the issue , I am facing the same issue?
