Mencoba menjalankan Webauthn

Aug 17 2020

Saya telah memulai proyek Fido2 / WebAuthn beberapa waktu yang lalu dan mencoba untuk memulai implementasi webauthn microsoft. Untuk ini dalam proyek ini ada terjemahan file webauthn.h (karena hari ini saya hanya menemukan referensi ke file ini dalam kode browser Mozilla dan Chromium ...).

Sekarang ... Saya hanya mencoba membuat formulir dengan tombol yang mengeluarkan perintah untuk membuat kredensial tetapi panggilan ini gagal total dengan pelanggaran akses @ $ 0000EA60 dan saya tidak tahu apa penyebabnya. Apa yang mungkin saya lakukan salah ???

Di sini kode untuk handler onClick tombol.

uses Webauthn;

// just a test JSON object that I obtained from a browser request
const cClientData : UTF8String = '{' +
 '"hashAlgorithm": "SHA-256",' +
 '"challenge": "fzjg31IEKi6ZxKqsQ9S_XHG9WvdmcXPah5EXd11p1bU",' +
 '"origin": "https:\/\/fidotest.com",' +
 '"clientExtensions": {},' +
 '"type": "webauthn.create"' +
 '}';

procedure TfrmWebAuthnTest.btnCredentialClick(Sender: TObject);
var RpInformation : TWebAuthnRPEntityInformation; // _In_
    UserInformation : TWebAuthUserEntityInformation; // _In_
    PubKeyCredParams : TWebauthnCoseCredentialParameters; // _In_
    WebAuthNClientData : TWebAuthnClientData; // _In_
    WebAuthNMakeCredentialOptions : TWebAuthnAuthenticatorMakeCredentialOptions; // _In_opt_
    pWebAuthNCredentialAttestation : PWEBAUTHN_CREDENTIAL_ATTESTATION; // _Outptr_result_maybenull_
    hr : HRESULT;
    coseParams : Array[0..1] of WEBAUTHN_COSE_CREDENTIAL_PARAMETER;
    i : integer;
    challenge : Array[0..31] of byte;
    cancellationID : TGuid;
    bufClientData : UTF8String;
begin
     // ################################################
     // #### relying party
     FillChar(RpInformation, sizeof(RpInformation), 0);
     RpInformation.dwVersion := WEBAUTHN_RP_ENTITY_INFORMATION_CURRENT_VERSION;
     RpInformation.pwszId := 'fidotest.com';
     RpInformation.pwszName := 'Sweet home localhost';
     RpInformation.pwszIcon := nil;

     // ################################################
     // #### user information
     FillChar(UserInformation, sizeof(UserInformation), 0);
     UserInformation.dwVersion := WEBAUTHN_USER_ENTITY_INFORMATION_CURRENT_VERSION;
     UserInformation.cbId := sizeof( challenge );

     Randomize;

     // create credentials
     for i := 0 to Length(challenge) - 1 do
     begin
          challenge[i] := Byte( Random(High(byte) + 1) );
     end;

     UserInformation.pbId := @challenge[0];
     UserInformation.pwszName := 'Mike';
     UserInformation.pwszIcon := niL;
     UserInformation.pwszDisplayName := 'Mike Rabat';

     // ################################################
     // #### Client data
     bufClientData := Copy( cClientData, 1, Length(cClientData));
     FillChar(WebAuthNClientData, sizeof(WebAuthNClientData), 0);
     WebAuthNClientData.dwVersion := WEBAUTHN_CLIENT_DATA_CURRENT_VERSION;
     WebAuthNClientData.cbClientDataJSON := Length(cClientData);
     WebAuthNClientData.pbClientDataJSON := PAnsiChar(bufClientData);
     WebAuthNClientData.pwszHashAlgId := WEBAUTHN_HASH_ALGORITHM_SHA_256;

     // ################################################
     // #### pub ked credential params
     PubKeyCredParams.cCredentialParameters := sizeof(coseParams);
     PubKeyCredParams.pCredentialParameters := @coseParams[0];

     coseParams[0].dwVersion := WEBAUTHN_COSE_CREDENTIAL_PARAMETER_CURRENT_VERSION;
     coseParams[0].pwszCredentialType := WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY;
     coseParams[0].lAlg := WEBAUTHN_COSE_ALGORITHM_ECDSA_P256_WITH_SHA256;

     coseParams[1].dwVersion := WEBAUTHN_COSE_CREDENTIAL_PARAMETER_CURRENT_VERSION;
     coseParams[1].pwszCredentialType := WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY;
     coseParams[1].lAlg := WEBAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA256;

     // ###########################################
     // #### Fill in params
     FillChar(WebAuthNMakeCredentialOptions, sizeof(WebAuthNMakeCredentialOptions), 0);
     WebAuthNMakeCredentialOptions.dwVersion := WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_CURRENT_VERSION;
     WebAuthNMakeCredentialOptions.dwTimeoutMilliseconds := 60000;
     WebAuthNMakeCredentialOptions.bRequireResidentKey := False;
     WebAuthNMakeCredentialOptions.dwAuthenticatorAttachment := WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM;
     WebAuthNMakeCredentialOptions.dwUserVerificationRequirement := WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED;
     WebAuthNMakeCredentialOptions.dwAttestationConveyancePreference := WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT;

     // ###########################################
     // #### Cancellation
     assert( WebAuthNGetCancellationId(cancellationID) = S_OK, 'Cancellation ID failed');
     WebAuthNMakeCredentialOptions.pCancellationId := @cancellationID;

     // ###########################################
     // #### do the magic
     pWebAuthNCredentialAttestation := nil;
     hr := WebAuthNAuthenticatorMakeCredential( Handle,
                                                @RpInformation,
                                                @UserInformation,
                                                @PubKeyCredParams,
                                                @WebAuthNClientData,
                                                @WebAuthNMakeCredentialOptions,
                                                pWebAuthNCredentialAttestation );

     if hr = S_OK then
     begin
          // WriteCredAttest( pWebAuthNCredentialAttestation );

          WebAuthNFreeCredentialAttestation( pWebAuthNCredentialAttestation );
          memLog.Lines.Add('Finished');
     end
     else
     begin
          memLog.Lines.Add('Make Cred failed with: ' + WebAuthNGetErrorName( hr ));
     end;
end;

Saya menggunakan Delphi2010 jadi semua string harus unicode kecuali string data klien JSON.

Jawaban

mrabat Aug 26 2020 at 13:18

Setelah mempelajari kode C ++ dari Browser Mozilla saya rasa saya menemukan masalahnya. Itu berada di bidang ukuran struktur COSE_PARAMS.

 // #### pub ked credential params
 PubKeyCredParams.cCredentialParameters := Length(coseParams);// sizeof(coseParams);
 PubKeyCredParams.pCredentialParameters := @coseParams[0];

Alih-alih ukuran dalam byte, mereka tampaknya mengharapkan panjang array coseParams terlampir. Kesalahpahaman itu menyebabkan AV.