authereum / contracts

🛡️ Authereum smart contracts
https://github.com/authereum/contracts
MIT License
55 stars 17 forks source link

When different type of EIP1271 signatures are used? #7

Open dvush opened 3 years ago

dvush commented 3 years ago

Hi, we are having some problems when users are using authereum wallet with zkSync.

It looks like this issue is caused by EIP1271 signature verification. I am wondering if it can be because there are two types of EIP1271 signatures that your wallet can produce: one is 65 byte long other is larger.

We use user signatures of the message to check for correctness and it fails sometimes. Can you please explain how user signatures work in authereum?

cwhinfrey commented 3 years ago

Hi @dvush, What you're saying is all correct. The signature that Authereum returns from a regular eth_sign is a 1271 signature that is twice the length of a normal signature. This allowed by the ERC1271 standard. The data is actually two signatures but your software can be unconcerned about how it's formatted. If the double length signature is checked against the account contract using the ERC1271 isValidSignature method, it will work as expected.

By the way, we have a package that makes it easy to check both 1271 and regular signatures. It checks if the signer address is a contract or not and then recovers the signature with the appropriate method, ERC 1271 or a regular ECDSA recovery. It's also backward compatible with different versions of ERC 1271 that existed before it was finalized. It might be helpful for you.

https://www.npmjs.com/package/is-valid-signature

Also, if you're still having trouble getting the signature to verify, would be happy to help debug if you can provide some more context or point me to some code.

dvush commented 3 years ago

Hi @cwhinfrey - thanks for the explanation, here are some tests that we did and we are sure that problems that we have is not connected to zkSync.

What I was able to see from our tests is this:

We wrote simple web app that just connects with WalletConnect and signs message using either: eth_sign or personal_sign.

  1. When this app is deployed to localhost signatures are incorrect (EIP1271 can't verify them, we tried all the method). Signature is 65 bytes long (so it should be usual signature with authKey). Ecreover returns same address for different messages but that address is not in authKey.
  2. When we deploy the same app but for domain (something).zksync.io then what we see is: eth_sign returns the same signature as localhost and it is not correct, personal_sign returns different signature and it is correct (it is verifiable onhchain and ECreover of it is authKey)
  3. For zkSync we have two main dapps: checkout.zksync.io and wallet.zksync.io and we use EIP1271 signatures. wallet.zksync.io works normally but checkout.zksync.io is not - signatures there are incorrect. I assume it is similar bug to mentioned in 1. - because we use personal_sign in our code. Also we assume that signature of specific message is deterministic - this way user can use our dapp without storing additional data. Is it possible to specify that we want to have signature using some specific auth key?
cwhinfrey commented 3 years ago

Hey @dvush, I'm not sure why those signatures aren't being verified for 1 and 2. We'll look into this and circle back with more info.

we do have a persistent signing key that you can use and will be deterministic but can't be verified with ERC1271. This is because our ERC1271 signature verification is based around the authKeys and authKeys can be removed at anytime invalidating the signature. We'll discuss this as well and come back with a recommendation for your use case.