Webauthn 실행 중

Aug 17 2020

얼마 전에 Fido2 / WebAuthn 프로젝트를 시작했고 microsofts webauthn 구현을 시작하려고했습니다. 이 프로젝트에는 webauthn.h 파일 의 번역이 있습니다 (현재는 Mozilla 및 Chromium 브라우저 코드에서만이 파일에 대한 참조를 찾았습니다 ...).

이제 ... 자격 증명을 만드는 명령을 내리는 버튼으로 양식을 만들려고했지만이 호출은 $ 0000EA60 @ 액세스 위반으로 인해 비참하게 실패하고 그 원인이 무엇인지 전혀 알 수 없습니다. 내가 뭘 잘못할까요 ???

다음은 버튼 onClick 핸들러의 코드입니다.

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;

Delphi2010을 사용하고 있으므로 JSON 클라이언트 데이터 문자열을 제외한 모든 문자열이 유니 코드 여야합니다.

답변

mrabat Aug 26 2020 at 13:18

Mozilla 브라우저의 C ++ 코드에 대한 오랜 연구 끝에 문제를 발견했다고 생각합니다. COSE_PARAMS 구조의 크기 필드에있었습니다.

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

바이트 단위의 크기 대신 첨부 된 coseParams의 배열 길이를 예상하는 것 같습니다. 그 오해가 AV로 이어졌습니다.