Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

Conversation

JohnGuilding
Copy link
Contributor

@JohnGuilding JohnGuilding commented Sep 14, 2023

This PR properly extracts the client challenge and validates it. The reason this wasn't working originally is because the code actually needed to use base64url encoding instead of base64 encoding to encode the clientChallenge in FCL_WebAuthn.

Base64URL encoding

The clientChallenge with base64url encoding is equal to NTo-1aBEGRnxxjmkaTHehyrDNX3izlqi1owmOd9UGJ0. Whereas the base64 encoding of that is NTo+1aBEGRnxxjmkaTHehyrDNX3izlqi1owmOd9UGJ0=. This resulted in the hash being incorrect which the extracted challenge was compared to. Therefore the assertion failed and an error was thrown.

Why did the original ledger implementation not use base64URL encoding?

It turns out the implementation located in src/ is different to the implementation that is tested against in tests/. If you look at the Fresh Crypto Lib (FCL) implementation, you can see that it does indeed use base64 encoding. Since I copied that file originally, I expected that to work. It turns out that the FCL tests do actually use base64url encoding instead! See this link here.

Does that mean we always have to use base64url encoding now?

TLDR: Not sure. Need to refresh my knowledge of how webauthn handles encoding clientData, and whether that is something we can manage. Ideally the aim is to not edit the FCL library contract at all. Added an issue to investigate this further - #84

### copyBytes function
Since we haven't implemented #68 yet, we couldn't use the original clientChallenge validation logic still, as that relied on the arguments being stored as calldata. As a temporary solution until we fix that, I've chosen to use a function called copyBytes. This is taken from the original webauthn solidity implementation which FCL_WebAuthn is based on. You can see the original code for that here.
^ #68 has been merged so we don't need to use the copyBytes function anymore

The PR also updates the webauthn sig values used throughout the tests to use a valid clientChallenge (I was using incorrect values such as the userOp hash before)

@JohnGuilding JohnGuilding marked this pull request as ready for review September 14, 2023 16:50
- Use base64url encoding
- Add copyBytes function to replace assembly calldatacopy logic
- Update webauthn sig values
- Use updated clientChallenge
@JohnGuilding JohnGuilding force-pushed the 44-extract-webauthn-challenge-from-clientData-and-compare-to-clientChallenge branch from a86e783 to dee5171 Compare September 15, 2023 14:46
s.clientChallengeDataOffset
) = abi.decode(
userOp.signature[i:i+dataLen],
(
bytes1,
uint256, //not sure what is encoded here
bytes32,
Copy link
Contributor Author

@JohnGuilding JohnGuilding Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^I'm not sure why this is the order for the decoding, I originally assumed it would have been bytes before uints like so:

(
    bytes1,
    bytes32,
    uint256, 
    uint256
)

The screenshot below shows the difference between the two signatures. The older signature without the clientChallenge is on the left, and the newer signature with the clientChallenge is on the right:

Screenshot 2023-09-15 at 16 12 30

You can see where the clientChallenge was added, look for 353a3ed5a0441919f1c639a46931de872ac3357de2ce5aa2d68c2639df54189d. There were some other changes which I'm not too sure about. It looks like the mystery uint256 changed. The value in the first 32 bytes was also changed, again not sure what that change means - @jzaki any ideas?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ordering of these fixed length vars is as they were encoded.
The additional 0x20 (32) on the length is the additional 32 bytes added.
The mystery number seems to be a length, since it also increased by 0x20. Will create an issue to get to the bottom of why and how that gets encoded in.

s.clientChallengeDataOffset
) = abi.decode(
userOp.signature[i:i+dataLen],
(
bytes1,
uint256, //not sure what is encoded here
bytes32,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ordering of these fixed length vars is as they were encoded.
The additional 0x20 (32) on the length is the additional 32 bytes added.
The mystery number seems to be a length, since it also increased by 0x20. Will create an issue to get to the bottom of why and how that gets encoded in.

@@ -135,4 +132,4 @@ library FCL_WebAuthn {

return result;
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this file is now back to it's original version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite, I raised #93 to revert more of the libs back to their original state. Remaining work to restore to it's original state is covered by #84 & #94

@JohnGuilding JohnGuilding merged commit 5850f85 into main Sep 18, 2023
2 checks passed
@JohnGuilding JohnGuilding deleted the 44-extract-webauthn-challenge-from-clientData-and-compare-to-clientChallenge branch September 18, 2023 11:57
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Extract webauthn challenge from clientData and compare to clientChallenge
2 participants