def test_verify_attestation_android_key( self, mock_verify_certificate: MagicMock, ) -> None: # Mocked because response is from FIDO Conformance with unknown root certs mock_verify_certificate.return_value = True credential = RegistrationCredential.parse_raw("""{ "id": "V51GE29tGbhby7sbg1cZ_qL8V8njqEsXpAnwQBobvgw", "rawId": "V51GE29tGbhby7sbg1cZ_qL8V8njqEsXpAnwQBobvgw", "response": { "attestationObject": "o2NmbXRrYW5kcm9pZC1rZXlnYXR0U3RtdKNjYWxnJmNzaWdYRzBFAiAbZhfcF0KSXj5rdEevvnBcC8ZfRQlNl9XYWRTiIGKSHwIhAIerc7jWjOF_lJ71n_GAcaHwDUtPxkjAAdYugnZ4QxkmY3g1Y4JZAxowggMWMIICvaADAgECAgEBMAoGCCqGSM49BAMCMIHkMUUwQwYDVQQDDDxGQUtFIEFuZHJvaWQgS2V5c3RvcmUgU29mdHdhcmUgQXR0ZXN0YXRpb24gSW50ZXJtZWRpYXRlIEZBS0UxMTAvBgkqhkiG9w0BCQEWImNvbmZvcm1hbmNlLXRvb2xzQGZpZG9hbGxpYW5jZS5vcmcxFjAUBgNVBAoMDUZJRE8gQWxsaWFuY2UxIjAgBgNVBAsMGUF1dGhlbnRpY2F0b3IgQXR0ZXN0YXRpb24xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNWTESMBAGA1UEBwwJV2FrZWZpZWxkMCAXDTcwMDIwMTAwMDAwMFoYDzIwOTkwMTMxMjM1OTU5WjApMScwJQYDVQQDDB5GQUtFIEFuZHJvaWQgS2V5c3RvcmUgS2V5IEZBS0UwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARuowgSu5AoRj8Vi_ZNSFBbGUZJXFG9MkDT6jADlr7tOK9NEgjVX53-ergXpyPaFZrAR9py-xnzfjILn_Kzb8Iqo4IBFjCCARIwCwYDVR0PBAQDAgeAMIHhBgorBgEEAdZ5AgERBIHSMIHPAgECCgEAAgEBCgEABCCfVEl83pSDSerk9I3pcICNTdzc5N3u4jt21cXdzBuJjgQAMGm_hT0IAgYBXtPjz6C_hUVZBFcwVTEvMC0EKGNvbS5hbmRyb2lkLmtleXN0b3JlLmFuZHJvaWRrZXlzdG9yZWRlbW8CAQExIgQgdM_LUHSI9SkQhZHHpQWRnzJ3MvvB2ANSauqYAAbS2JgwMqEFMQMCAQKiAwIBA6MEAgIBAKUFMQMCAQSqAwIBAb-DeAMCAQK_hT4DAgEAv4U_AgUAMB8GA1UdIwQYMBaAFKPSqizvDYzyJALVHLRgvL9qWyQUMAoGCCqGSM49BAMCA0cAMEQCIC7WHb2PyULnjp1M1TVI3Wti_eDhe6sFweuQAdecXtHhAiAS_eZkFsx_VNsrTu3XfZ2D7wIt-vT6nTljfHZ4zqU5xlkDGDCCAxQwggK6oAMCAQICAQIwCgYIKoZIzj0EAwIwgdwxPTA7BgNVBAMMNEZBS0UgQW5kcm9pZCBLZXlzdG9yZSBTb2Z0d2FyZSBBdHRlc3RhdGlvbiBSb290IEZBS0UxMTAvBgkqhkiG9w0BCQEWImNvbmZvcm1hbmNlLXRvb2xzQGZpZG9hbGxpYW5jZS5vcmcxFjAUBgNVBAoMDUZJRE8gQWxsaWFuY2UxIjAgBgNVBAsMGUF1dGhlbnRpY2F0b3IgQXR0ZXN0YXRpb24xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNWTESMBAGA1UEBwwJV2FrZWZpZWxkMB4XDTE5MDQyNTA1NDkzMloXDTQ2MDkxMDA1NDkzMlowgeQxRTBDBgNVBAMMPEZBS0UgQW5kcm9pZCBLZXlzdG9yZSBTb2Z0d2FyZSBBdHRlc3RhdGlvbiBJbnRlcm1lZGlhdGUgRkFLRTExMC8GCSqGSIb3DQEJARYiY29uZm9ybWFuY2UtdG9vbHNAZmlkb2FsbGlhbmNlLm9yZzEWMBQGA1UECgwNRklETyBBbGxpYW5jZTEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1ZMRIwEAYDVQQHDAlXYWtlZmllbGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASrUGErYk0Xu8O1GwRJOwVJC4wfi52883my3tygfFKh17YN0yF13Ct-3bwm2wjVX4b2cbaU3DBNpKKKjE4DpvXHo2MwYTAPBgNVHRMBAf8EBTADAQH_MA4GA1UdDwEB_wQEAwIChDAdBgNVHQ4EFgQUo9KqLO8NjPIkAtUctGC8v2pbJBQwHwYDVR0jBBgwFoAUUpobMuBWqs1RD-9fgDcGi_KRIx0wCgYIKoZIzj0EAwIDSAAwRQIhALFvLkAvtHrObTmN8P0-yLIT496P_weSEEbB6vCJWSh9AiBu-UOorCeLcF4WixOG9E5Li2nXe4uM2q6mbKGkll8u-WhhdXRoRGF0YVikPdxHEOnAiLIp26idVjIguzn3Ipr_RlsKZWsa-5qK-KBBAAAAYFUOS1SqR0CfmpUat2wTATEAIFedRhNvbRm4W8u7G4NXGf6i_FfJ46hLF6QJ8EAaG74MpQECAyYgASFYIG6jCBK7kChGPxWL9k1IUFsZRklcUb0yQNPqMAOWvu04Ilggr00SCNVfnf56uBenI9oVmsBH2nL7GfN-Mguf8rNvwio", "clientDataJSON": "eyJvcmlnaW4iOiJodHRwczovL2Rldi5kb250bmVlZGEucHciLCJjaGFsbGVuZ2UiOiI0YWI3ZGZkMS1hNjk1LTQ3NzctOTg1Zi1hZDI5OTM4MjhlOTkiLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0" }, "type": "public-key", "clientExtensionResults": {} } """) challenge = base64url_to_bytes("4ab7dfd1-a695-4777-985f-ad2993828e99") rp_id = "dev.dontneeda.pw" expected_origin = "https://dev.dontneeda.pw" verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.fmt == AttestationFormat.ANDROID_KEY assert verification.credential_id == base64url_to_bytes( "V51GE29tGbhby7sbg1cZ_qL8V8njqEsXpAnwQBobvgw")
def test_verify_attestation_from_fido_conformance(self) -> None: credential = RegistrationCredential.parse_raw("""{ "id": "2i53XtAuBVv2ztu9hdTkG_I4_zc-MhmYOjM2HWDCIlk", "rawId": "2i53XtAuBVv2ztu9hdTkG_I4_zc-MhmYOjM2HWDCIlk", "response": { "clientDataJSON": "eyJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjaGFsbGVuZ2UiOiJjMFd4b3JXd0VUb094bGJiNU1zRFpQV0tkTmlVaHlPSkw4cy1NSWNqSS1RNVNGSk9ub1dlX3EyWmhnWUtIeWt2NFBHdzNMLV9wbGdOQm5LZ3d3M2RBdyIsInR5cGUiOiJ3ZWJhdXRobi5jcmVhdGUifQ", "attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIgYCbOYmJrEQy_oJqbBpgT_V8DhOUA-Kt3578zKalWyPkCIQDkyAm3YO98SF3AFi5Px1LChUDMLfPzL_p7um8sqxel0GN4NWOBWQQvMIIEKzCCAhOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBoTEYMBYGA1UEAwwPRklETzIgVEVTVCBST09UMTEwLwYJKoZIhvcNAQkBFiJjb25mb3JtYW5jZS10b29sc0BmaWRvYWxsaWFuY2Uub3JnMRYwFAYDVQQKDA1GSURPIEFsbGlhbmNlMQwwCgYDVQQLDANDV0cxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNWTESMBAGA1UEBwwJV2FrZWZpZWxkMB4XDTE4MDMxNjE0MzUyN1oXDTI4MDMxMzE0MzUyN1owgawxIzAhBgNVBAMMGkZJRE8yIEJBVENIIEtFWSBwcmltZTI1NnYxMTEwLwYJKoZIhvcNAQkBFiJjb25mb3JtYW5jZS10b29sc0BmaWRvYWxsaWFuY2Uub3JnMRYwFAYDVQQKDA1GSURPIEFsbGlhbmNlMQwwCgYDVQQLDANDV0cxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNWTESMBAGA1UEBwwJV2FrZWZpZWxkMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETzpeXqtsH7yul_bfZEmWdix773IAQCp2xvIw9lVvF6qZm1l_xL9Qiq-OnvDNAT9aub0nkUvwgEN4y8yxG4m1RqMsMCowCQYDVR0TBAIwADAdBgNVHQ4EFgQUVk33wPjGVbahH2xNGfO_QeL9AXkwDQYJKoZIhvcNAQEFBQADggIBAI-_jI31FB-8J2XxzBXMuI4Yg-vAtq07ABHJqnQpUmt8lpOzmvJ0COKcwtq_7bpsgSVBJ26zhnyWcm1q8V0ZbxUvN2kH8N7nteIGn-CJOJkHDII-IbiH4-TUQCJjuCB52duUWL0fGVw2R13J6V-K7U5r0OWBzmtmwwiRVTggVbjDpbx2oqGAwzupG3RmBFDX1M92s3tgywnLr-e6NZal5yZdS8VblJGjswDZbdY-Qobo2DCN6vxvn5TVkukAHiArjpBBpAmuQfKa52vqSCYRpTCm57fQUZ1c1n29OsvDw1x9ckyH8j_9Xgk0AG-MlQ9Rdg3hCb7LkSPvC_zYDeS2Cj_yFw6OWahnnIRwO6t4UtLuRAkLrjP1T7nk0zu1whwj7YEwtva45niWWh6rdyg_SZlfsph3o_MZN5DwKaSrUaEO6b-numELH5GWjjiPgfgPKkIof-D40xaKUFBpNJzorQkAZCJWuHvXRpBZWFVh_UhNlGhX0mhz2yFlBrujYa9BgvIkdJ8Keok6qfAn-r5EEFXcSI8vGY7OEF01QKXVpu8-FW0uSxtQ991AcFD6KjvR51l7e61visUgduhZRIq9bYzeCIxnK5Jhm3o_NJE2bOp2NmVwVe4kjuJX87wo3Ba41bXgwIpdiLWyWJhSHPmJI_1ibRTZ5XO92xbPPSnnkXrFaGF1dGhEYXRhWKRJlg3liA6MaHQ0Fw9kdmBbj-SuuaKGMseZXPO6gx2XY0EAAAACAAAAAAAAAAAAAAAAAAAAAAAg2i53XtAuBVv2ztu9hdTkG_I4_zc-MhmYOjM2HWDCIlmlAQIDJiABIVggFgD81bv3uFCOrjw3DfHTIuscQkA7gikvjGdE6ltNPjoiWCA_7nP-fPzwp30E4kLjh4nyMyHQ2tfPJR8lA0h7SQ1dfA" }, "type": "public-key", "transports": null } """) challenge = base64url_to_bytes( "c0WxorWwEToOxlbb5MsDZPWKdNiUhyOJL8s-MIcjI-Q5SFJOnoWe_q2ZhgYKHykv4PGw3L-_plgNBnKgww3dAw" ) rp_id = "localhost" expected_origin = "http://localhost:5000" verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.fmt == AttestationFormat.FIDO_U2F assert verification.credential_id == base64url_to_bytes( "2i53XtAuBVv2ztu9hdTkG_I4_zc-MhmYOjM2HWDCIlk")
def test_verify_attestation_lenovo_carbon_x1(self) -> None: """ TPM Mfgr: STM (ST Microelectronics) Mfgr Version: 73.8.17568.5511 TPM Version: 2.0 """ credential = RegistrationCredential.parse_raw( """{ "id": "kU6oEC95fTXAtpI6b2w69fQrKGntFFt1l_2ySjmndYM", "rawId": "kU6oEC95fTXAtpI6b2w69fQrKGntFFt1l_2ySjmndYM", "response": { "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiWlhsS2FHSkhZMmxQYVVwSlZYcEpNVTVwU1hOSmJsSTFZME5KTmtscmNGaFdRMG81TG1WNVNuQlpXRkZwVDJwRk1rMXFVVEJPZWxVd1RYcGpjMGx0VmpSalEwazJUVlJaZVU1RVZUVk9WRkY2VG5sM2FXTXpWbWxKYW05cFkyMDVjMkpIYkhWSmJqQXVjbkJaTTJwVVpVUjBjekE1VFhOSWJUSlZiWGx0WnpsWlpIWnZlbmMyY2xGUGVsRjZNelZpYkhsbU5BIiwib3JpZ2luIjoiaHR0cHM6Ly93ZWJhdXRobnRlc3QuYXp1cmV3ZWJzaXRlcy5uZXQiLCJjcm9zc09yaWdpbiI6ZmFsc2UsIm90aGVyX2tleXNfY2FuX2JlX2FkZGVkX2hlcmUiOiJkbyBub3QgY29tcGFyZSBjbGllbnREYXRhSlNPTiBhZ2FpbnN0IGEgdGVtcGxhdGUuIFNlZSBodHRwczovL2dvby5nbC95YWJQZXgifQ==", "attestationObject": "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" }, "type": "public-key" } """ ) challenge = base64url_to_bytes( "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMk1qUTBOelUwTXpjc0ltVjRjQ0k2TVRZeU5EVTVOVFF6Tnl3aWMzVmlJam9pY205c2JHbHVJbjAucnBZM2pUZUR0czA5TXNIbTJVbXltZzlZZHZvenc2clFPelF6MzVibHlmNA" ) rp_id = "webauthntest.azurewebsites.net" expected_origin = "https://webauthntest.azurewebsites.net" verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.fmt == AttestationFormat.TPM assert verification.credential_id == base64url_to_bytes( "kU6oEC95fTXAtpI6b2w69fQrKGntFFt1l_2ySjmndYM" )
def form_valid(self, form): webauthn_challenge = self.request.session["webauthn_challenge"] try: credential = RegistrationCredential.parse_raw(form.cleaned_data["token_response"]) verification = verify_registration_response( credential=credential, expected_challenge=trimmed_urlsafe_b64decode(webauthn_challenge["challenge"]), expected_origin=zentral_settings["api"]["tls_hostname"], expected_rp_id=zentral_settings["api"]["fqdn"], require_user_verification=False ) except Exception: logger.exception("Could not verify registration") messages.error(self.request, "Authentication error") return self.form_invalid(form) transports = json.loads(form.cleaned_data["token_response"]).get("transports", []) user_device = UserWebAuthn.objects.create( user=self.request.user, name=form.cleaned_data["name"], key_handle=urlsafe_b64encode(verification.credential_id).decode("ascii").rstrip("="), public_key=verification.credential_public_key, rp_id=zentral_settings["api"]["fqdn"], transports=transports, sign_count=verification.sign_count ) post_verification_device_event(self.request, self.request.user, "create", user_device) messages.info(self.request, "Security key registered") return super().form_valid(form)
def test_verify_attestation_surface_pro_4(self) -> None: """ TPM Mfgr: INTC (Intel) Mfgr Version: 500.5.0.0 TPM Version: 2.0 """ credential = RegistrationCredential.parse_raw( """{ "id": "2O_TSbHXS3KJwx5uwajcqbKwWCBeHjOBCXXb7vrPfUU", "rawId": "2O_TSbHXS3KJwx5uwajcqbKwWCBeHjOBCXXb7vrPfUU", "response": { "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiWlhsS2FHSkhZMmxQYVVwSlZYcEpNVTVwU1hOSmJsSTFZME5KTmtscmNGaFdRMG81TG1WNVNuQlpXRkZwVDJwRk1rMXFUWGxPVkd0M1RXcE5jMGx0VmpSalEwazJUVlJaZVUxNlRUTlBWRUY1VFhsM2FXTXpWbWxKYW05cFpGaE9iR050TldoaVYxWnZXbGhLYkVsdU1DNTNhbVZJVWpSNFNuRkdVUzFTVTBabFgxZFVWVjlPUm5odk4zZHRRakJ5Y3pWSE1uRnBSRjluVkRObiIsIm9yaWdpbiI6Imh0dHBzOi8vd2ViYXV0aG50ZXN0LmF6dXJld2Vic2l0ZXMubmV0IiwiY3Jvc3NPcmlnaW4iOmZhbHNlfQ==", "attestationObject": "o2NmbXRjdHBtZ2F0dFN0bXSmY2FsZzn//mNzaWdZAQAW8nyy4aArkiLbIKwObN2DgpGdJfU7klHgF1hAk2fJVzxZe5OOzhN1ZWuDZy+I0Q8vJzQfyO/xz6zZM0lcTIXL8bOO82Wvd6QwzB9HbzQZ8mjtRis4139S+OgF5UfReijMF1TMQCSzqo4K+1w2Bo0ppS1Tygr5P4iFV6qnQ9V3xr/1Afv4i2fpPeNtRT9REW599PNwMA2pCnBGC8tJRlbWXJURe5TGBtMc1k7Qg65H8uDcYJZt6TsiuFpkkMlXnbgma9ZffLqgEKjwEPF7W/SsILLDcFs8HcNI/mE2wJXSxI1bSipf7Hao7xV1w2a/etKd76HgUTVUqQy25Zk/BK4LY3ZlcmMyLjBjeDVjglkFvTCCBbkwggOhoAMCAQICEBVC9wOQ6UasrBmEcAVMotMwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UEAxM3V1VTLUlOVEMtS0VZSUQtRTcwODNGMjIxNTJBNzQ5MkVDNTlCMEM0MjQzNDM3NjQ4QjE1REJCNzAeFw0yMTA0MDEyMzExMjdaFw0yNTA1MjIyMDMyMjFaMAAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0xn6eF6c3LHsT+QPrZZc9zYxgd/0zJAQZfKeDP4V59kQZZWBRnjVzamUCd11tdbVWtBbydTotghZ+vofinvIrShv4Va/jUl+Fd2r/Iu868PejBmgtlzLG7BXht1ooDxlSpKB70k83PyAeOLoIzecWpjz4lgJvUV6SHIgj/HVZg0O4E5lXsF1ko6+YGMWo2t4l49ffuYBmM2PXg6Yk7YEpsS9vO+LVQMhRdxE0e9U0KdtiDsFjyRZyeiQOXWnzB2oMmueWpAzoFgpIZVlmeswsWF4mef70Ze/SEtddHyqnAZ56v97NNx3Eirint/KEyoN1gjvEjiapBv1x3prkYrjBAgMBAAGjggHrMIIB5zAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADBtBgNVHSABAf8EYzBhMF8GCSsGAQQBgjcVHzBSMFAGCCsGAQUFBwICMEQeQgBUAEMAUABBACAAIABUAHIAdQBzAHQAZQBkACAAIABQAGwAYQB0AGYAbwByAG0AIAAgAEkAZABlAG4AdABpAHQAeTAQBgNVHSUECTAHBgVngQUIAzBQBgNVHREBAf8ERjBEpEIwQDEWMBQGBWeBBQIBDAtpZDo0OTRFNTQ0MzEOMAwGBWeBBQICDANJQ0wxFjAUBgVngQUCAwwLaWQ6MDAwMjAwMDAwHwYDVR0jBBgwFoAUJKtDKWNW/+lQbKrQmv+0KVRndZ0wHQYDVR0OBBYEFBoLz1WCz4WjgFvf4gdjDwposC2+MIGzBggrBgEFBQcBAQSBpjCBozCBoAYIKwYBBQUHMAKGgZNodHRwOi8vYXpjc3Byb2R3dXNhaWtwdWJsaXNoLmJsb2IuY29yZS53aW5kb3dzLm5ldC93dXMtaW50Yy1rZXlpZC1lNzA4M2YyMjE1MmE3NDkyZWM1OWIwYzQyNDM0Mzc2NDhiMTVkYmI3L2NjZjJmMTYzLTU1YzAtNGMyZC04Y2FkLWViZDMzM2EzMGEyZi5jZXIwDQYJKoZIhvcNAQELBQADggIBAI2YgavqGYCUe8crkcaOy20oWQN/3Ap/i0i78puCTz+c72X2R+nZMT1QUC+XwL6diX9SEKKWWJc17OdHcF5lCtQVzjbVUp7UXsX89NUIOtiyZtiGo7AM+VgrTDxylyVSkTgovktrCWl6ycwpiD7vEwtl0ShlSbvLgKZDXWJtRBFIv+NTNje8WHhclnovKWCZnISA2ExKshGIALeLundGcgITINr8uTcC8ZTFSwhQrwHf7pjhrYllfO+7Fh3Cb1kMIfYC+GfjtFjKUm2jLUsEXAYZA2KEk2QdNgxDmy/b0SN9MiVtm9Pn7cPpxkBJuIPunA+3WlsKor1o87U2//oOHssq2HqUm9Kji9wR5pG8V1rmezhtHN606FMAkwlPly3ihu40GXPEPV7na2dnPPv8kHyRPtSOhotpZtXHzWW6vw6TrqNxFL93gExdzzF7K1x96Wb3AHsuhM7+HiPweBw/+Xl+c3A6rz1VAH9/K3IjLLFpFoyLsiTiYLAc+q5QCLhRImSe5TIao3O7GPnBUHigzsuwpQydTsZfe5RFzxU1bEdroOOaDPCEtiXZnBcIPE/Ec9/Xg9DFAMxJ43z9KrHEmsoRdVfZiCy+3aVnDkSz63GUs+tpHcEi+CSTixgxejtGZMd6bA4a55axuamE5Yd+kb5glT4dJRxRuAioF0MVpRV6WQbwMIIG7DCCBNSgAwIBAgITMwAAAtJlMfxfe3kISgAAAAAC0jANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE2MDQGA1UEAxMtTWljcm9zb2Z0IFRQTSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDE0MB4XDTE5MDUyMjIwMzIyMVoXDTI1MDUyMjIwMzIyMVowQjFAMD4GA1UEAxM3V1VTLUlOVEMtS0VZSUQtRTcwODNGMjIxNTJBNzQ5MkVDNTlCMEM0MjQzNDM3NjQ4QjE1REJCNzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANsHFapiqDMZD3nY6Jevf1zAWMI+hV4w0CmSZEb+S73hBTplWkg6uv75G7P/x4AFle8/uOlLPOqLlKKKnNNVPAnbS+WfspyUFMSsCF/ZOEaP4YBtdQjuoQxrN7X5qmY6C/ZOgt8VmVgkza5PymaxZDPPDKEP9LatDVkUzXutiY1YsUGc6xMq/oa4I3JL7I6nXGWxVN7slSziYHAhBTpef5PK235k6AIE+oEbpdmlrEj5UT41SfFIyC8el+Vy2obmuulsziyzyUCbZqBQ9yHa3ACCUMqIaDvVin8cEMXA6jcxVI+oYug6Nx77735GuC2we2aQwlaRvOFvxZLphIb/3h17EqakM0NMxFgIVxvvmnmrNIBylN3Uhh6FbvCviWssrl0NR0NNFnV8KCsdIsy8w0ALl6wAh0UCitEKuG+fThczYQpMv4KmKPBF2Kq1dloXDK3f9bT5I2pGXpUQHmkAs8TSRNlTso6vfdZ5g5jTJvWNJGUA2H5IgAWs59+ZHZVMlzbGUBIMyo1Po+KClGhEXmBA5Y77qWob/ebAGLibMH2lq9I9eREa/WTpQxcT7uInO45XaU0cxcthNNKsPOyg5aX3HoClpzPdvizE9iC3y5ydjrvndcg4D/jLrUAZJLwmS+VP+qrDR4/AG/yiS38lPvAeeUQD80WX3oonZBYHHd53AgMBAAGjggGOMIIBijAOBgNVHQ8BAf8EBAMCAoQwGwYDVR0lBBQwEgYJKwYBBAGCNxUkBgVngQUIAzAWBgNVHSAEDzANMAsGCSsGAQQBgjcVHzASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQkq0MpY1b/6VBsqtCa/7QpVGd1nTAfBgNVHSMEGDAWgBR6jArOL0hiF+KU0a5VwVLscXSkVjBwBgNVHR8EaTBnMGWgY6Bhhl9odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUUE0lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDE0LmNybDB9BggrBgEFBQcBAQRxMG8wbQYIKwYBBQUHMAKGYWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVFBNJTIwUm9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAxNC5jcnQwDQYJKoZIhvcNAQELBQADggIBAJ24mLPy6pE9mVLnL+VQqlPNxohciCr7OeLFudlqpVQooX2Tv5TISYM+jXIckTgqUnLkTP330fdt38ov+K/ZCnw6OymkaqKgDXfojhcNqAmCN2fX4j8LhOPhidqxOy2WlNkdXs0SF8c/iR70jsJoXxluotuKbciZ2b8gZquyST0R5hn8k2ea59/XO0rzIeZ9fozCDmDuBZcejtFync48TkMUDlwjDLXkBtGBkmE9ZVLL3jr1Mu8Nt0gal7eHs3IxPO6n+kC33MF7PxgkWmzqOrs+nStyj2WLNqTkiCCFhEBaePZqptfMejk8k5HJGtqVg9OE0r2HFRQOxkES5BDXwG74L6nw9plEksjjz2tXEKDju9JrL1aNMLgy035exLjWgRa+xiJ9hTgnsAoM9zkJM21dHMnHwGL37YD9lEHyLX+IgO/r/WtKoiJScaDqmdow9EmGTqvUqBcE+z3wiT0WIcglea1JidVIWAnoeCQApybX17ihBUYgUycvIc6QpmHqrlkEutPc3pQx7ThbIkaq2Sx4VkDWGWw1H/TPnQ4hSEM6DlWJBdvdWWoH4yXpF3HZvCBtOyXabnfpIPPX4G+trrpch4xaLxwpDST1VkJ9xRSOqoQ2uoIrZWG1fcjEtSh3P+zxDJzFjl0GGJ2zHV9G/N7bvngbho/SV3cETzZoL8YiZ3B1YkFyZWFZATYAAQALAAYEcgAgnf/L82w4OuaZ+5ho3G3LidcVOIS+KAOSLBJBWL+tIq4AEAAQCAAAAAAAAQC00gwM+S0CrYvZMzdrGmNFkIUzADgIUzylOBVgLXvAYvVY3E+UhvYYFP/eAW4Vz4js6H6Bw9O/Z4KJ5rt7/1f/I0khA7GK9paagKVYavgrmgFyJrxcrh1VLIbDcSdVa3PlSy8UU3cB+kWdgfxKV2KAYxvE88MfZJ8i/c5bOHrg6usYgdOPY6v6hI2EMFyPUxs+I1KxkdCm9iZS7sU2GFQlIqWiM2mWsKZ7gshAFLBUPE6y0s5aMl5nBtI3WFzYQFkBGskBj69kmJYGbnRFx4mIpabrVlXfqePgnmAspsIDxcV3CHZafAhL2USit0CyXkayoigOruSmqdPgSTFSO0HXaGNlcnRJbmZvWKH/VENHgBcAIgALVyJme0o1XzkiFQlMAdVlvHLGyQO8I7Vt7rV5SStq5s4AFGALRChBmfPTEklbBB/05/spyAKPAAAAABowKVoWsH2xUidz+AGXZzFL+mZgVAAiAAvnHCKQB95B4Xfgs0bhBwKMFmLhDZ64ruepNaz2Gu14iQAiAAt/6ITaQ6fFP85wdCypCkGZk7wfFctzf+AalnXK5I+GgWhhdXRoRGF0YVkBZ+RTKdA6IGjRyvf3uwrpVOaw5iWXRfMvSCn3UPBQEfnCRQAAAAAImHBYytxLgbbhMN5Q3L6WACDY79NJsddLconDHm7BqNypsrBYIF4eM4EJddvu+s99RaQBAwM5AQAgWQEAtNIMDPktAq2L2TM3axpjRZCFMwA4CFM8pTgVYC17wGL1WNxPlIb2GBT/3gFuFc+I7Oh+gcPTv2eCiea7e/9X/yNJIQOxivaWmoClWGr4K5oBcia8XK4dVSyGw3EnVWtz5UsvFFN3AfpFnYH8SldigGMbxPPDH2SfIv3OWzh64OrrGIHTj2Or+oSNhDBcj1MbPiNSsZHQpvYmUu7FNhhUJSKlojNplrCme4LIQBSwVDxOstLOWjJeZwbSN1hc2EBZARrJAY+vZJiWBm50RceJiKWm61ZV36nj4J5gLKbCA8XFdwh2WnwIS9lEordAsl5GsqIoDq7kpqnT4EkxUjtB1yFDAQAB" }, "type": "public-key" } """ ) challenge = base64url_to_bytes( "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMk1qTXlOVGt3TWpNc0ltVjRjQ0k2TVRZeU16TTNPVEF5TXl3aWMzVmlJam9pZFhObGNtNWhiV1ZvWlhKbEluMC53amVIUjR4SnFGUS1SU0ZlX1dUVV9ORnhvN3dtQjByczVHMnFpRF9nVDNn" ) rp_id = "webauthntest.azurewebsites.net" expected_origin = "https://webauthntest.azurewebsites.net" verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.fmt == AttestationFormat.TPM assert verification.credential_id == base64url_to_bytes( "2O_TSbHXS3KJwx5uwajcqbKwWCBeHjOBCXXb7vrPfUU" )
def test_verify_attestation_dell_xps_13(self) -> None: """ TPM Mfgr: NTC (Nuvoton Technology) Mfgr Version: 1.3.2.8 TPM Version: 2.0 """ credential = RegistrationCredential.parse_raw( """{ "id": "56iW7RC7YLiknnNU70kO5Bb-jip9-WTUbohh_Aqq1q4", "rawId": "56iW7RC7YLiknnNU70kO5Bb-jip9-WTUbohh_Aqq1q4", "response": { "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiWlhsS2FHSkhZMmxQYVVwSlZYcEpNVTVwU1hOSmJsSTFZME5KTmtscmNGaFdRMG81TG1WNVNuQlpXRkZwVDJwRk1rMXFVVEJPYWswMFRWUnJjMGx0VmpSalEwazJUVlJaZVU1RVZUUk5lbWQ0VDFOM2FXTXpWbWxKYW05cFdXMDVhVWx1TUM1UmFIVnJaMWsxZEV3eVpITTRkWGRCY25STFVHRnJTemRFYW5wa1ptMDRPWGx2VTNnMFpsOURWMDlGIiwib3JpZ2luIjoiaHR0cHM6Ly93ZWJhdXRobnRlc3QuYXp1cmV3ZWJzaXRlcy5uZXQiLCJjcm9zc09yaWdpbiI6ZmFsc2V9", "attestationObject": "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" }, "type": "public-key" } """ ) challenge = base64url_to_bytes( "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMk1qUTBOak00TVRrc0ltVjRjQ0k2TVRZeU5EVTRNemd4T1N3aWMzVmlJam9pWW05aUluMC5RaHVrZ1k1dEwyZHM4dXdBcnRLUGFrSzdEanpkZm04OXlvU3g0Zl9DV09F" ) rp_id = "webauthntest.azurewebsites.net" expected_origin = "https://webauthntest.azurewebsites.net" verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.fmt == AttestationFormat.TPM assert verification.credential_id == base64url_to_bytes( "56iW7RC7YLiknnNU70kO5Bb-jip9-WTUbohh_Aqq1q4" )
def test_verify_attestation_with_okp_public_key(self) -> None: credential = RegistrationCredential.parse_raw("""{ "id": "WlHiMqH6UhUs-d43z-aGlE3nsXuEOQpa9P9pwpqb4tmvtBMBfGvAV2wUrqBCDENjkkxd6kIRzZQKcluyOFlyW_vXVZSAEgod1xj-1QmFpuwyBVnlkQGefRbmUjbEt5iE4q3tdjy65EWIekO0SNjCQx3LxIJMzi25fgUkI9Y-gg0", "rawId": "WlHiMqH6UhUs-d43z-aGlE3nsXuEOQpa9P9pwpqb4tmvtBMBfGvAV2wUrqBCDENjkkxd6kIRzZQKcluyOFlyW_vXVZSAEgod1xj-1QmFpuwyBVnlkQGefRbmUjbEt5iE4q3tdjy65EWIekO0SNjCQx3LxIJMzi25fgUkI9Y-gg0", "response": { "attestationObject": "o2NmbXRmcGFja2VkZ2F0dFN0bXSjY2FsZyZjc2lnWEcwRQIgB3c0BvOsyJut14wj4XVWxXliicWZMZLDNF621Zz7h_8CIQCIOqRyWOazVhqlBrD-HL-83KWAvGZRgvW-4A9SE8BLFWN4NWOBWQLBMIICvTCCAaWgAwIBAgIEK_F8eDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbjELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEnMCUGA1UEAwweWXViaWNvIFUyRiBFRSBTZXJpYWwgNzM3MjQ2MzI4MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdMLHhCPIcS6bSPJZWGb8cECuTN8H13fVha8Ek5nt-pI8vrSflxb59Vp4bDQlH8jzXj3oW1ZwUDjHC6EnGWB5i6NsMGowIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjcwEwYLKwYBBAGC5RwCAQEEBAMCAiQwIQYLKwYBBAGC5RwBAQQEEgQQxe9V_62aS5-1gK3rr-Am0DAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQCLbpN2nXhNbunZANJxAn_Cd-S4JuZsObnUiLnLLS0FPWa01TY8F7oJ8bE-aFa4kTe6NQQfi8-yiZrQ8N-JL4f7gNdQPSrH-r3iFd4SvroDe1jaJO4J9LeiFjmRdcVa-5cqNF4G1fPCofvw9W4lKnObuPakr0x_icdVq1MXhYdUtQk6Zr5mBnc4FhN9qi7DXqLHD5G7ZFUmGwfIcD2-0m1f1mwQS8yRD5-_aDCf3vutwddoi3crtivzyromwbKklR4qHunJ75LGZLZA8pJ_mXnUQ6TTsgRqPvPXgQPbSyGMf2z_DIPbQqCD_Bmc4dj9o6LozheBdDtcZCAjSPTAd_uiaGF1dGhEYXRhWOFJlg3liA6MaHQ0Fw9kdmBbj-SuuaKGMseZXPO6gx2XY0EAAAACxe9V_62aS5-1gK3rr-Am0ACAWlHiMqH6UhUs-d43z-aGlE3nsXuEOQpa9P9pwpqb4tmvtBMBfGvAV2wUrqBCDENjkkxd6kIRzZQKcluyOFlyW_vXVZSAEgod1xj-1QmFpuwyBVnlkQGefRbmUjbEt5iE4q3tdjy65EWIekO0SNjCQx3LxIJMzi25fgUkI9Y-gg2kAQEDJyAGIVggnB_oUZDQU0esRlNPmjEO96aMDTgs34D8Dv31tAwhUZo", "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiN0pVQmpXWkZkRm96dWx4YjcxRHZIa2gzUDZXS1VHNEVsVW83d0VrS2ljMkpFVEpNQUlLQ2Y3ckJFOVlrc0k1b05qRHpRNkhxaDZFNzNPeTZTUGNNbnciLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9" }, "type": "public-key", "clientExtensionResults": {}, "transports": [ "usb" ] } """) challenge = base64url_to_bytes( "7JUBjWZFdFozulxb71DvHkh3P6WKUG4ElUo7wEkKic2JETJMAIKCf7rBE9YksI5oNjDzQ6Hqh6E73Oy6SPcMnw" ) rp_id = "localhost" expected_origin = "http://localhost:5000" verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.fmt == AttestationFormat.PACKED assert verification.credential_id == base64url_to_bytes( "WlHiMqH6UhUs-d43z-aGlE3nsXuEOQpa9P9pwpqb4tmvtBMBfGvAV2wUrqBCDENjkkxd6kIRzZQKcluyOFlyW_vXVZSAEgod1xj-1QmFpuwyBVnlkQGefRbmUjbEt5iE4q3tdjy65EWIekO0SNjCQx3LxIJMzi25fgUkI9Y-gg0" )
def test_verify_attestation_with_unsupported_token_binding_status( self) -> None: # Credential contains `clientDataJSON: { tokenBinding: { status: "not-supported" } }` credential = RegistrationCredential.parse_raw("""{ "id": "JeC3qgQjIVysq88GxhGUYyDl4oZeW8mLWd7luJWQvnrm-wxGZ5mzf2bBCaUDq7D2qr4aQezvzfoFIF880ciAsQ", "rawId": "JeC3qgQjIVysq88GxhGUYyDl4oZeW8mLWd7luJWQvnrm-wxGZ5mzf2bBCaUDq7D2qr4aQezvzfoFIF880ciAsQ", "response": { "clientDataJSON": "eyJjaGFsbGVuZ2UiOiJhR0ZHQ2JMMFZrUGYxRmNDVm5TQVpwNFpVSlRjZkY5diIsIm9yaWdpbiI6Imh0dHBzOi8vYXBpLWR1bzEuZHVvLnRlc3QiLCJ0b2tlbkJpbmRpbmciOnsic3RhdHVzIjoibm90LXN1cHBvcnRlZCJ9LCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0", "attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEgwRgIhAJB-eYnY106PNDhEVM8QLuZnVCxBX0Khp9vzdj-kjw1CAiEA0PlEdDtH4GKG3eY_1YC4sIZR2ZPg-9SsLgODDWUDYnRjeDVjgVkCUzCCAk8wggE3oAMCAQICBDxoKU0wDQYJKoZIhvcNAQELBQAwLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290IENBIFNlcmlhbCA0NTcyMDA2MzEwIBcNMTQwODAxMDAwMDAwWhgPMjA1MDA5MDQwMDAwMDBaMDExLzAtBgNVBAMMJll1YmljbyBVMkYgRUUgU2VyaWFsIDIzOTI1NzM0ODExMTE3OTAxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvd9nk9t3lMNQMXHtLE1FStlzZnUaSLql2fm1ajoggXlrTt8rzXuSehSTEPvEaEdv_FeSqX22L6Aoa8ajIAIOY6M7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAKrADVEJfuwVpIazebzEg0D4Z9OXLs5qZ_ukcONgxkRZ8K04QtP_CB5x6olTlxsj-SXArQDCRzEYUgbws6kZKfuRt2a1P-EzUiqDWLjRILSr-3_o7yR7ZP_GpiFKwdm-czb94POoGD-TS1IYdfXj94mAr5cKWx4EKjh210uovu_pLdLjc8xkQciUrXzZpPR9rT2k_q9HkZhHU-NaCJzky-PTyDbq0KKnzqVhWtfkSBCGw3ezZkTS-5lrvOKbIa24lfeTgu7FST5OwTPCFn8HcfWZMXMSD_KNU-iBqJdAwTLPPDRoLLvPTl29weCAIh-HUpmBQd0UltcPOrA_LFvAf61oYXV0aERhdGFYxEvYNAXQphWPDADgZiwL4n_m5OggKcxKctshspIdTVKXQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAl4LeqBCMhXKyrzwbGEZRjIOXihl5byYtZ3uW4lZC-eub7DEZnmbN_ZsEJpQOrsPaqvhpB7O_N-gUgXzzRyICxpQECAyYgASFYIJH525xGEk1oYXXxejoHvYcBrIwDbwcC_Kptwg6m5hArIlggvPFJ43EBPjkPK7aCIkiA3mtk_b6mkmzR8C_Fgjq3-xQ" }, "type": "public-key" } """) challenge = base64url_to_bytes("aGFGCbL0VkPf1FcCVnSAZp4ZUJTcfF9v", ) rp_id = "duo.test" expected_origin = "https://api-duo1.duo.test" verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.fmt == AttestationFormat.FIDO_U2F assert verification.credential_id == base64url_to_bytes( "JeC3qgQjIVysq88GxhGUYyDl4oZeW8mLWd7luJWQvnrm-wxGZ5mzf2bBCaUDq7D2qr4aQezvzfoFIF880ciAsQ", )
def test_verify_attestation_from_yubikey_firefox(self) -> None: credential = RegistrationCredential.parse_raw("""{ "id": "lrjqbPdLbWXTJ2sFIreka9aWd2ED-SDx_VAgBAh4XmCJgjCjudEjoi42pGQd-_Bi6nNPQ3T7-xOEgty2I3m7cw", "rawId": "lrjqbPdLbWXTJ2sFIreka9aWd2ED-SDx_VAgBAh4XmCJgjCjudEjoi42pGQd-_Bi6nNPQ3T7-xOEgty2I3m7cw", "response": { "attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIhAIJO_x-FicMO0XDFwnVfXWyF-Dp7GW7oL43QfZyUjKU0AiAxQBUFu17l9rmKmqAWnHL6F1dDaIu54WYc9Mi_jtdNL2N4NWOBWQLBMIICvTCCAaWgAwIBAgIEKudiYzANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbjELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEnMCUGA1UEAwweWXViaWNvIFUyRiBFRSBTZXJpYWwgNzE5ODA3MDc1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKgOGXmBD2Z4R_xCqJVRXhL8Jr45rHjsyFykhb1USGozZENOZ3cdovf5Ke8fj2rxi5tJGn_VnW4_6iQzKdIaeP6NsMGowIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjEwEwYLKwYBBAGC5RwCAQEEBAMCBDAwIQYLKwYBBAGC5RwBAQQEEgQQbUS6m_bsLkm5MAyP6SDLczAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQByV9A83MPhFWmEkNb4DvlbUwcjc9nmRzJjKxHc3HeK7GvVkm0H4XucVDB4jeMvTke0WHb_jFUiApvpOHh5VyMx5ydwFoKKcRs5x0_WwSWL0eTZ5WbVcHkDR9pSNcA_D_5AsUKOBcbpF5nkdVRxaQHuuIuwV4k1iK2IqtMNcU8vL6w21U261xCcWwJ6sMq4zzVO8QCKCQhsoIaWrwz828GDmPzfAjFsJiLJXuYivdHACkeJ5KHMt0mjVLpfJ2BCML7_rgbmvwL7wBW80VHfNdcKmKjkLcpEiPzwcQQhiN_qHV90t-p4iyr5xRSpurlP5zic2hlRkLKxMH2_kRjhqSn4aGF1dGhEYXRhWMRJlg3liA6MaHQ0Fw9kdmBbj-SuuaKGMseZXPO6gx2XY0EAAAAAAAAAAAAAAAAAAAAAAAAAAABAlrjqbPdLbWXTJ2sFIreka9aWd2ED-SDx_VAgBAh4XmCJgjCjudEjoi42pGQd-_Bi6nNPQ3T7-xOEgty2I3m7c6UBAgMmIAEhWCDpQmUwrGnn3mk-T27A6awwL4HJG62Plj8Hz-lL0KltuiJYILwFIu48iEB8Ov6mEAqtCxn3mQOoaGIG4eidiWyLRg05", "clientDataJSON": "eyJjaGFsbGVuZ2UiOiJaSlZObG1Pclh3d2dRa2QxZ0RNbHk4QklpSU1WNElRRERzQ3I2S1BiQ0lIY09aNXdhS0htLU1adHVZNzQ4U0NxZy1OWlZwUnJZRnlGcmMzNmdRb0Z0dyIsImNsaWVudEV4dGVuc2lvbnMiOnt9LCJoYXNoQWxnb3JpdGhtIjoiU0hBLTI1NiIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMCIsInR5cGUiOiJ3ZWJhdXRobi5jcmVhdGUifQ" }, "type": "public-key", "clientExtensionResults": {} } """) challenge = base64url_to_bytes( "ZJVNlmOrXwwgQkd1gDMly8BIiIMV4IQDDsCr6KPbCIHcOZ5waKHm-MZtuY748SCqg-NZVpRrYFyFrc36gQoFtw" ) rp_id = "localhost" expected_origin = "http://localhost:5000" verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.fmt == AttestationFormat.FIDO_U2F assert verification.credential_id == base64url_to_bytes( "lrjqbPdLbWXTJ2sFIreka9aWd2ED-SDx_VAgBAh4XmCJgjCjudEjoi42pGQd-_Bi6nNPQ3T7-xOEgty2I3m7cw" )
def test_raises_when_root_cert_invalid_for_response(self) -> None: # "packed" credential = RegistrationCredential.parse_raw("""{ "id": "syGQPDZRUYdb4m3rdWeyPaIMYlbmydGp1TP_33vE_lqJ3PHNyTd0iKsnKr5WjnCcBzcesZrDEfB_RBLFzU3k4w", "rawId": "syGQPDZRUYdb4m3rdWeyPaIMYlbmydGp1TP_33vE_lqJ3PHNyTd0iKsnKr5WjnCcBzcesZrDEfB_RBLFzU3k4w", "response": { "attestationObject": "o2NmbXRmcGFja2VkZ2F0dFN0bXSjY2FsZyZjc2lnWEcwRQIhAOfrFlQpbavT6dJeTDJSCDzYSYPjBDHli2-syT2c1IiKAiAx5gQ2z5cHjdQX-jEHTb7JcjfQoVSW8fXszF5ihSgeOGN4NWOBWQLBMIICvTCCAaWgAwIBAgIEKudiYzANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbjELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEnMCUGA1UEAwweWXViaWNvIFUyRiBFRSBTZXJpYWwgNzE5ODA3MDc1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKgOGXmBD2Z4R_xCqJVRXhL8Jr45rHjsyFykhb1USGozZENOZ3cdovf5Ke8fj2rxi5tJGn_VnW4_6iQzKdIaeP6NsMGowIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjEwEwYLKwYBBAGC5RwCAQEEBAMCBDAwIQYLKwYBBAGC5RwBAQQEEgQQbUS6m_bsLkm5MAyP6SDLczAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQByV9A83MPhFWmEkNb4DvlbUwcjc9nmRzJjKxHc3HeK7GvVkm0H4XucVDB4jeMvTke0WHb_jFUiApvpOHh5VyMx5ydwFoKKcRs5x0_WwSWL0eTZ5WbVcHkDR9pSNcA_D_5AsUKOBcbpF5nkdVRxaQHuuIuwV4k1iK2IqtMNcU8vL6w21U261xCcWwJ6sMq4zzVO8QCKCQhsoIaWrwz828GDmPzfAjFsJiLJXuYivdHACkeJ5KHMt0mjVLpfJ2BCML7_rgbmvwL7wBW80VHfNdcKmKjkLcpEiPzwcQQhiN_qHV90t-p4iyr5xRSpurlP5zic2hlRkLKxMH2_kRjhqSn4aGF1dGhEYXRhWMRJlg3liA6MaHQ0Fw9kdmBbj-SuuaKGMseZXPO6gx2XY0UAAAA0bUS6m_bsLkm5MAyP6SDLcwBAsyGQPDZRUYdb4m3rdWeyPaIMYlbmydGp1TP_33vE_lqJ3PHNyTd0iKsnKr5WjnCcBzcesZrDEfB_RBLFzU3k46UBAgMmIAEhWCBAX_i3O3DvBnkGq_uLNk_PeAX5WwO_MIxBp0mhX6Lw7yJYIOW-1-Fch829McWvRUYAHTWZTx5IycKSGECL1UzUaK_8", "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiOExCQ2lPWTNxMWNCWkhGQVd0UzRBWlpDaHpHcGh5NjdsSzdJNzB6S2k0eUM3cGdyUTJQY2g3bkFqTGsxd3E5Z3Jlc2hJQXNXMkFqaWJoWGpqSTBUbVEiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9" }, "type": "public-key", "clientExtensionResults": {}, "transports": [ "nfc", "usb" ] } """) challenge = base64url_to_bytes( "8LBCiOY3q1cBZHFAWtS4AZZChzGphy67lK7I70zKi4yC7pgrQ2Pch7nAjLk1wq9greshIAsW2AjibhXjjI0TmQ" ) rp_id = "localhost" expected_origin = "http://localhost:5000" with self.assertRaises(InvalidRegistrationResponse): verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, pem_root_certs_bytes_by_fmt={ # This root cert is actually for android-safetynet AttestationFormat.PACKED: [globalsign_r2] }, )
def post(self, request, *args, **kwargs): r""" Verify a registration challenge and register a 2-FA key. Called asynchronously by JavaScript. :param request: The current request :type request: ~django.http.HttpResponse :param \*args: The supplied arguments :type \*args: list :param \**kwargs: The supplied keyword arguments :type \**kwargs: dict :return: The JSON response :rtype: ~django.http.JsonResponse """ json_data = json.loads(request.body) webauthn_registration_response = verify_registration_response( credential=RegistrationCredential.parse_raw(request.body), expected_rp_id=settings.HOSTNAME, expected_origin=settings.BASE_URL, expected_challenge=base64url_to_bytes( request.session["mfa_registration_challenge"] ), ) existing_key = request.user.mfa_keys.filter(name=json_data["name"]) if existing_key.exists(): return JsonResponse( {"success": False, "error": _("This key name has already been used")} ) existing_key = request.user.mfa_keys.filter( key_id=webauthn_registration_response.credential_id ) if existing_key.exists(): return JsonResponse( {"success": False, "error": _("You already registered this key")} ) new_key = UserMfaKey( user=request.user, name=json_data["name"], key_id=webauthn_registration_response.credential_id, public_key=webauthn_registration_response.credential_public_key, sign_count=webauthn_registration_response.sign_count, ) new_key.save() messages.success( request, _( 'The 2-factor authentication key "{}" was successfully registered.' ).format(new_key.name), ) # Determine success url based on current region kwargs = {"region_slug": request.region.slug} if request.region else {} success_url = reverse("user_settings", kwargs=kwargs) return JsonResponse({"success": True, "successUrl": success_url})
def test_supports_multiple_expected_origins(self) -> None: credential = RegistrationCredential.parse_raw("""{ "id": "9y1xA8Tmg1FEmT-c7_fvWZ_uoTuoih3OvR45_oAK-cwHWhAbXrl2q62iLVTjiyEZ7O7n-CROOY494k7Q3xrs_w", "rawId": "9y1xA8Tmg1FEmT-c7_fvWZ_uoTuoih3OvR45_oAK-cwHWhAbXrl2q62iLVTjiyEZ7O7n-CROOY494k7Q3xrs_w", "response": { "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjESZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NFAAAAFwAAAAAAAAAAAAAAAAAAAAAAQPctcQPE5oNRRJk_nO_371mf7qE7qIodzr0eOf6ACvnMB1oQG165dqutoi1U44shGezu5_gkTjmOPeJO0N8a7P-lAQIDJiABIVggSFbUJF-42Ug3pdM8rDRFu_N5oiVEysPDB6n66r_7dZAiWCDUVnB39FlGypL-qAoIO9xWHtJygo2jfDmHl-_eKFRLDA", "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiVHdON240V1R5R0tMYzRaWS1xR3NGcUtuSE00bmdscXN5VjBJQ0psTjJUTzlYaVJ5RnRya2FEd1V2c3FsLWdrTEpYUDZmbkYxTWxyWjUzTW00UjdDdnciLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9" }, "type": "public-key", "clientExtensionResults": {}, "transports": [ "nfc", "usb" ] }""") challenge = base64url_to_bytes( "TwN7n4WTyGKLc4ZY-qGsFqKnHM4nglqsyV0ICJlN2TO9XiRyFtrkaDwUvsql-gkLJXP6fnF1MlrZ53Mm4R7Cvw" ) rp_id = "localhost" expected_origin = ["https://foo.bar", "http://localhost:5000"] verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.credential_id == base64url_to_bytes( "9y1xA8Tmg1FEmT-c7_fvWZ_uoTuoih3OvR45_oAK-cwHWhAbXrl2q62iLVTjiyEZ7O7n-CROOY494k7Q3xrs_w" )
def test_verify_attestation_android_safetynet( self, mock_verify_certificate: MagicMock) -> None: # Mocked because these certs actually expired and started failing this test mock_verify_certificate.return_value = True credential = RegistrationCredential.parse_raw("""{ "id": "AePltP2wAoNYwG5XGc9sfleGgDxQRHdkX8vphNIHv3HylIj_nZo9ncs7bLL65AGmVAc69pS4l64hgOBJU9o2jCQ", "rawId": "AePltP2wAoNYwG5XGc9sfleGgDxQRHdkX8vphNIHv3HylIj_nZo9ncs7bLL65AGmVAc69pS4l64hgOBJU9o2jCQ", "response": { "attestationObject": "o2NmbXRxYW5kcm9pZC1zYWZldHluZXRnYXR0U3RtdKJjdmVyaTIxMjYyMTAzN2hyZXNwb25zZVkgXGV5SmhiR2NpT2lKU1V6STFOaUlzSW5nMVl5STZXeUpOU1VsR1dIcERRMEpGWldkQmQwbENRV2RKVVdadE9HbFpXbnAxY1RCRlNrRkJRVUZCU0RkMVVsUkJUa0puYTNGb2EybEhPWGN3UWtGUmMwWkJSRUpIVFZGemQwTlJXVVJXVVZGSFJYZEtWbFY2UldsTlEwRkhRVEZWUlVOb1RWcFNNamwyV2pKNGJFbEdVbmxrV0U0d1NVWk9iR051V25CWk1sWjZTVVY0VFZGNlJWUk5Ra1ZIUVRGVlJVRjRUVXRTTVZKVVNVVk9Ra2xFUmtWT1JFRmxSbmN3ZVUxVVFUTk5WR3Q0VFhwRmVrNUVTbUZHZHpCNVRWUkZkMDFVWTNoTmVrVjZUa1JHWVUxQ01IaEhla0ZhUW1kT1ZrSkJUVlJGYlVZd1pFZFdlbVJETldoaWJWSjVZakpzYTB4dFRuWmlWRU5EUVZOSmQwUlJXVXBMYjFwSmFIWmpUa0ZSUlVKQ1VVRkVaMmRGVUVGRVEwTkJVVzlEWjJkRlFrRkxaazVUUWxsNE0wMDJTbkpKYVRCTVVVUkdORlZhYUhSemVUZ3lRMjgwVG5aM2NpOUdTVzQzTHpsbkszaHpWM3BEV1dkU04xRnpSMjF5ZVVjNWRsQkdja2Q1VVhKRlpHcERVWFZDVTFGVGQyOXZOR2R3YVVocGR6RllibkZHWm5KT1l6SjNURkpQTDFCVWRTdGhhMFpFU1UwMlozVXpaR1JuZDFGWFIwZGFjbFpRZWt0RmFrOTVUbE5HVFVKTU1GZEJTMmwxZFZsQ2RqRTBVWFp1YmxjeFJXdFpZbkZLWkZSb05reFhabVYyWTFkU1N5dFVkRlpoT1hwelIyNUZibWMzYTAxUVYxQkNTekJPTUdKUVozaGlOR3B1ZUdGSWNXeE1lSEV2UTJwRWJreHJSRVZrZFdabFZEVlZaM0pzVkc1M09WVnRXbTFOZUdGUWRHRXZkbm93WTJnMlpteERkM2xwZG1wSGFqSjRWRWhMVmxsMmJWbHdORlJtVEdjd1kxVk9VRVV4WkV0cVRrbGlTMWxEZUZGSlZucHVlSFY0WlhCVVUxWnBXWFZqVUVZMFZuZHVLelpFT1ZwNFVVcEtLeTlsTmt0TVNXdERRWGRGUVVGaFQwTkJia0YzWjJkS2MwMUJORWRCTVZWa1JIZEZRaTkzVVVWQmQwbEdiMFJCVkVKblRsWklVMVZGUkVSQlMwSm5aM0pDWjBWR1FsRmpSRUZVUVUxQ1owNVdTRkpOUWtGbU9FVkJha0ZCVFVJd1IwRXhWV1JFWjFGWFFrSlVUWE5VU1RWeFowRlBVbXRCWkROTlVFd3dOV2cwTm1KdlZsaEVRV1pDWjA1V1NGTk5SVWRFUVZkblFsRnNOR2huVDNOc1pWSnNRM0pzTVVZeVIydEpVR1ZWTjA4MGEycENkRUpuWjNKQ1owVkdRbEZqUWtGUlVtaE5SamgzUzJkWlNVdDNXVUpDVVZWSVRVRkhSMGh0YURCa1NFRTJUSGs1ZGxrelRuZE1ia0p5WVZNMWJtSXlPVzVNTW1Rd1kzcEdhMDVIYkhWa1JFRjRRbWRuY2tKblJVWkNVV04zUVc5WmJHRklVakJqUkc5MlRETkNjbUZUTlc1aU1qbHVURE5LYkdOSE9IWlpNbFo1WkVoTmRsb3pVbnBOVjFFd1RHMVNiR05xUVdSQ1owNVdTRkpGUlVacVFWVm5hRXBvWkVoU2JHTXpVWFZaVnpWclkyMDVjRnBETldwaU1qQjNTVkZaUkZaU01HZENRbTkzUjBSQlNVSm5XbTVuVVhkQ1FXZEZkMFJCV1V0TGQxbENRa0ZJVjJWUlNVWkJla0V2UW1kT1ZraFNPRVZQUkVFeVRVUlRaMDF4UVhkb2FUVnZaRWhTZDA5cE9IWlpNMHB6WTNrMWQyRXlhM1ZhTWpsMlduazVibVJJVFhoYVJGSndZbTVSZGxnd1dsRmpXRVpLVTBka1dVNXFaM1ZaTTBwelRVbEpRa0YzV1V0TGQxbENRa0ZJVjJWUlNVVkJaMU5DT1VGVFFqaFJSSFpCU0ZWQldFNTRSR3QyTjIxeE1GWkZjMVkyWVRGR1ltMUZSR1kzTVdad1NETkxSbnBzVEVwbE5YWmlTRVJ6YjBGQlFVWTJkbmd5VHpGblFVRkNRVTFCVW1wQ1JVRnBRa3AxVjFCU2JWSk5kbXBqVkZWd1NXSnlUa3RvT0hONFlrZDRUbEJOWm14aWNuWXhaSGhVYWtwM1EyZEpaMU01ZDJkTVZVcGxVWEZNVFZJNFdHVnVSMDVtZVZsb1lYRnNjbEo0ZUUwNGMxQTRWa2x3VVVkVFV6QkJaR2RDT1ZCMlREUnFMeXRKVmxkbmEzZHpSRXR1YkV0S1pWTjJSa1J1WjBwbWVUVnhiREpwV21acFRIY3hkMEZCUVZoeEwwaFpLMHRCUVVGRlFYZENTRTFGVlVOSlJESk1NbkpJUW14S2FUbFNSbTlQWmtWQ00yUjRTR1ZJVjFSS2QzTndORFpKWmtscU5tOUxTM0JZWWtGcFJVRXlOVk5aUmswNFp6RlVLMGRKVlhKVlRUQjRZMDVVZDJrdmJISnhhRmxyVVUxSEswWnpNbVp0Um1SSmQwUlJXVXBMYjFwSmFIWmpUa0ZSUlV4Q1VVRkVaMmRGUWtGRU5qaG1lRWhNZUU5REsxWnNUakZTVGtONVMyUlVjV1pJWWxKQlFXUk9XVmczTjBoWEwyMVFRbTVWUXpGb2NtVlVSM2hIZUZOT01VUm9hazF4Tkhwb09GQkRiVEI2TDNKQ00zQkVkMmxuYldsTmRtRllVRVZFYXpaRWJHbE5VMFY1WkRCak5ua3dPV2cxVjA1WFRpOWplR3BITDNWUk1ESjZSRU12UldrdlptUkZaM1V5TVVobmVITTNRMFZVZFROMFpUWkNiekZTZUM5NFIxRnRLMnRvTlhZd2NIWXJhVmw2Y25oVmJFOHZUV1J2YjJsa2VqbENRMWhYT0haeVRVbzJVbk5SVmxKUWVUUjVSbGN2TXpjeU4yeDFSRnBaTUVoME5XMUZSa2xLUTNCV1EybENUSE5wZURCd2JWUnNhMXBhZFhSRWFDOHZUV1JOTlVFME56RldRVU14VTBsNGVrTXpUMkYwZEZoV1RGTnRTWFpuZDFoWFlsbzVhekpzZWtwcGVrRnNiRkpMVld0TlRGUmtjMDlFY0RVek0yNVBhMlJXVTFvMlppdEljbkZKYzFSTVRuTTFVVk5MWWtVMGNuaHlkbFpPS3pROUlpd2lUVWxKUm1wRVEwTkJNMU5uUVhkSlFrRm5TVTVCWjBOUGMyZEplazV0VjB4YVRUTmliWHBCVGtKbmEzRm9hMmxIT1hjd1FrRlJjMFpCUkVKSVRWRnpkME5SV1VSV1VWRkhSWGRLVmxWNlJXbE5RMEZIUVRGVlJVTm9UVnBTTWpsMldqSjRiRWxHVW5sa1dFNHdTVVpPYkdOdVduQlpNbFo2U1VWNFRWRjZSVlZOUWtsSFFURlZSVUY0VFV4U01WSlVTVVpLZG1JelVXZFZha1YzU0doalRrMXFRWGRQUkVWNlRVUkJkMDFFVVhsWGFHTk9UV3BqZDA5VVRYZE5SRUYzVFVSUmVWZHFRa2ROVVhOM1ExRlpSRlpSVVVkRmQwcFdWWHBGYVUxRFFVZEJNVlZGUTJoTldsSXlPWFphTW5oc1NVWlNlV1JZVGpCSlJrNXNZMjVhY0ZreVZucEpSWGhOVVhwRlZFMUNSVWRCTVZWRlFYaE5TMUl4VWxSSlJVNUNTVVJHUlU1RVEwTkJVMGwzUkZGWlNrdHZXa2xvZG1OT1FWRkZRa0pSUVVSblowVlFRVVJEUTBGUmIwTm5aMFZDUVV0MlFYRnhVRU5GTWpkc01IYzVla000WkZSUVNVVTRPV0pCSzNoVWJVUmhSemQ1TjFabVVUUmpLMjFQVjJoc1ZXVmlWVkZ3U3pCNWRqSnlOamM0VWtwRmVFc3dTRmRFYW1WeEsyNU1TVWhPTVVWdE5XbzJja0ZTV21sNGJYbFNVMnBvU1ZJd1MwOVJVRWRDVFZWc1pITmhlblJKU1VvM1R6Qm5Memd5Y1dvdmRrZEViQzh2TTNRMGRGUnhlR2xTYUV4UmJsUk1XRXBrWlVJck1rUm9hMlJWTmtsSlozZzJkMDQzUlRWT1kxVklNMUpqYzJWcVkzRnFPSEExVTJveE9YWkNiVFpwTVVab2NVeEhlVzFvVFVaeWIxZFdWVWRQTTNoMFNVZzVNV1J6WjNrMFpVWkxZMlpMVmt4WFN6TnZNakU1TUZFd1RHMHZVMmxMYlV4aVVrbzFRWFUwZVRGbGRVWktiVEpLVFRsbFFqZzBSbXR4WVROcGRuSllWMVZsVm5SNVpUQkRVV1JMZG5OWk1rWnJZWHAyZUhSNGRuVnpURXA2VEZkWlNHczFOWHBqVWtGaFkwUkJNbE5sUlhSQ1lsRm1SREZ4YzBOQmQwVkJRV0ZQUTBGWVdYZG5aMFo1VFVFMFIwRXhWV1JFZDBWQ0wzZFJSVUYzU1VKb2FrRmtRbWRPVmtoVFZVVkdha0ZWUW1kbmNrSm5SVVpDVVdORVFWRlpTVXQzV1VKQ1VWVklRWGRKZDBWbldVUldVakJVUVZGSUwwSkJaM2RDWjBWQ0wzZEpRa0ZFUVdSQ1owNVdTRkUwUlVablVWVktaVWxaUkhKS1dHdGFVWEUxWkZKa2FIQkRSRE5zVDNwMVNrbDNTSGRaUkZaU01HcENRbWQzUm05QlZUVkxPSEpLYmtWaFN6Qm5ibWhUT1ZOYWFYcDJPRWxyVkdOVU5IZGhRVmxKUzNkWlFrSlJWVWhCVVVWRldFUkNZVTFEV1VkRFEzTkhRVkZWUmtKNlFVSm9hSEJ2WkVoU2QwOXBPSFppTWs1NlkwTTFkMkV5YTNWYU1qbDJXbms1Ym1SSVRubE5WRUYzUW1kbmNrSm5SVVpDVVdOM1FXOVphMkZJVWpCalJHOTJURE5DY21GVE5XNWlNamx1VEROS2JHTkhPSFpaTWxaNVpFaE5kbG96VW5wamFrVjFXa2RXZVUxRVVVZEJNVlZrU0hkUmRFMURjM2RMWVVGdWIwTlhSMGt5YURCa1NFRTJUSGs1YW1OdGQzVmpSM1J3VEcxa2RtSXlZM1phTTFKNlkycEZkbG96VW5wamFrVjFXVE5LYzAxRk1FZEJNVlZrU1VGU1IwMUZVWGREUVZsSFdqUkZUVUZSU1VKTlJHZEhRMmx6UjBGUlVVSXhibXREUWxGTmQwdHFRVzlDWjJkeVFtZEZSa0pSWTBOQlVsbGpZVWhTTUdOSVRUWk1lVGwzWVRKcmRWb3lPWFphZVRsNVdsaENkbU15YkRCaU0wbzFUSHBCVGtKbmEzRm9hMmxIT1hjd1FrRlJjMFpCUVU5RFFXZEZRVWxXVkc5NU1qUnFkMWhWY2pCeVFWQmpPVEkwZG5WVFZtSkxVWFZaZHpOdVRHWnNUR1pNYURWQldWZEZaVlpzTDBSMU1UaFJRVmRWVFdSalNqWnZMM0ZHV21Kb1dHdENTREJRVG1OM09UZDBhR0ZtTWtKbGIwUlpXVGxEYXk5aUsxVkhiSFZvZURBMmVtUTBSVUptTjBnNVVEZzBibTV5ZDNCU0t6UkhRa1JhU3l0WWFETkpNSFJ4U25reWNtZFBjVTVFWm14eU5VbE5VVGhhVkZkQk0zbHNkR0ZyZWxOQ1MxbzJXSEJHTUZCd2NYbERVblp3TDA1RFIzWXlTMWd5VkhWUVEwcDJjMk53TVM5dE1uQldWSFI1UW1wWlVGSlJLMUYxUTFGSFFVcExhblJPTjFJMVJFWnlabFJ4VFZkMldXZFdiSEJEU2tKcmQyeDFOeXMzUzFrelkxUkpabnBGTjJOdFFVeHphMDFMVGt4MVJIb3JVbnBEWTNOWlZITldZVlUzVm5BemVFdzJNRTlaYUhGR2EzVkJUMDk0UkZvMmNFaFBhamtyVDBwdFdXZFFiVTlVTkZnekt6ZE1OVEZtV0VwNVVrZzVTMlpNVWxBMmJsUXpNVVExYm0xelIwRlBaMW95Tmk4NFZEbG9jMEpYTVhWdk9XcDFOV1phVEZwWVZsWlROVWd3U0hsSlFrMUZTM2xIVFVsUWFFWlhjbXgwTDJoR1V6STRUakY2WVV0Sk1GcENSMFF6WjFsblJFeGlhVVJVT1daSFdITjBjR3NyUm0xak5HOXNWbXhYVUhwWVpUZ3hkbVJ2Ulc1R1luSTFUVEkzTWtoa1owcFhieXRYYUZRNVFsbE5NRXBwSzNka1ZtMXVVbVptV0dkc2IwVnZiSFZVVG1OWGVtTTBNV1JHY0dkS2RUaG1Sak5NUnpCbmJESnBZbE5aYVVOcE9XRTJhSFpWTUZSd2NHcEtlVWxYV0doclNsUmpUVXBzVUhKWGVERldlWFJGVlVkeVdESnNNRXBFZDFKcVZ5ODJOVFp5TUV0V1FqQXllRWhTUzNadE1scExTVEF6Vkdkc1RFbHdiVlpEU3pOclFrdHJTMDV3UWs1clJuUTRjbWhoWm1ORFMwOWlPVXA0THpsMGNFNUdiRkZVYkRkQ016bHlTbXhLVjJ0U01UZFJibHB4Vm5CMFJtVlFSazlTYjFwdFJucE5QU0lzSWsxSlNVWlpha05EUWtWeFowRjNTVUpCWjBsUlpEY3dUbUpPY3pJclVuSnhTVkV2UlRoR2FsUkVWRUZPUW1kcmNXaHJhVWM1ZHpCQ1FWRnpSa0ZFUWxoTlVYTjNRMUZaUkZaUlVVZEZkMHBEVWxSRldrMUNZMGRCTVZWRlEyaE5VVkl5ZUhaWmJVWnpWVEpzYm1KcFFuVmthVEY2V1ZSRlVVMUJORWRCTVZWRlEzaE5TRlZ0T1haa1EwSkVVVlJGWWsxQ2EwZEJNVlZGUVhoTlUxSXllSFpaYlVaelZUSnNibUpwUWxOaU1qa3dTVVZPUWsxQ05GaEVWRWwzVFVSWmVFOVVRWGROUkVFd1RXeHZXRVJVU1RSTlJFVjVUMFJCZDAxRVFUQk5iRzkzVW5wRlRFMUJhMGRCTVZWRlFtaE5RMVpXVFhoSmFrRm5RbWRPVmtKQmIxUkhWV1IyWWpKa2MxcFRRbFZqYmxaNlpFTkNWRnBZU2pKaFYwNXNZM2xDVFZSRlRYaEdSRUZUUW1kT1ZrSkJUVlJETUdSVlZYbENVMkl5T1RCSlJrbDRUVWxKUTBscVFVNUNaMnR4YUd0cFJ6bDNNRUpCVVVWR1FVRlBRMEZuT0VGTlNVbERRMmRMUTBGblJVRjBhRVZEYVhnM2FtOVlaV0pQT1hrdmJFUTJNMnhoWkVGUVMwZzVaM1pzT1UxbllVTmpabUl5YWtndk56Wk9kVGhoYVRaWWJEWlBUVk12YTNJNWNrZzFlbTlSWkhObWJrWnNPVGQyZFdaTGFqWmlkMU5wVmpadWNXeExjaXREVFc1NU5sTjRia2RRWWpFMWJDczRRWEJsTmpKcGJUbE5XbUZTZHpGT1JVUlFhbFJ5UlZSdk9HZFpZa1YyY3k5QmJWRXpOVEZyUzFOVmFrSTJSekF3YWpCMVdVOUVVREJuYlVoMU9ERkpPRVV6UTNkdWNVbHBjblUyZWpGcldqRnhLMUJ6UVdWM2JtcEllR2R6U0VFemVUWnRZbGQzV2tSeVdGbG1hVmxoVWxGTk9YTkliV3RzUTJsMFJETTRiVFZoWjBrdmNHSnZVRWRwVlZVck5rUlBiMmR5UmxwWlNuTjFRalpxUXpVeE1YQjZjbkF4V210cU5WcFFZVXMwT1d3NFMwVnFPRU00VVUxQlRGaE1NekpvTjAweFlrdDNXVlZJSzBVMFJYcE9hM1JOWnpaVVR6aFZjRzEyVFhKVmNITjVWWEYwUldvMVkzVklTMXBRWm0xbmFFTk9Oa296UTJsdmFqWlBSMkZMTDBkUU5VRm1iRFF2V0hSalpDOXdNbWd2Y25Nek4wVlBaVnBXV0hSTU1HMDNPVmxDTUdWelYwTnlkVTlETjFoR2VGbHdWbkU1VDNNMmNFWk1TMk4zV25CRVNXeFVhWEo0V2xWVVVVRnpObkY2YTIwd05uQTVPR2MzUWtGbEsyUkVjVFprYzI4ME9UbHBXVWcyVkV0WUx6RlpOMFI2YTNabmRHUnBlbXByV0ZCa2MwUjBVVU4yT1ZWM0szZHdPVlUzUkdKSFMyOW5VR1ZOWVROTlpDdHdkbVY2TjFjek5VVnBSWFZoS3l0MFoza3ZRa0pxUmtaR2VUTnNNMWRHY0U4NVMxZG5lamQ2Y0cwM1FXVkxTblE0VkRFeFpHeGxRMlpsV0d0clZVRkxTVUZtTlhGdlNXSmhjSE5hVjNkd1ltdE9SbWhJWVhneWVFbFFSVVJuWm1jeFlYcFdXVGd3V21OR2RXTjBURGRVYkV4dVRWRXZNR3hWVkdKcFUzY3hia2cyT1UxSE5ucFBNR0k1WmpaQ1VXUm5RVzFFTURaNVN6VTJiVVJqV1VKYVZVTkJkMFZCUVdGUFEwRlVaM2RuWjBVd1RVRTBSMEV4VldSRWQwVkNMM2RSUlVGM1NVSm9ha0ZRUW1kT1ZraFNUVUpCWmpoRlFsUkJSRUZSU0M5TlFqQkhRVEZWWkVSblVWZENRbFJyY25semJXTlNiM0pUUTJWR1RERktiVXhQTDNkcFVrNTRVR3BCWmtKblRsWklVMDFGUjBSQlYyZENVbWRsTWxsaFVsRXlXSGx2YkZGTU16QkZlbFJUYnk4dmVqbFRla0puUW1kbmNrSm5SVVpDVVdOQ1FWRlNWVTFHU1hkS1VWbEpTM2RaUWtKUlZVaE5RVWRIUjFkb01HUklRVFpNZVRsMldUTk9kMHh1UW5KaFV6VnVZakk1Ymt3eVpIcGpha1YzUzFGWlNVdDNXVUpDVVZWSVRVRkxSMGhYYURCa1NFRTJUSGs1ZDJFeWEzVmFNamwyV25rNWJtTXpTWGhNTW1SNlkycEZkVmt6U2pCTlJFbEhRVEZWWkVoM1VYSk5RMnQzU2paQmJHOURUMGRKVjJnd1pFaEJOa3g1T1dwamJYZDFZMGQwY0V4dFpIWmlNbU4yV2pOT2VVMVRPVzVqTTBsNFRHMU9lV0pFUVRkQ1owNVdTRk5CUlU1RVFYbE5RV2RIUW0xbFFrUkJSVU5CVkVGSlFtZGFibWRSZDBKQlowbDNSRkZaVEV0M1dVSkNRVWhYWlZGSlJrRjNTWGRFVVZsTVMzZFpRa0pCU0ZkbFVVbEdRWGROZDBSUldVcExiMXBKYUhaalRrRlJSVXhDVVVGRVoyZEZRa0ZFVTJ0SWNrVnZiemxETUdSb1pXMU5XRzlvTm1SR1UxQnphbUprUWxwQ2FVeG5PVTVTTTNRMVVDdFVORlo0Wm5FM2RuRm1UUzlpTlVFelVta3habmxLYlRsaWRtaGtSMkZLVVROaU1uUTJlVTFCV1U0dmIyeFZZWHB6WVV3cmVYbEZiamxYY0hKTFFWTlBjMmhKUVhKQmIzbGFiQ3QwU21GdmVERXhPR1psYzNOdFdHNHhhRWxXZHpReGIyVlJZVEYyTVhabk5FWjJOelI2VUd3MkwwRm9VM0ozT1ZVMWNFTmFSWFEwVjJrMGQxTjBlalprVkZvdlEweEJUbmc0VEZwb01VbzNVVXBXYWpKbWFFMTBabFJLY2psM05Ib3pNRm95TURsbVQxVXdhVTlOZVN0eFpIVkNiWEIyZGxsMVVqZG9Xa3cyUkhWd2MzcG1ibmN3VTJ0bWRHaHpNVGhrUnpsYVMySTFPVlZvZG0xaFUwZGFVbFppVGxGd2MyY3pRbHBzZG1sa01HeEpTMDh5WkRGNGIzcGpiRTk2WjJwWVVGbHZka3BLU1hWc2RIcHJUWFV6TkhGUllqbFRlaTk1YVd4eVlrTm5hamc5SWwxOS5leUp1YjI1alpTSTZJakp5TlZWak5EQXhieTkxWW5WNWVGbzJUVk4wVGtGa1pXMUlkVGg0UVZReWNXOVFXR2c1WldoeVdUZzlJaXdpZEdsdFpYTjBZVzF3VFhNaU9qRTJNekEzTURNeU5EQXdOVGNzSW1Gd2ExQmhZMnRoWjJWT1lXMWxJam9pWTI5dExtZHZiMmRzWlM1aGJtUnliMmxrTG1kdGN5SXNJbUZ3YTBScFoyVnpkRk5vWVRJMU5pSTZJbXhHVVhkSFYwRklkekZaTkdKNVNsUjRSVWQ0T0hsQmFsVkJlVUZFUW10NFJqTlNaa0pIVHpSMVFUZzlJaXdpWTNSelVISnZabWxzWlUxaGRHTm9JanAwY25WbExDSmhjR3REWlhKMGFXWnBZMkYwWlVScFoyVnpkRk5vWVRJMU5pSTZXeUk0VURGelZ6QkZVRXBqYzJ4M04xVjZVbk5wV0V3Mk5IY3JUelV3UldRclVrSkpRM1JoZVRGbk1qUk5QU0pkTENKaVlYTnBZMGx1ZEdWbmNtbDBlU0k2ZEhKMVpTd2laWFpoYkhWaGRHbHZibFI1Y0dVaU9pSkNRVk5KUXlKOS5NUFlueXVkY3lOQTB1bHM1R0NidXpkTmhvNVhReDkyY2NfUWwyVXdSa1hWdTdPVE5SRVdRTTdHRkN4Wl9TcEJ4ZzBqS1lRd21FX2Z3Rll2U1BqaXlZbmpocENKejFZQjY5bVAwMG9VaHJzTUR2MmgxblQwTjdxd045U2tUTno4WFdnN0VPRDhmcUI0US1NMUNoemdRelNla2RxQXBfSXlrQXdYRjBFM3pqV0xuN2h1WTNjV3FPeFQzNGRSWFBFWkNIMlR1RDRQSUdHcmVJMlkxczlrckY1NjZjZGtfaXRKcGQ3ZlZ4OVVHaEtkNkg3bi02NGtQUzF2VE10WkhkMXRtRExuM3p4aUhTLVJmWFBxT3JEY0NacWcxcXFPdTRnQWpCb1pZbW03RF9oM2gzUVh6aW9ob0ZoeFNpNHVYMjc3NDU1ZHlRSXY2VW02RkpVZWFNOXE4ZEFoYXV0aERhdGFYxUM-aBZp-t3K2T8SiJsc0tHiVg5EKhu4zSaRsspfcKDIRQAAAAC5P9lh8uZGL7EiggAiR954AEEB4-W0_bACg1jAblcZz2x-V4aAPFBEd2Rfy-mE0ge_cfKUiP-dmj2dyztssvrkAaZUBzr2lLiXriGA4ElT2jaMJKUBAgMmIAEhWCCRXy7I5ieefvztqGsBuhKzrZ791MIGmTh9EvllVMBLzyJYIEUi7k0WWjywJtUaxQkA-0zRgEPQCYTP9hkDWi_BTH4j", "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiczh4cnFMc3hnZXdqdG80c3gzbjFqVFlJUlFCcEhXbjMiLCJvcmlnaW4iOiJodHRwczpcL1wvZGV2aWNlbWFuYWdlbWVudC1kdW8xLnB3bC5uZ3Jvay5pbyIsImFuZHJvaWRQYWNrYWdlTmFtZSI6ImNvbS5hbmRyb2lkLmNocm9tZSJ9" }, "type": "public-key", "clientExtensionResults": {} } """) parsed_attestation_object = parse_attestation_object( credential.response.attestation_object) # Test the verifier itself so we can activate its timestamp verification bypass verified = verify_android_safetynet( attestation_statement=parsed_attestation_object.att_stmt, attestation_object=credential.response.attestation_object, client_data_json=credential.response.client_data_json, pem_root_certs_bytes=[], verify_timestamp_ms=False, ) assert verified is True
def test_raises_exception_on_unsupported_attestation_type(self) -> None: cred_json = { "id": "FsWBrFcw8yRjxV8z18Egh91o1AScNRYkIuUoY6wIlIhslDpP7eydKi1q5s9g1ugDP9mqBlPDDFPRbH6YLwHbtg", "rawId": "FsWBrFcw8yRjxV8z18Egh91o1AScNRYkIuUoY6wIlIhslDpP7eydKi1q5s9g1ugDP9mqBlPDDFPRbH6YLwHbtg", "response": { "attestationObject": "o2NmbXRmcGFja2VkZ2F0dFN0bXSjY2FsZyZjc2lnWEcwRQIgRpuZ6hdaLAgWgCFTIo4BGSTBAxwwqk4u3s1-JAzv_H4CIQCZnfoic34aOwlac1A09eflEtb0V1kO7yGhHOw5P5wVWmN4NWOBWQLBMIICvTCCAaWgAwIBAgIEKudiYzANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbjELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEnMCUGA1UEAwweWXViaWNvIFUyRiBFRSBTZXJpYWwgNzE5ODA3MDc1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKgOGXmBD2Z4R_xCqJVRXhL8Jr45rHjsyFykhb1USGozZENOZ3cdovf5Ke8fj2rxi5tJGn_VnW4_6iQzKdIaeP6NsMGowIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjEwEwYLKwYBBAGC5RwCAQEEBAMCBDAwIQYLKwYBBAGC5RwBAQQEEgQQbUS6m_bsLkm5MAyP6SDLczAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQByV9A83MPhFWmEkNb4DvlbUwcjc9nmRzJjKxHc3HeK7GvVkm0H4XucVDB4jeMvTke0WHb_jFUiApvpOHh5VyMx5ydwFoKKcRs5x0_WwSWL0eTZ5WbVcHkDR9pSNcA_D_5AsUKOBcbpF5nkdVRxaQHuuIuwV4k1iK2IqtMNcU8vL6w21U261xCcWwJ6sMq4zzVO8QCKCQhsoIaWrwz828GDmPzfAjFsJiLJXuYivdHACkeJ5KHMt0mjVLpfJ2BCML7_rgbmvwL7wBW80VHfNdcKmKjkLcpEiPzwcQQhiN_qHV90t-p4iyr5xRSpurlP5zic2hlRkLKxMH2_kRjhqSn4aGF1dGhEYXRhWMRJlg3liA6MaHQ0Fw9kdmBbj-SuuaKGMseZXPO6gx2XY0UAAAAqbUS6m_bsLkm5MAyP6SDLcwBAFsWBrFcw8yRjxV8z18Egh91o1AScNRYkIuUoY6wIlIhslDpP7eydKi1q5s9g1ugDP9mqBlPDDFPRbH6YLwHbtqUBAgMmIAEhWCAq3y0RWh8nLzanBZQwTA7yAbUy9KEDAM0b3N9Elrb0VCJYIJrX7ygtpyInb5mXBE7g9YEow6xWrJ400HhL2r4q5tzV", "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoicERSbWtkZHVBaS1BVTJ4Nm8tRnFxaEkzWEsybmxWbHNDU3IwNHpXa050djg0SndyTUh0RWxSSEhVV0xFRGhrckVhUThCMWxCY0lIX1ZTUnFwX1JBQXciLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9", }, "type": "public-key", "clientExtensionResults": {}, "transports": ["nfc", "usb"], } # Take the otherwise legitimate credential and mangle its attestationObject's # "fmt" to something it could never actually be parsed_atte_obj = cbor2.loads(base64url_to_bytes(cred_json["response"]["attestationObject"])) # type: ignore parsed_atte_obj["fmt"] = "not_real_fmt" cred_json["response"]["attestationObject"] = bytes_to_base64url(cbor2.dumps(parsed_atte_obj)) # type: ignore credential = RegistrationCredential.parse_raw(json.dumps(cred_json)) challenge = base64url_to_bytes( "pDRmkdduAi-AU2x6o-FqqhI3XK2nlVlsCSr04zWkNtv84JwrMHtElRHHUWLEDhkrEaQ8B1lBcIH_VSRqp_RAAw" ) rp_id = "localhost" expected_origin = "http://localhost:5000" with self.assertRaisesRegex( Exception, "value is not a valid enumeration member" ): verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, )
def test_verify_attestation_with_unsupported_token_binding(self) -> None: # Credential contains `clientDataJSON: { tokenBinding: "unused" }` credential = RegistrationCredential.parse_raw("""{ "id": "jXFBv0gxr-DvGP58Oz3qfxMydiZM2RFlRoItoHyeAhdLNbmR7aPkzPVSKWO9VOZ4A2EEUQz8nsLtsP5EOqeNiQ", "rawId": "jXFBv0gxr-DvGP58Oz3qfxMydiZM2RFlRoItoHyeAhdLNbmR7aPkzPVSKWO9VOZ4A2EEUQz8nsLtsP5EOqeNiQ", "response": { "clientDataJSON": "eyJjaGFsbGVuZ2UiOiJCMjBMWlFBNnZtb2hXMnB2Q1RpM3lsVU5HZXQ4NTZwbyIsImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cHM6Ly9hcGktZHVvMS5kdW8udGVzdCIsInRva2VuQmluZGluZyI6InVudXNlZCIsInR5cGUiOiJ3ZWJhdXRobi5jcmVhdGUifQ", "attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEYwRAIgZNXeJymCt3MaODbi40dqksHQmfjvOajH4Th3qHK4nboCIEemlbhtg6g549fk5f6xU901qYeowKQ4lDOxwBisVo-RY3g1Y4FZAlMwggJPMIIBN6ADAgECAgQ8aClNMA0GCSqGSIb3DQEBCwUAMC4xLDAqBgNVBAMTI1l1YmljbyBVMkYgUm9vdCBDQSBTZXJpYWwgNDU3MjAwNjMxMCAXDTE0MDgwMTAwMDAwMFoYDzIwNTAwOTA0MDAwMDAwWjAxMS8wLQYDVQQDDCZZdWJpY28gVTJGIEVFIFNlcmlhbCAyMzkyNTczNDgxMTExNzkwMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL3fZ5Pbd5TDUDFx7SxNRUrZc2Z1Gki6pdn5tWo6IIF5a07fK817knoUkxD7xGhHb_xXkql9ti-gKGvGoyACDmOjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS41MBMGCysGAQQBguUcAgEBBAQDAgUgMA0GCSqGSIb3DQEBCwUAA4IBAQCqwA1RCX7sFaSGs3m8xINA-GfTly7Oamf7pHDjYMZEWfCtOELT_wgeceqJU5cbI_klwK0AwkcxGFIG8LOpGSn7kbdmtT_hM1Iqg1i40SC0q_t_6O8ke2T_xqYhSsHZvnM2_eDzqBg_k0tSGHX14_eJgK-XClseBCo4dtdLqL7v6S3S43PMZEHIlK182aT0fa09pP6vR5GYR1PjWgic5Mvj08g26tCip86lYVrX5EgQhsN3s2ZE0vuZa7zimyGtuJX3k4LuxUk-TsEzwhZ_B3H1mTFzEg_yjVPogaiXQMEyzzw0aCy7z05dvcHggCIfh1KZgUHdFJbXDzqwPyxbwH-taGF1dGhEYXRhWMRL2DQF0KYVjwwA4GYsC-J_5uToICnMSnLbIbKSHU1Sl0EAAAAAAAAAAAAAAAAAAAAAAAAAAABAjXFBv0gxr-DvGP58Oz3qfxMydiZM2RFlRoItoHyeAhdLNbmR7aPkzPVSKWO9VOZ4A2EEUQz8nsLtsP5EOqeNiaUBAgMmIAEhWCD2BOHjcogovRtFtYbJpxctnRdgL-GL_Dwh0Pje7wUJ7yJYIACvXapVQbM5vEurQkI4096yU5dXv6CA-PftVTiTj-LT" }, "type": "public-key" } """) challenge = base64url_to_bytes("B20LZQA6vmohW2pvCTi3ylUNGet856po", ) rp_id = "duo.test" expected_origin = "https://api-duo1.duo.test" verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.fmt == AttestationFormat.FIDO_U2F assert verification.credential_id == base64url_to_bytes( "jXFBv0gxr-DvGP58Oz3qfxMydiZM2RFlRoItoHyeAhdLNbmR7aPkzPVSKWO9VOZ4A2EEUQz8nsLtsP5EOqeNiQ", )
def test_verify_registration_response(monkeypatch): fake_verified_registration = VerifiedRegistration( credential_id=b"foo", credential_public_key=b"bar", sign_count=0, aaguid="wutang", fmt=AttestationFormat.NONE, credential_type=PublicKeyCredentialType.PUBLIC_KEY, user_verified=False, attestation_object=b"foobar", ) mock_verify_registration_response = pretend.call_recorder( lambda *a, **kw: fake_verified_registration ) monkeypatch.setattr( pywebauthn, "verify_registration_response", mock_verify_registration_response ) resp = webauthn.verify_registration_response( ( '{"id": "foo", "rawId": "foo", "response": ' '{"attestationObject": "foo", "clientDataJSON": "bar"}}' ), b"not_a_real_challenge", rp_id="fake_rp_id", origin="fake_origin", ) assert mock_verify_registration_response.calls == [ pretend.call( credential=RegistrationCredential( id="foo", raw_id=b"~\x8a", response=AuthenticatorAttestationResponse( client_data_json=b"m\xaa", attestation_object=b"~\x8a" ), transports=None, type=PublicKeyCredentialType.PUBLIC_KEY, ), expected_challenge=bytes_to_base64url(b"not_a_real_challenge").encode(), expected_rp_id="fake_rp_id", expected_origin="fake_origin", require_user_verification=False, ) ] assert resp == fake_verified_registration
def validate_response(self, response: dict) -> dict: """Validate webauthn challenge response""" challenge = self.request.session["challenge"] try: registration: VerifiedRegistration = verify_registration_response( credential=RegistrationCredential.parse_raw(dumps(response)), expected_challenge=challenge, expected_rp_id=get_rp_id(self.request), expected_origin=get_origin(self.request), ) except InvalidRegistrationResponse as exc: LOGGER.warning("registration failed", exc=exc) raise ValidationError(f"Registration failed. Error: {exc}") credential_id_exists = WebAuthnDevice.objects.filter( credential_id=bytes_to_base64url( registration.credential_id)).first() if credential_id_exists: raise ValidationError("Credential ID already exists.") return registration
def test_verify_attestation_apple_passkey( self, mock_verify_certificate: MagicMock ) -> None: # Mocked because these certs actually expired and started failing this test mock_verify_certificate.return_value = True credential = RegistrationCredential.parse_raw( """{ "id": "0yhsKG_gCzynIgNbvXWkqJKL8Uc", "rawId": "0yhsKG_gCzynIgNbvXWkqJKL8Uc", "response": { "attestationObject": "o2NmbXRlYXBwbGVnYXR0U3RtdKFjeDVjglkCRzCCAkMwggHJoAMCAQICBgF7o5kiITAKBggqhkjOPQQDAjBIMRwwGgYDVQQDDBNBcHBsZSBXZWJBdXRobiBDQSAxMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTIxMDgzMTIzMDIwN1oXDTIxMDkwMzIzMDIwN1owgZExSTBHBgNVBAMMQGIxMGY3MThiYzVkZDc1ODg4NmExZDhjZmI1YjhiNjMxNzI5ZjRkN2U0YmEwNjlhYjBhOTkyYzFjMDg0NzhhZjkxGjAYBgNVBAsMEUFBQSBDZXJ0aWZpY2F0aW9uMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0SSw6f-BknI8nuL6T4Fw03PgMobPiAruxwCKFM3qZHJJY-BbuMRKn5gN7RKqijN5XPgdMedBFs7W8fTF6ww1j6NVMFMwDAYDVR0TAQH_BAIwADAOBgNVHQ8BAf8EBAMCBPAwMwYJKoZIhvdjZAgCBCYwJKEiBCDkV-W8KS8WNSECSO0ud2uhKcfMRpUkp1NWg2yu8vBYoDAKBggqhkjOPQQDAgNoADBlAjBlxucHXdrLUIeahBKQR1kBPQ2nhyZAh1mgHxmUwXlaacLB0RMGwtG8l75hQWJ7hncCMQCrC559l8orYDse224mTEm_GXE4DCr6XTf4xP9aXebUV6GcuAwCsu35SwhT4EgvhoZZAjgwggI0MIIBuqADAgECAhBWJVOVx6f7QOviKNgmCFO2MAoGCCqGSM49BAMDMEsxHzAdBgNVBAMMFkFwcGxlIFdlYkF1dGhuIFJvb3QgQ0ExEzARBgNVBAoMCkFwcGxlIEluYy4xEzARBgNVBAgMCkNhbGlmb3JuaWEwHhcNMjAwMzE4MTgzODAxWhcNMzAwMzEzMDAwMDAwWjBIMRwwGgYDVQQDDBNBcHBsZSBXZWJBdXRobiBDQSAxMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEgy6HLyYUkYECJbn1_Na7Y3i19V8_ywRbxzWZNHX9VJBE35v-GSEXZcaaHdoFCzjUUINAGkNPsk0RLVbD4c-_y5iR_sBpYIG--Wy8d8iN3a9Gpa7h3VFbWvqrk76cCyaRo2YwZDASBgNVHRMBAf8ECDAGAQH_AgEAMB8GA1UdIwQYMBaAFCbXZNnFeMJaZ9Gn3msS0Btj8cbXMB0GA1UdDgQWBBTrroLE_6GsW1HUzyRhBQC-Y713iDAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIxAN2LGjSBpfrZ27TnZXuEHhRMJ7dbh2pBhsKxR1dQM3In7-VURX72SJUMYy5cSD5wwQIwLIpgRNwgH8_lm8NNKTDBSHhR2WDtanXx60rKvjjNJbiX0MgFvvDH94sHpXHG6A4HaGF1dGhEYXRhWJiPh6BZvowZk4E0cyGRAQ-e4LvoufWAcLD1j4UMTOIowUUAAAAA8kqOcNDT-CwpNzJSPMTeWgAU0yhsKG_gCzynIgNbvXWkqJKL8UelAQIDJiABIVgg0SSw6f-BknI8nuL6T4Fw03PgMobPiAruxwCKFM3qZHIiWCBJY-BbuMRKn5gN7RKqijN5XPgdMedBFs7W8fTF6ww1jw", "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiMW5ocXlNa2ZHQVFMLXRUY3NmcHVveXE4aHFlb0hyMGQ5dERtanYxQnVKOTdZVEEzRkxXUzVFZFk0cVVnLU16cnVjMnNpQmR5VmxuRklQQjFnMEhoMkEiLCJvcmlnaW4iOiJodHRwczovL2RldjIuZG9udG5lZWRhLnB3OjUwMDAifQ" }, "type": "public-key", "clientExtensionResults": {} } """ ) challenge = base64url_to_bytes( "1nhqyMkfGAQL-tTcsfpuoyq8hqeoHr0d9tDmjv1BuJ97YTA3FLWS5EdY4qUg-Mzruc2siBdyVlnFIPB1g0Hh2A" ) rp_id = "dev2.dontneeda.pw" expected_origin = "https://dev2.dontneeda.pw:5000" verification = verify_registration_response( credential=credential, expected_challenge=challenge, expected_origin=expected_origin, expected_rp_id=rp_id, ) assert verification.fmt == AttestationFormat.APPLE assert verification.credential_id == base64url_to_bytes( "0yhsKG_gCzynIgNbvXWkqJKL8Uc" )
def verify_registration_response(response, challenge, *, rp_id, origin): """ Validates the challenge and attestation information sent from the client during device registration. Returns a WebAuthnCredential on success. Raises RegistrationRejectedError on failire. """ # NOTE: We re-encode the challenge below, because our # response's clientData.challenge is encoded twice: # first for the entire clientData payload, and then again # for the individual challenge. encoded_challenge = _webauthn_b64encode(challenge) try: _credential = RegistrationCredential.parse_raw(response) return pywebauthn.verify_registration_response( credential=_credential, expected_challenge=encoded_challenge, expected_rp_id=rp_id, expected_origin=origin, require_user_verification=False, ) except InvalidRegistrationResponse as e: raise RegistrationRejectedError(str(e))
], supported_pub_key_algs=[COSEAlgorithmIdentifier.ECDSA_SHA_512], timeout=12000, ) print("\n[Registration Options - Complex]") print(options_to_json(complex_registration_options)) # Registration Response Verification registration_verification = verify_registration_response( credential=RegistrationCredential.parse_raw("""{ "id": "ZoIKP1JQvKdrYj1bTUPJ2eTUsbLeFkv-X5xJQNr4k6s", "rawId": "ZoIKP1JQvKdrYj1bTUPJ2eTUsbLeFkv-X5xJQNr4k6s", "response": { "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVkBZ0mWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjRQAAAAAAAAAAAAAAAAAAAAAAAAAAACBmggo_UlC8p2tiPVtNQ8nZ5NSxst4WS_5fnElA2viTq6QBAwM5AQAgWQEA31dtHqc70D_h7XHQ6V_nBs3Tscu91kBL7FOw56_VFiaKYRH6Z4KLr4J0S12hFJ_3fBxpKfxyMfK66ZMeAVbOl_wemY4S5Xs4yHSWy21Xm_dgWhLJjZ9R1tjfV49kDPHB_ssdvP7wo3_NmoUPYMgK-edgZ_ehttp_I6hUUCnVaTvn_m76b2j9yEPReSwl-wlGsabYG6INUhTuhSOqG-UpVVQdNJVV7GmIPHCA2cQpJBDZBohT4MBGme_feUgm4sgqVCWzKk6CzIKIz5AIVnspLbu05SulAVnSTB3NxTwCLNJR_9v9oSkvphiNbmQBVQH1tV_psyi9HM1Jtj9VJVKMeyFDAQAB", "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiQ2VUV29nbWcwY2NodWlZdUZydjhEWFhkTVpTSVFSVlpKT2dhX3hheVZWRWNCajBDdzN5NzN5aEQ0RmtHU2UtUnJQNmhQSkpBSW0zTFZpZW40aFhFTGciLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9" }, "type": "public-key", "clientExtensionResults": {}, "transports": ["internal"] }"""), expected_challenge=base64url_to_bytes( "CeTWogmg0cchuiYuFrv8DXXdMZSIQRVZJOga_xayVVEcBj0Cw3y73yhD4FkGSe-RrP6hPJJAIm3LVien4hXELg" ), expected_origin="http://localhost:5000", expected_rp_id="localhost", require_user_verification=True, ) print("\n[Registration Verification - None]") print(registration_verification.json(indent=2))