mirror of
https://github.com/MichaelGrafnetter/webauthn-interop
synced 2026-08-09 12:12:33 +00:00
Expose authenticator AAGUID as Guid instead of raw bytes (#43)
* Expose authenticator AAGUID as Guid instead of raw bytes The Win32 WebAuthNGetAuthenticatorList API returns the authenticator identifier as a big-endian encoded GUID, which is in fact the Authenticator Attestation GUID (AAGUID). Decode it into a Guid in the wrapper instead of surfacing the raw bytes (previously Base64Url-encoded in the UI and PowerShell output). - Rename AuthenticatorDetails.AuthenticatorId (byte[]) to AaGuid (Guid) and decode the big-endian bytes in ApiHelper.Translate. - Display the value as a GUID in the PasskeyUI authenticator list, renaming the column to 'AAGUID'. - Update the Get-PasskeyAuthenticator format views accordingly. - Update API docs and CHANGELOG. * Remove unused EndianBitConverter helper EndianBitConverter was dead code: all of its members (ToUInt32BigEndian, ToUInt16BigEndian, ToGuidBigEndian, SwapBytes) were only referenced within the file itself. Big-endian GUID decoding now goes through the GuidPolyfill.Create helper used elsewhere in the codebase. * Make AuthenticatorDetails.AaGuid nullable Return null instead of Guid.Empty when the Win32 API does not provide a valid 16-byte authenticator identifier, so the absence of an AAGUID is represented distinctly rather than as an all-zero GUID. --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
2265792276
commit
3a05986c82
@@ -29,17 +29,17 @@ Corresponds to WEBAUTHN_AUTHENTICATOR_DETAILS.
|
||||
|
||||
## Properties
|
||||
|
||||
### <a id="DSInternals_Win32_WebAuthn_AuthenticatorDetails_AuthenticatorId"></a> AuthenticatorId
|
||||
### <a id="DSInternals_Win32_WebAuthn_AuthenticatorDetails_AaGuid"></a> AaGuid
|
||||
|
||||
The authenticator Id.
|
||||
The Authenticator Attestation GUID (AAGUID) identifying the model of the authenticator.
|
||||
|
||||
```csharp
|
||||
public byte[]? AuthenticatorId { get; set; }
|
||||
public Guid? AaGuid { get; set; }
|
||||
```
|
||||
|
||||
#### Property Value
|
||||
|
||||
[byte](https://learn.microsoft.com/dotnet/api/system.byte)\[\]?
|
||||
[Guid](https://learn.microsoft.com/dotnet/api/system.guid)?
|
||||
|
||||
### <a id="DSInternals_Win32_WebAuthn_AuthenticatorDetails_AuthenticatorLogo"></a> AuthenticatorLogo
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. The format
|
||||
|
||||
- `WebAuthnApi.AuthenticatorGetAssertion` now prefers the native `pbAuthenticationResponseJSON` returned in `WEBAUTHN_ASSERTION_VERSION_6` when present, deserializing the full credential (including `clientExtensionResults`) verbatim from the OS-produced JSON. The legacy field-by-field assembly and per-extension recomputation remain as a fallback for older OS versions.
|
||||
- `WebAuthnApi.AuthenticatorMakeCredential` now prefers the native `pbRegistrationResponseJSON` returned in `WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_8` when present, deserializing the full credential verbatim from the OS-produced JSON. The legacy field-by-field assembly and per-extension recomputation remain as a fallback for older OS versions.
|
||||
- The `AuthenticatorDetails.AuthenticatorId` property (returned by `Get-PasskeyAuthenticator`) was renamed to `AaGuid` and its type changed from `byte[]` to `Guid?`. The binary identifier returned by the Win32 API is a big-endian encoded Authenticator Attestation GUID (AAGUID), so it is now decoded and surfaced as a `Guid` (or `null` when absent) instead of a Base64Url-encoded string.
|
||||
|
||||
## [3.1.0] - 2026-05-14
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
<ListEntry>
|
||||
<ListItems>
|
||||
<ListItem>
|
||||
<Label>AuthenticatorId</Label>
|
||||
<ScriptBlock>[System.Buffers.Text.Base64Url]::EncodeToString($PSItem.AuthenticatorId)</ScriptBlock>
|
||||
<Label>AAGUID</Label>
|
||||
<PropertyName>AaGuid</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>AuthenticatorName</PropertyName>
|
||||
@@ -36,8 +36,8 @@
|
||||
<TableControl>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Label>AuthenticatorId</Label>
|
||||
<Width>45</Width>
|
||||
<Label>AAGUID</Label>
|
||||
<Width>38</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>AuthenticatorName</Label>
|
||||
@@ -51,7 +51,7 @@
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<ScriptBlock>[System.Buffers.Text.Base64Url]::EncodeToString($PSItem.AuthenticatorId)</ScriptBlock>
|
||||
<PropertyName>AaGuid</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>AuthenticatorName</PropertyName>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace DSInternals.Win32.WebAuthn;
|
||||
using System;
|
||||
|
||||
namespace DSInternals.Win32.WebAuthn;
|
||||
|
||||
/// <summary>
|
||||
/// Information about an authenticator.
|
||||
@@ -7,9 +9,9 @@
|
||||
public sealed class AuthenticatorDetails
|
||||
{
|
||||
/// <summary>
|
||||
/// The authenticator Id.
|
||||
/// The Authenticator Attestation GUID (AAGUID) identifying the model of the authenticator.
|
||||
/// </summary>
|
||||
public byte[]? AuthenticatorId { get; set; }
|
||||
public Guid? AaGuid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The authenticator name.
|
||||
|
||||
@@ -253,7 +253,7 @@ namespace DSInternals.Win32.WebAuthn.Interop
|
||||
{
|
||||
result.Add(new AuthenticatorDetails
|
||||
{
|
||||
AuthenticatorId = authenticator.AuthenticatorId,
|
||||
AaGuid = DecodeAaGuid(authenticator.AuthenticatorId),
|
||||
AuthenticatorName = authenticator.AuthenticatorName,
|
||||
AuthenticatorLogo = DecodeBinaryLogo(authenticator.AuthenticatorLogo),
|
||||
Locked = authenticator.Locked
|
||||
@@ -263,6 +263,17 @@ namespace DSInternals.Win32.WebAuthn.Interop
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the authenticator identifier returned by the Win32 API, which is the AAGUID encoded as a big-endian GUID.
|
||||
/// </summary>
|
||||
private static Guid? DecodeAaGuid(byte[]? authenticatorId)
|
||||
{
|
||||
// The AAGUID is always a 16-byte big-endian encoded GUID.
|
||||
return authenticatorId is { Length: 16 }
|
||||
? Guid.Create(authenticatorId, bigEndian: true)
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a byte array logo (expected UTF-8 SVG) to a string.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace DSInternals.Win32.WebAuthn.Interop
|
||||
{
|
||||
internal static class EndianBitConverter
|
||||
{
|
||||
public static uint ToUInt32BigEndian(this byte[] bytes, int startIndex = 0)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
return BitConverter.ToUInt32(bytes, startIndex);
|
||||
}
|
||||
|
||||
public static ushort ToUInt16BigEndian(this byte[] bytes, int startIndex = 0)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
return BitConverter.ToUInt16(bytes, startIndex);
|
||||
}
|
||||
|
||||
public static Guid ToGuidBigEndian(this byte[] bytes)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
bytes.SwapBytes(0, 3);
|
||||
bytes.SwapBytes(1, 2);
|
||||
bytes.SwapBytes(4, 5);
|
||||
bytes.SwapBytes(6, 7);
|
||||
}
|
||||
|
||||
return new Guid(bytes);
|
||||
}
|
||||
|
||||
public static void SwapBytes(this byte[] bytes, int index1, int index2)
|
||||
{
|
||||
var temp = bytes[index1];
|
||||
bytes[index1] = bytes[index2];
|
||||
bytes[index2] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,10 +56,10 @@
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
<DataGridTemplateColumn Header="Authenticator ID" Width="280" MinWidth="80" SortMemberPath="AuthenticatorId">
|
||||
<DataGridTemplateColumn Header="AAGUID" Width="280" MinWidth="80" SortMemberPath="AaGuid">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<local:ClipboardEnabledTextBlock Text="{Binding AuthenticatorId, Converter={StaticResource ByteArrayToBase64UrlConverter}}" />
|
||||
<local:ClipboardEnabledTextBlock Text="{Binding AaGuid}" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
Reference in New Issue
Block a user