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

Assertion Failure: Fails to assert in libfido2 when using the public key and credential Id generated in response of enrollment using FIDO2 library #342

Open
AdityaSharma21 opened this issue Nov 21, 2022 · 6 comments

Comments

@AdityaSharma21
Copy link

Hi,
I have integrated libfido2 library (https://github.com/Yubico/libfido2) release dlls in my Windows application which is developed in C# for enrolling and authenticating the user via FIDO device.
So, After enrolling user I store the publicKey and CredentailId in database generated from FidoCredential class and then authenticate the user using the same publicKey and CredentailId using the FidoAssertion class Verify method. So, As far everthing is working fine.

As, This application also have integration over Web so on web I have used WebAuthn for the FIDO2 (https://github.com/passwordless-lib/fido2-net-lib) for Enrolling and Authenticating the user. So, the enrollment and authentication at web part also working fine.

But, When I try to authenticate the user on the windows application which uses libfido2 library by using the publicKey and CredentailId generated from WebAuthn (https://github.com/passwordless-lib/fido2-net-lib) it gives me the error of FIDO2 operation failed (InvalidSignature) .
Same is also happening with the WebAuthn(https://github.com/passwordless-lib/fido2-net-lib) Assertion method that the publickey and credentialId generated from libfido2 library is unable to authenticate using the WebAuthn(https://github.com/passwordless-lib/fido2-net-lib) Assertion method and throws the error PeterO.Cbor.CBORException Message: Too many bytes.

So, Please suggest the workaround for this problem as I am stuck here as these two apps are dependent on each other and required to enroll and authenticate the user at both the ends using the publickey and credentialId generated from any of the windows or web platforms.

@aseigler
Copy link
Collaborator

Seems like you have some data formatting issues. Unfortunately without seeing some sample data I doubt we're going to be able to make any meaningful recommendations.

@AdityaSharma21
Copy link
Author

AdityaSharma21 commented Nov 22, 2022

Hi,
Here I am attaching the code of the libfido2 library which is integrated in our windows application for enrolling and Authenticating the user with FIDO device.
LibFido2 Implementation:
Initialize Registration Method
`

            Fido2Settings.Flags = FidoFlags.Debug;
    
            using(var cred = new FidoCredential()) {
        
            using(var dev = new FidoDevice()) {
            dev.Open(device);
            cred.SetType(FidoCose.ES256);
            cred.SetClientData(Cd);

            cred.Rp = new FidoCredentialRp {
                Id = rpId, Name = "XYZ"
            };

            cred.SetUser(new FidoCredentialUser {
                Id = Encoding.UTF8.GetBytes(userId),
                    DisplayName = userName,
                    Name = userName
            });
            cred.SetExtensions(FidoExtensions.None);
            dev.MakeCredential(cred, null);
            dev.Close();
        }
        EnrollmentCredentialsDto enrollmentCredentialsDto = CompleteRegistration(cred, rpId);}`

And after executing the above function it makes call to CompleteRegistration method which provide the public key and credentialId which is later used with fido2-net-lib(https://github.com/passwordless-lib/fido2-net-lib/issues) for the assertion.
CompleteRegistration Method

`

            using(var cred = new FidoCredential()){

            cred.SetType(FidoCose.ES256);

            cred.SetClientData(Cd);

            cred.Rp = new FidoCredentialRp{
            Id = rpId,
            Name = "XYZ"};

           cred.AuthData = fidoCredential.AuthData;
           cred.SetExtensions(FidoExtensions.None);
           cred.SetX509(fidoCredential.X5C);
           cred.Signature = fidoCredential.Signature;
           cred.Format = fidoCredential.Format;
           cred.Verify();
           return new EnrollmentCredentialsDto(Convert.ToBase64String(cred.PublicKey.ToArray()),
           Convert.ToBase64String(cred.Id.ToArray()));}`

After getting the public key and credential Id from above function we store it to our server database which is later used for performing the assertion at our server using Fido2 Library .

Hope this code might help for the details you required and let me know if you have further questions or suggestions.

@aseigler
Copy link
Collaborator

I don't see anything obviously wrong with the code, but like I said on the Stack Overflow question, the data inputs are probably not in the an expected format. That data would be like the client data Cd, the AuthData, the Signature, and the PublicKey.

@AdityaSharma21
Copy link
Author

AdityaSharma21 commented Nov 22, 2022

Here I am sharing the requests of the assertion that we are getting when authenticating the user using fido device on web browser.

Initialize assertion:
`
navigator.credentials.get({

                publicKey: {

rpId: response.data.challengeData.appId,

challenge: coerceToArrayBuffer(response.data.challengeData.challenge),

allowCredentials: [{

type: 'public-key',

id: coerceToArrayBuffer(response.data.challengeData.keyHandles)}],

timeout: 60000}}).then(function (assertion) {
// Send new credential info to server for verification and registration.
if (assertion != undefined && assertion != null)
{
let authData = new Uint8Array(assertion.response.authenticatorData);
let clientDataJSON = new Uint8Array(assertion.response.clientDataJSON);
let rawId = new Uint8Array(assertion.rawId);
let sig = new Uint8Array(assertion.response.signature);

                    const data = {
                        id: assertion.id,
                        rawId: coerceToBase64Url(rawId),
                        type: assertion.type,
                        extensions: assertion.getClientExtensionResults(),
                        response: {
                            authenticatorData: coerceToBase64Url(authData),
                            clientDataJson: coerceToBase64Url(clientDataJSON),
                            signature: coerceToBase64Url(sig)
                        }
                    };
                    resolve(data);
                }
            }).catch(function (err) {
                // No acceptable authenticator or user refused consent. Handle appropriately.
            });`

Initialize Assertion Response:
`
publicKey: {

                rpId: "xyz.com",

                challenge: "Lu8JFMmuAjrP+Do+BoBtGg==",

                allowCredentials:[{
                                              type: 'public-key',

id:"z1/NZd2BgyayBdc1dn4JjK4Eow4eit1qW0ewHN8FaUvH1GHNhMl+1TxT1lA8mqJA86vv/xioQRMCkRLv+7pprZqj6hUHgFROVGC2/xHHB8kZcncGD36PjY0mfq64UlDU"}],

timeout: 60000

}`

And After touching fido device I got this response:
`{
id:"z1_NZd2BgyayBdc1dn4JjK4Eow4eit1qW0ewHN8FaUvH1GHNhMl-1TxT1lA8mqJA86vv_xioQRMCkRLv-7pprZqj6hUHgFROVGC2_xHHB8kZcncGD36PjY0mfq64UlDU",

rawId:"z1_NZd2BgyayBdc1dn4JjK4Eow4eit1qW0ewHN8FaUvH1GHNhMl-1TxT1lA8mqJA86vv_xioQRMCkRLv-7pprZqj6hUHgFROVGC2_xHHB8kZcncGD36PjY0mfq64UlDU",

response:{

authenticatorData:"oEZkc_5aGr1I98knEzlsHcFzP74DMy0SBSiWtUEwB9EBAAAH4Q",

clientDataJson:"eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiTHU4SkZNbXVBanJQLURvLUJvQnRHZyIsIm9yaWdpbiI6Imh0dHBzOi8vZGV2Y3MuY2xvdWQuMmZhLmNvbSIsImNyb3NzT3JpZ2luIjpmYWxzZX0",

signature:"MEUCICscQd96rSwiUJstvXEZTyGlxtGYGpDizNCmKTcIKoaOAiEAnafOL9mHl6DOXRYiaP02FANsuu9qEQgQ_4-cLy3J4ls"},

type:"public-key",

extensions:{}`

@aseigler
Copy link
Collaborator

The stuff here from the web looks reasonably ok, the credential public key is missing and, the challenge is base64 encoded instead of base64url, but that's probably not the issue here. It sounds like the output you're getting locally from libfido2 is not in the same format as the code you've got working for the web.

@dbeinder
Copy link
Contributor

dbeinder commented Dec 2, 2022

@AdityaSharma21 I think libfido2 makes use of webauthn.h to communicate with FIDO keys on Windows 10+. I have built a direct C# interface for it and I'm using it successfully with fido2-net-lib. Maybe by comparing with my code you can trace how you end up with incompatible data: https://github.com/dbeinder/Yoq.WindowsWebAuthn

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants