Skip to content
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

definition of a webauthn varsig type #11

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,31 @@ sig-bytes = 128(OCTET)
| `es512-varsig-header` | `%x1202` | `%x8224` | P-521 [multicodec] prefix |
| `es512-hash-algorithm` | `%x13` | `%x13` | SHA2-512 [multicodec] prefix |

### 5.3.4 Example: Webauthn

``` abnf
webauthn-varsig = webauthn-varsig-header client-data-length client-data-json authenticator-data-length authenticator-data signature

webauthn-varsig-header = TODO
client-data-length = 1*unsigned-varint
client-data-json = *OCTET
authenticator-data-length = 1*unsigned-varint
authenticator-data = *OCTET
signature = varsig-body
```

The Webauthn varsig header notifies the consumer that the signature is generated via webauthn. Verification must therefor rely on the [`client-data-json`][Webauthn Client Data JSON] JSON object and the [`authenticator-data`][Webauthn Authenticator Data] bytestring. The `client-data-json` and `authenticator-data` byte strings must conform to the formats specified by the Webauthn spec. To enable the inclusion of the varsig in a byte stream, they each require a varint-encoded length prefix (`client-data-length` and `authenticator-data-length` respectively).

The signature itself is encoded as a varsig-body, containing hash and encoding info in the `signature` field. For example, a webauthn authenticator using `P-256` keys would result in a `signature` field which is a varsig-body conforming to the [`ES256` varsig body defined in section 5.3.1](#5.3.1-example:-es256). The signed payload is included in the signed data as the `challenge` field of the `client-data-json` as a [Multihash][Multihash]. This multihash MUST be made using the result of encoding the payload according to the parameters defined by the `signature` varsig body (for example, a DAG-CBOR encoded payload must have `signature.encoding-info` set to match). The `signature` field MUST be a signature type supported by the WebAuthn specification.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why use challenge = multihash and not challenge = cid? This way we would not need the signature.encoding-info field. (Afaik, the challenge can be longer than 32 bytes).

Copy link
Author

Choose a reason for hiding this comment

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

so that the other defined varsigs could be entirely reused instead of defining cut-down versions specific to webauthn. there will also be a tiny saving on length as the encoding won't be part of a base64 string, but that wasn't my main reason

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok, it would be helpful if you provided an example here to make the discussion easier.

Not sure what you mean by "base64 string"

Copy link
Author

Choose a reason for hiding this comment

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

will add an example 👍. For the base64 string, the client-data-json's challenge field which gets signed over is always a base64 encoding of the challenge which is passed in (as a byte array). Because the client-data-json is passed back as a byte array of what was signed, we can't repack it to make anything in there smaller.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Btw, it might make sense to sign over the CID regardless in light of #12

Copy link
Author

Choose a reason for hiding this comment

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

the CID doesnt capture the signature algorithm though, and indeed when it comes to webauthn there is no way to embed the signature algorithm in the challenge as the authenticator selection is up to the user via the UI. I can though see how it might be useful to capture the payload encoding in the signed data


Verification of this varsig follows these steps:
1. extraction of the `client-data-json` and `authenticator-data` from the varsig.
2. parse `client-data-json` as `cData`
3. extraction of the payload multihash from `cData.challenge` as `payloadHash`
4. parse `signature` as a varsig body
5. ensure that the extracted multihash matches the result of encoding the payload according to `signature.encoding-info` and hashing it with the hash function defined by `payloadHash.code`
6. verify the `signature` using the concatenation of `authenticator-data` and `sha2_256(client-data-json)` as the payload bytes (as defined by [WebAuthn signature creation][Webauthn Signature Creation])

# 6 Further Reading

* [Canonicalization Attacks Against MACs and Signatures][canonicalization attacks]
Expand All @@ -407,6 +432,7 @@ sig-bytes = 128(OCTET)
[IPLD]: https://ipld.io/docs/
[Multicodec]: https://github.com/multiformats/multicodec
[Multiformats]: https://multiformats.io
[Multihash]: https://multiformats.io/multihash/
[PKI Layer Cake]: https://link.springer.com/chapter/10.1007/978-3-642-14577-3_22
[Parse Don't Validate]: https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/
[RFC 2119]: https://datatracker.ietf.org/doc/html/rfc2119
Expand All @@ -416,3 +442,7 @@ sig-bytes = 128(OCTET)
[multicodec]: https://github.com/multiformats/multicodec
[raw binary multicodec]: https://github.com/multiformats/multicodec/blob/master/table.csv#L40
[unsigned varint]: https://github.com/multiformats/unsigned-varint
[Webauthn Client Data JSON]: https://w3c.github.io/webauthn/#dictionary-client-data
[Webauthn Authenticator Data]: https://w3c.github.io/webauthn/#sctn-authenticator-data
[Webauthn Signature Creation]: https://w3c.github.io/webauthn/#fig-signature
[Webauthn Attested Credential Data]: https://w3c.github.io/webauthn/#sctn-attested-credential-data