Ethereum uses deterministic ECDSA for message signing, ensuring that the signature for “same message and same key” remains the same every time you sign.
Does the threshold ECDSA of the internet computer support this as well? I cannot find any information about this RFC 6979 feature. The “k” value needs to be generated securely based on the private key and the hash of the message you want to sign.
What I want to achieve is to securely generate a seed value in a canister based on a message (an eth address). The seed should remain the same when the message is the same.
The value k is random and not known to any single entity but generated jointly by a group of nodes in the ECDSA signing service. You could imagine workarounds to get determinism, e.g. MPC supporting this or keeping a lookup table of previously signed messages to avoid resigning, but this is not supported (and looks cumbersome, unlike in the singe-signer setting, where it is easy to generate k pseudorandomly&deterministically based on the message and secret seed know to the single-signer entity).
Not sure what you have in mind wrt seed, but sounds like it might be supported by VetKeys
Ah, great will look more into VetKeys.
Use case is about SIWE (Sign in with ethereum):
- Canister produces a onetime SIWE message
- User signs message with eth wallet, calls canister with signature
- Canister validates signature, recovers address (Canister now have secure knowledge about which eth address is being controlled in frontend)
- Canister produces a seed and an identity/principal based on this seed
- Canister links the principal with the eth address, creating a “session” based on rules from SIWE message (expires_at etc)
- Canister returns seed (or identity) to user
- This identity/seed should be the same every time for a given address
- User generates an Identity based on the seed, this Identity will have same principal as canister generated identity
Then, for the duration of the “session”:
- User makes canister call with generated Identity
- Canister checks validity of session. Canister securely knows that the SIWE flow was used to generate this identity. Canister also securely knows which eth address can be said to be “represented by” the Identity.
Why does it have to be same seed/principal every time? It sounds like you are just using the principal for the duration of the session and are always linking it back to the Eth address. So if it always linked to the Eth address anyway then why isn’t it enough if only the Eth address is permanent and the principal changes from session to session?
It sounds like you want to delegate from an Eth address to a principal for the duration of a session, which is a common concept, but the concept doesn’t usually require that the delegatee is the same ever time. Is there anything different/special here in your application?
My interest is not tied to a specific app, I am looking to create a generic library around SIWE (Sign in with Ethereum).
I agree, in some cases, a new principal for each session works fine. Like you say, you delegate from an Ethereum address to a temporary principal during the session. But that implies the app uses only limited IC functionality. For example, Uniswap might want to store user profile information not on Ethereum (obviously) and choose IC over IPFS to avoid the issues with data pinning.
In other scenarios, a more “equal” relationship is desired. How would a 50/50 ETH/IC app look? An app that does some things on Ethereum but also wants to handle ICRC tokens. In such cases, it could be beneficial to establish a 1:1 relationship between an Ethereum address and an IC principal.
Finally, you have the app scenario where Ethereum is just another sign-in mechanism, similar to other WebAuthn methods. Ethereum is used for login mainly because the app targets the large user base already accustomed to logging in with Metamask. Everything else, except for login, happens on IC. The arguments for having the same principal in each session are the same as when logging in with Internet Identity.
Adding to above:
The most straight forward solution to this problem is to let the user generate an identity prior to “logging in” to the canister. The user signs a static message using their eth wallet. Since eth wallets are using deterministic ECDSA (as per RFC 6979), the hash of that signature then can be used as the seed for the identity. This identity can be stored in the browser if that is an acceptable security level for the app in question.
After creating the identity, logging in to the canister using SIWE proceeds, with the user signing the canister generated SIWE as described above.
Only drawback with this approach is that user has to sign two messages when first using the app. One would have been better UX.