-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Summary
Add support for accepting a pre-computed clientDataHash (SHA-256) as an alternative to clientDataJSON in the D-Bus API. This aligns with Android and iOS platform APIs, and enables a wider range of WebAuthn integration scenarios.
Background
The CTAP2 specification defines that authenticator operations (authenticatorMakeCredential and authenticatorGetAssertion) accept a hash of the client data, not the raw JSON:
hash (0x01): Hash of the serialized client data, provided by the client.
Reference: FIDO CTAP2 Specification §6.1
While browser-based WebAuthn flows typically construct clientDataJSON locally, there are several scenarios where the caller may already have the hash:
- Cross-device authentication (CTAP2 Hybrid/caBLE) - The initiating device may provide the hash directly
- Native application integrations - Apps may negotiate client data with their backend
- Remote desktop/VDI scenarios - The remote server constructs clientData and transmits only the hash
- Proxy/relay architectures - Intermediate systems may only forward the hash
Prior Art - Platform API Parity
Both Android and iOS platform APIs support this pattern:
Android (Credential Manager API)
val request = GetPublicKeyCredentialOption(
requestJson = "...",
clientDataHash = clientDataHashBytes // Optional pre-computed hash
)Reference: Android Credential Manager Documentation
iOS (ASAuthorizationPublicKeyCredentialProvider)
let request = provider.createCredentialAssertionRequest(challenge: challenge)
request.clientDataHash = clientDataHash // Supports pre-computed hashReference: Apple Developer Documentation
Adding this support to credentialsd would bring Linux to feature parity with these platforms.
Proposed API Change
Add an optional client_data_hash parameter to the D-Bus methods:
Option A: New optional parameter (backward compatible)
<method name="MakeCredential">
<arg name="request_json" type="s" direction="in"/>
<arg name="client_data_hash" type="ay" direction="in"/> <!-- NEW: optional 32-byte SHA-256 -->
<arg name="response" type="a{sv}" direction="out"/>
</method>Behavior:
- If
client_data_hashis provided (non-empty), use it directly - If
client_data_hashis empty, compute hash fromrequest_json.clientDataJSON(current behavior)
Option B: Separate methods
<method name="MakeCredentialWithHash">
<arg name="request_json" type="s" direction="in"/>
<arg name="client_data_hash" type="ay" direction="in"/>
<arg name="response" type="a{sv}" direction="out"/>
</method>Use Case
This feature enables various integration scenarios where the caller has a pre-computed hash rather than raw JSON:
- Cross-device flows where another device initiated the WebAuthn ceremony
- Native applications with custom client data handling
- Remote desktop environments where authentication is redirected to the local machine
- Enterprise SSO integrations with proxy architectures
The key benefit is flexibility - allowing callers to provide either the raw JSON (current behavior) or a pre-computed hash when that's what they have available.
Security Considerations
This change maintains the same security model:
- The authenticator still requires user interaction (touch/PIN)
- The UI still displays the relying party information
- The cryptographic signature is still bound to the hash
The only difference is who computes the hash - the caller vs the credential service.
Implementation Notes
Looking at libwebauthn, the underlying register() and sign() functions may already work with the hash internally. The change would primarily be in:
- D-Bus interface definition (
xyz.iinuwa.credentials.xml) - Request parsing in
credentialsd - Passing the hash through to libwebauthn
Related
- W3C WebAuthn Level 3 §5.8.1 - client data hash computation
- FIDO CTAP2 Specification - authenticator protocol
- Android and iOS platform APIs (referenced above)
Questions
- Would you prefer Option A (optional parameter) or Option B (new method)?
- Are there any security considerations I might have missed?
- Is this something you're planning to implement, or would you be open to accepting a community contribution? I'd be happy to work on a PR if that would be helpful.
Thank you for considering this feature request!