-
-
Notifications
You must be signed in to change notification settings - Fork 20
Add support for custom bytes in Wax.Challenge struct #47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Hi, and thanks for the PR! 2 questions:
Gonna take a look at your PR today. |
That's correct. We intend to add the passkey signature as metadata to the PDF and therefore must calculate the document digest from the content section of the PDF.
Sadly our solution does not include time stamping that's equivalent to how they work in signed PDFs. Ideally we would sign PDF docs using a proper document signing certificate which gives you a green tick on the signature panel in Acrobat Reader but sadly they are expensive to buy, have to be renewed every year and have hard storage requirements. There are PDF signing services too but their cost also does not scale for us. I'm now sharing my own opinion – my understanding of the timestamp in signed PDFs is to show it happened while the certificate was valid and helps to validate the document years after its signing certificate is expired. When signing documents with passkeys, timestamps may not matter as Passkeys never expire – they either exist in an authenticator or they don't. I could be truly wrong about what I'm sharing here 😂 please don't quote me on it. |
Thing is the specification seems to explicitly prohibit that: https://www.w3.org/TR/webauthn-3/#sctn-cryptographic-challenges We'll have to dig it further, as you can't make such changes to a security library without proper security analysis. Feel free to give me as much as input as you can (articles, libraries already supporting it...).
Fair enough, it was really out of curiosity :) |
I agree, you raised an important point about the WebAuthn specification and potential security implications. So I'll elaborate on the nuanced considerations: The WebAuthn specification indeed emphasizes the importance of using unique, random challenges to prevent replay attacks in authentication scenarios. However, our use case presents an interesting edge case where we're looking to create a cryptographic binding between a user's passkey and a specific document. While the standard session authentication flow should be done using random challenges, our approach aims to leverage the passkey as a form of document-specific signature. This differs from traditional authentication in that we're essentially using the passkey as a cryptographic attestation mechanism for a specific resource. I know at least one project that does something similar. The banana-passkey-eoa project provides an interesting precedent for our approach. However, your point is well-taken that we cannot casually modify a security library without thorough analysis. The other point to make is whether the proposed changes make it easy to make mistakes that were previous impossible. I don't believe is that is the case – there are existing opportunities for challenge reuse:
Thanks for referencing the other locations to update the docs. I will add them too. EDIT One more thought. I am not sure if Wax is currently doing anything to prevent replay attacks. I presume the challenge needs to be persisted in a more permanent basis to detect reuse 🤔 |
end | ||
|
||
test "does not override bytes when provided as an option" do | ||
assert %{bytes: "abcd"} = Challenge.new(bytes: "abcd") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A clearer test would be:
challenge = Challenge.new(...)
assert challenge.bytes == "abcd"
Additional resources:
Please consider adding it to the security considerations I just updated |
@armanm any update? Did you see my comments? :) |
This PR adds support for supplying custom bytes when creating a
%Wax.Challenge{}
struct.This enhancement is significant because these bytes (referred to as "cryptographic challenge" in the Passkey standard) are signed by the authenticator, with the signature returned as part of the AuthenticatorAssertionResponse.signature.
The practical value is that this signature creates a cryptographic connection between the passkey and the provided bytes, serving as strong proof of an activity. For example, in our workflow where passkey presentation is required before performing a legal action, we can use the resulting signature as irrefutable proof that a user has taken a very specific action.