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

Illegal Base64URL string #21

Open
JMarkstrom opened this issue Nov 17, 2024 · 8 comments
Open

Illegal Base64URL string #21

JMarkstrom opened this issue Nov 17, 2024 · 8 comments
Assignees
Labels
bug Something isn't working

Comments

@JMarkstrom
Copy link

Hi Michael,
Having installed v. 1.0.3 (passkey module only) and running command:

Register-Passkey -UserId 'username@domain.com' -DisplayName 'YubiKey 5C NFC'

Getting error:

ParentContainsErrorRecordException: Exception calling "Create" with "1" argument(s): "Illegal Base64URL string! (Parameter 'input')"

In readme.md you state:

The DSInternals.Passkeys PowerShell module uses the DSInternals.Win32.WebAuthn library...

Should I understand this as I might be missing a dependency or that it is incorporated already in the PS module?

Environment:

  • Windows 11 24H2
  • PowerShell 7.4.6
  • YubiKey: any/all

Thank you in advance,

@aseigler
Copy link
Contributor

aseigler commented Nov 17, 2024

That's this: https://x.com/alexseigler/status/1857127079705497882?t=lDqE2WGLCZavRrhX0qN5uQ&s=19

MSFT broke the API by adding an extra 0 at the end of some credentialId strings. I am trying to find someone who can find someone who can fix it.

@JMarkstrom
Copy link
Author

I just retested using the Yubico "PoC" scripts and I can successfully create, register and authenticate.
But yes, I see there's a 0 at the end of the credential id now:

XDjx9wXDrVWBmE2MbPSkXdeMERfv6gN98uxavJ0ZrSyT8jYUs2BHKjAmh4P_T3Av0

I will pass your Twitter post along.

@aseigler
Copy link
Contributor

I just retested using the Yubico "PoC" scripts and I can successfully create, register and authenticate.
But yes, I see there's a 0 at the end of the credential id now:

XDjx9wXDrVWBmE2MbPSkXdeMERfv6gN98uxavJ0ZrSyT8jYUs2BHKjAmh4P_T3Av0

I will pass your Twitter post along.

It will work if you don't already have any authenticators registered on the account. The issue is with the credentialId being non-base64 in the excludeCredentials.

@JMarkstrom
Copy link
Author

OK, I have passed it along. Note that my test user has multiple FIDO2 authenticators already however.

@aseigler
Copy link
Contributor

aseigler commented Nov 17, 2024

OK, I have passed it along. Note that my test user has multiple FIDO2 authenticators already however.

Yes, it kind of depends. Not all of the credentials are broken. The ones that are 44 chars are fine, the ones that are 64 chars got padded with a extra 0 for some reason so they are now 65 chars which is illegal (len % 4 = 1 is never OK). I think the length might vary based on the YK firmware revision. The older ones seem shorter and the newer ones seem like they are 64 chars (base64url with no padding).

That's the pattern I noticed. Thankfully I have a database with thousands of registered users and key data, which made the pattern pretty easy to spot.

@MichaelGrafnetter
Copy link
Owner

@aseigler Could you please send the bug report to fido-dev@microsoft.com ?

There are additional confirmed issues, including this one:

If you registered more than three passkeys, sign in with a passkey might not work.

@MichaelGrafnetter MichaelGrafnetter changed the title Readme / docs Illegal Base64URL string Nov 18, 2024
@MichaelGrafnetter MichaelGrafnetter added the bug Something isn't working label Nov 18, 2024
@aseigler
Copy link
Contributor

Given that I haven't heard a peep from anyone on this I was thinking about this a little more and I looked at my data samples again. It seems that all credentialId fields that used to be base64url with no padding now all either end in 0, 1, or 2. So, I am now suspicious that the number of padding characters required to turn the string into a legal base64 string has been encoded as that last character.

Like this

ReadOnlySpan<byte> input;
int paddingLength;

bool isFunky = BinaryPrimitives.TryReadInt32LittleEndian(input.Slice(input[^1], 1), out paddingLength);

if (!isFunky)
{
    paddingLength = (input.Length % 4) switch
    {
        0 => 0, // Padding is not needed
        2 => 2, // "==" missing in Base64Url vs. Base64
        3 => 1, // "=" missing in Base64Url vs. Base64
        _ => throw new ArgumentException("Illegal Base64URL string!", nameof(input))
    };
}

@aseigler
Copy link
Contributor

aseigler commented Nov 20, 2024

Either that...or somebody was trying to do something like:

var b64 = "XDjx9wXDrVWBmE2MbPSkXdeMERfv6gN98uxavJ0ZrSyT8jYUs2BHKjAmh4P_T3Av";
int paddingChars = (b64.Length % 4);

And intended to do:

b64 = b64.PadRight(b64.Length + paddingChars, '=');

Which would yield XDjx9wXDrVWBmE2MbPSkXdeMERfv6gN98uxavJ0ZrSyT8jYUs2BHKjAmh4P_T3Av, but instead they did something like:

b64 = b64 + paddingChars;

Which would yield XDjx9wXDrVWBmE2MbPSkXdeMERfv6gN98uxavJ0ZrSyT8jYUs2BHKjAmh4P_T3Av0 ...

foobar would become foobar2 instead of foobar==

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants