Esempio n. 1
0
    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_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"
        )
Esempio n. 3
0
    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",
        )
Esempio n. 4
0
    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,
            )
Esempio n. 5
0
    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",
        )
Esempio n. 6
0
    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"
        )
Esempio n. 7
0
    def test_verify_authentication_response_with_OKP_public_key(self):
        credential = AuthenticationCredential.parse_raw(
            """{
                "id": "fq9Nj0nS24B5y6Pkw_h3-9GEAEA3-0LBPxE2zvTdLjDqtSeCSNYFe9VMRueSpAZxT3YDc6L1lWXdQNwI-sVNYrefEcRR1Nsb_0jpHE955WEtFud2xxZg3MvoLMxHLet63i5tajd1fHtP7I-00D6cehM8ZWlLp2T3s9lfZgVIFcA",
                "rawId": "fq9Nj0nS24B5y6Pkw_h3-9GEAEA3-0LBPxE2zvTdLjDqtSeCSNYFe9VMRueSpAZxT3YDc6L1lWXdQNwI-sVNYrefEcRR1Nsb_0jpHE955WEtFud2xxZg3MvoLMxHLet63i5tajd1fHtP7I-00D6cehM8ZWlLp2T3s9lfZgVIFcA",
                "response": {
                    "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAABw",
                    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZVo0ZWVBM080ank1Rkl6cURhU0o2SkROR3UwYkJjNXpJMURqUV9rTHNvMVdOcWtHNms1bUNZZjFkdFFoVlVpQldaV2xaa3pSNU1GZWVXQ3BKUlVOWHciLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
                    "signature": "RRWV8mYDRvK7YdQgdtZD4pJ2dh1D_IWZ_D6jsZo6FHJBoenbj0CVT5nA20vUzlRhN4R6dOEUHmUwP1F8eRBhBg"
                },
                "type": "public-key",
                "clientExtensionResults": {}
            }"""
        )
        challenge = base64url_to_bytes(
            "eZ4eeA3O4jy5FIzqDaSJ6JDNGu0bBc5zI1DjQ_kLso1WNqkG6k5mCYf1dtQhVUiBWZWlZkzR5MFeeWCpJRUNXw"
        )
        expected_rp_id = "localhost"
        expected_origin = "http://localhost:5000"
        credential_public_key = base64url_to_bytes(
            "pAEBAycgBiFYIMz6_SUFLiDid2Yhlq0YboyJ-CDrIrNpkPUGmJp4D3Dp"
        )
        sign_count = 3

        verification = verify_authentication_response(
            credential=credential,
            expected_challenge=challenge,
            expected_rp_id=expected_rp_id,
            expected_origin=expected_origin,
            credential_public_key=credential_public_key,
            credential_current_sign_count=sign_count,
        )

        assert verification.new_sign_count == 7
Esempio n. 8
0
    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_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": "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"
            },
            "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_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 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"
        )
Esempio n. 12
0
    def test_verify_attestation_from_yubikey_firefox(self) -> None:
        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"

        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(
            "syGQPDZRUYdb4m3rdWeyPaIMYlbmydGp1TP_33vE_lqJ3PHNyTd0iKsnKr5WjnCcBzcesZrDEfB_RBLFzU3k4w"
        )
Esempio n. 13
0
    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_can_parse_attestation_client_data(self):
        client_data_bytes = base64url_to_bytes(
            "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoidkZHdmt6UFZzQ0JKOXVLMWxHT0ZucGl4NDF5clB1eFBITFlMdGJRckVYNjNqSlplYXNaVlBfY3lZZkExYktmelJJbk1vcG05VUJtNkNvS2FfakZ0MWciLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
        )
        expected_challenge = base64url_to_bytes(
            "vFGvkzPVsCBJ9uK1lGOFnpix41yrPuxPHLYLtbQrEX63jJZeasZVP_cyYfA1bKfzRInMopm9UBm6CoKa_jFt1g"
        )

        output = parse_client_data_json(client_data_bytes)

        assert output.type == "webauthn.create"
        assert output.challenge == expected_challenge
        assert output.origin == "http://localhost:5000"
        assert output.cross_origin is False
        assert output.token_binding is None
Esempio n. 15
0
 def parse_raw(cls, header_data: str):
     parsed: dict = json_loads_base64url_to_bytes(
         base64url_to_bytes(header_data))
     return cls(
         alg=parsed["alg"],
         x5c=parsed["x5c"],
     )
Esempio n. 16
0
def validate_challenge_webauthn(data: dict, request: HttpRequest,
                                user: User) -> Device:
    """Validate WebAuthn Challenge"""
    challenge = request.session.get("challenge")
    credential_id = data.get("id")

    device = WebAuthnDevice.objects.filter(credential_id=credential_id).first()
    if not device:
        raise ValidationError("Device does not exist.")

    try:
        authentication_verification = verify_authentication_response(
            credential=AuthenticationCredential.parse_raw(dumps(data)),
            expected_challenge=challenge,
            expected_rp_id=get_rp_id(request),
            expected_origin=get_origin(request),
            credential_public_key=base64url_to_bytes(device.public_key),
            credential_current_sign_count=device.sign_count,
            require_user_verification=False,
        )

    except InvalidAuthenticationResponse as exc:
        LOGGER.warning("Assertion failed", exc=exc)
        raise ValidationError("Assertion failed") from exc

    device.set_sign_count(authentication_verification.new_sign_count)
    return device
Esempio n. 17
0
def _get_webauthn_user_public_keys(user, *, rp_id):
    return [
        (
            base64url_to_bytes(credential.public_key),
            credential.sign_count,
        )
        for credential in user.webauthn
    ]
Esempio n. 18
0
 def parse_raw(cls, payload_data: str):
     parsed: dict = json_loads_base64url_to_bytes(
         base64url_to_bytes(payload_data))
     return cls(
         nonce=parsed["nonce"],
         timestamp_ms=parsed["timestampMs"],
         apk_package_name=parsed["apkPackageName"],
         apk_digest_sha256=parsed["apkDigestSha256"],
         cts_profile_match=parsed["ctsProfileMatch"],
         apk_certificate_digest_sha256=parsed["apkCertificateDigestSha256"],
         basic_integrity=parsed["basicIntegrity"],
     )
    def test_can_parse_good_none_attestation_object(self) -> None:
        attestation_object = base64url_to_bytes(
            "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjESZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NFAAAAKwAAAAAAAAAAAAAAAAAAAAAAQBGidLzwQ3gFpfrQexcVIM1EKISJJUorv8HP1BQ-Km2G7Lw5VyGWRVG7pibkOG3OJ2LYG9tZY57jUrSjOqfEJgilAQIDJiABIVggBlNr3gyj0tq3QJrYd7t74BncruqqAVPCDlMfaU-7_kIiWCCXa5Oxqay8XoVwsTYzLSDp-ULUIAalnTyiQJrrrRWB_A"
        )

        output = parse_attestation_object(attestation_object)

        assert output.fmt == AttestationFormat.NONE
        # attestation statement
        att_stmt = output.att_stmt
        assert att_stmt.sig is None
        assert att_stmt.x5c is None
        assert att_stmt.response is None
        assert att_stmt.alg is None
        assert att_stmt.ver is None
        assert att_stmt.cert_info is None
        assert att_stmt.pub_area is None
        # authenticator data
        auth_data = output.auth_data
        assert auth_data.rp_id_hash == base64url_to_bytes(
            "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2M")
        assert auth_data.flags.up
        assert auth_data.flags.uv
        assert auth_data.flags.at
        assert not auth_data.flags.ed
        assert auth_data.sign_count == 43
        # attested credential data
        assert auth_data.attested_credential_data
        attested_cred_data = auth_data.attested_credential_data
        assert attested_cred_data.aaguid == base64url_to_bytes(
            "AAAAAAAAAAAAAAAAAAAAAA")
        assert attested_cred_data.credential_id == base64url_to_bytes(
            "EaJ0vPBDeAWl-tB7FxUgzUQohIklSiu_wc_UFD4qbYbsvDlXIZZFUbumJuQ4bc4nYtgb21ljnuNStKM6p8QmCA"
        )
        assert attested_cred_data.credential_public_key == base64url_to_bytes(
            "pQECAyYgASFYIAZTa94Mo9Lat0Ca2He7e-AZ3K7qqgFTwg5TH2lPu_5CIlggl2uTsamsvF6FcLE2My0g6flC1CAGpZ08okCa660Vgfw"
        )
        # extensions
        assert not auth_data.extensions
Esempio n. 20
0
    def test_supports_multiple_expected_origins(self) -> None:
        credential = AuthenticationCredential.parse_raw(
            """{
            "id": "AXmOjWWZH67pgl5_gAbKVBqoL2dyHHGEWZLspIsCwULG0hZ3HyuGgvkaRcSOLq9W72XtegcvFYXIdlafrilbtVnx2Q14gNbfSQQP2sgNEAif4MjHtGpeVB0BfFawCs85Y3XY_j4sxthVnyTY_Q",
            "rawId": "AXmOjWWZH67pgl5_gAbKVBqoL2dyHHGEWZLspIsCwULG0hZ3HyuGgvkaRcSOLq9W72XtegcvFYXIdlafrilbtVnx2Q14gNbfSQQP2sgNEAif4MjHtGpeVB0BfFawCs85Y3XY_j4sxthVnyTY_Q",
            "response": {
                "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFYN-Mog",
                "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiNnpyU1JYOEN4d1BTWEVBclh5WEwydHBiNnJCN1N0YXIwckxWSWo1cnZmNzRtWktGNWlyNzE1WG1nejV0QV9HeUhleE40b1hmclE4ODlBclZDTGFSZEEiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
                "signature": "MEUCIQDBqeI274exaKWGQz37g7yo1--TVcZSCcYVftZ1AnEJkQIgNw-nlx-_U9rVfFfER8oX6BlYZTuPFyGaL_wCDY23s0E",
                "userHandle": "TldNMFlqYzNOVFF0WW1NNE5DMDBaakprTFRrME9EVXROR05rTnpreVkyTTROVEUz"
            },
            "type": "public-key",
            "clientExtensionResults": {}
        }"""
        )

        challenge = base64url_to_bytes(
            "6zrSRX8CxwPSXEArXyXL2tpb6rB7Star0rLVIj5rvf74mZKF5ir715Xmgz5tA_GyHexN4oXfrQ889ArVCLaRdA"
        )
        expected_rp_id = "localhost"
        expected_origin = ["https://foo.bar", "http://localhost:5000"]
        credential_public_key = base64url_to_bytes(
            "pQECAyYgASFYIFm1Py-FzzFOuwXbRbTr95SiDxuB1BkZsEEJxFhquzqkIlggL1U1T713Jo_2muzhXvpbwRNdoAs8CYK6PflvY1MBdCI"
        )
        sign_count = 1625263263

        verification = verify_authentication_response(
            credential=credential,
            expected_challenge=challenge,
            expected_rp_id=expected_rp_id,
            expected_origin=expected_origin,
            credential_public_key=credential_public_key,
            credential_current_sign_count=sign_count,
        )

        assert verification.credential_id == base64url_to_bytes(
            "AXmOjWWZH67pgl5_gAbKVBqoL2dyHHGEWZLspIsCwULG0hZ3HyuGgvkaRcSOLq9W72XtegcvFYXIdlafrilbtVnx2Q14gNbfSQQP2sgNEAif4MjHtGpeVB0BfFawCs85Y3XY_j4sxthVnyTY_Q"
        )
Esempio n. 21
0
    def test_decode_rsa_public_key(self) -> None:
        decoded = decode_credential_public_key(
            base64url_to_bytes(
                "pAEDAzkBACBZAQDxfpXrj0ba_AH30JJ_-W7BHSOPugOD8aEDdNBKc1gjB9AmV3FPl2aL0fwiOMKtM_byI24qXb2FzcyjC7HUVkHRtzkAQnahXckI4wY_01koaY6iwXuIE3Ya0Zjs2iZyz6u4G_abGnWdObqa_kHxc3CHR7Xy5MDkAkKyX6TqU0tgHZcEhDd_Lb5ONJDwg4wvKlZBtZYElfMuZ6lonoRZ7qR_81rGkDZyFaxp6RlyvzEbo4ijeIaHQylqCz-oFm03ifZMOfRHYuF4uTjJDRH-g4BW1f3rdi7DTHk1hJnIw1IyL_VFIQ9NifkAguYjNCySCUNpYli2eMrPhAu5dYJFFjINIUMBAAE"
            ))

        assert isinstance(decoded, DecodedRSAPublicKey)
        assert decoded.kty == COSEKTY.RSA
        assert decoded.alg == COSEAlgorithmIdentifier.RSASSA_PKCS1_v1_5_SHA_256
        assert decoded.e and bytes_to_base64url(decoded.e) == "AQAB"
        assert (
            decoded.n and bytes_to_base64url(decoded.n) ==
            "8X6V649G2vwB99CSf_luwR0jj7oDg_GhA3TQSnNYIwfQJldxT5dmi9H8IjjCrTP28iNuKl29hc3Mowux1FZB0bc5AEJ2oV3JCOMGP9NZKGmOosF7iBN2GtGY7Nomcs-ruBv2mxp1nTm6mv5B8XNwh0e18uTA5AJCsl-k6lNLYB2XBIQ3fy2-TjSQ8IOMLypWQbWWBJXzLmepaJ6EWe6kf_NaxpA2chWsaekZcr8xG6OIo3iGh0Mpags_qBZtN4n2TDn0R2LheLk4yQ0R_oOAVtX963Yuw0x5NYSZyMNSMi_1RSEPTYn5AILmIzQskglDaWJYtnjKz4QLuXWCRRYyDQ"
        )
Esempio n. 22
0
    def test_decodes_ec2_public_key(self) -> None:
        decoded = decode_credential_public_key(
            base64url_to_bytes(
                "pQECAyYgASFYIDDHBDxTqWP4yZZnAa524L6uPuwhireUwRD5sXY6U2gxIlggxuwbECbDdNfTTegnc174oYdusZiMmJgct0yI_ulrJGI"
            ))

        assert isinstance(decoded, DecodedEC2PublicKey)
        assert decoded.kty == COSEKTY.EC2
        assert decoded.alg == COSEAlgorithmIdentifier.ECDSA_SHA_256
        assert decoded.crv == 1
        assert (decoded.x and bytes_to_base64url(decoded.x)
                == "MMcEPFOpY_jJlmcBrnbgvq4-7CGKt5TBEPmxdjpTaDE")
        assert (decoded.y and bytes_to_base64url(decoded.y)
                == "xuwbECbDdNfTTegnc174oYdusZiMmJgct0yI_ulrJGI")
Esempio n. 23
0
    def test_decode_uncompressed_ec2_public_key(self) -> None:
        decoded = decode_credential_public_key(
            base64url_to_bytes(
                "BBaxKZueVyr5ICDfosygxwRflSdPUcNheZhThXCeTFTNo0EM9dj0V+xJ1JwpE2XZ/8NRIt5KVvr71Zl0rB8BWOs="
            ))

        assert isinstance(decoded, DecodedEC2PublicKey)
        assert decoded.kty == COSEKTY.EC2
        assert decoded.alg == COSEAlgorithmIdentifier.ECDSA_SHA_256
        assert decoded.crv == 1
        assert (decoded.x and bytes_to_base64url(decoded.x)
                == "FrEpm55XKvkgIN-izKDHBF-VJ09Rw2F5mFOFcJ5MVM0")
        assert (decoded.y and bytes_to_base64url(decoded.y)
                == "o0EM9dj0V-xJ1JwpE2XZ_8NRIt5KVvr71Zl0rB8BWOs")
Esempio n. 24
0
    def test_verify_authentication_response_with_EC2_public_key(self):
        credential = AuthenticationCredential.parse_raw(
            """{
            "id": "EDx9FfAbp4obx6oll2oC4-CZuDidRVV4gZhxC529ytlnqHyqCStDUwfNdm1SNHAe3X5KvueWQdAX3x9R1a2b9Q",
            "rawId": "EDx9FfAbp4obx6oll2oC4-CZuDidRVV4gZhxC529ytlnqHyqCStDUwfNdm1SNHAe3X5KvueWQdAX3x9R1a2b9Q",
            "response": {
                "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAATg",
                "clientDataJSON": "eyJjaGFsbGVuZ2UiOiJ4aTMwR1BHQUZZUnhWRHBZMXNNMTBEYUx6VlFHNjZudi1fN1JVYXpIMHZJMll2RzhMWWdERW52TjVmWlpOVnV2RUR1TWk5dGUzVkxxYjQyTjBma0xHQSIsImNsaWVudEV4dGVuc2lvbnMiOnt9LCJoYXNoQWxnb3JpdGhtIjoiU0hBLTI1NiIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMCIsInR5cGUiOiJ3ZWJhdXRobi5nZXQifQ",
                "signature": "MEUCIGisVZOBapCWbnJJvjelIzwpixxIwkjCCb5aCHafQu68AiEA88v-2pJNNApPFwAKFiNuf82-2hBxYW5kGwVweeoxCwo"
            },
            "type": "public-key",
            "clientExtensionResults": {}
        }"""
        )
        challenge = base64url_to_bytes(
            "xi30GPGAFYRxVDpY1sM10DaLzVQG66nv-_7RUazH0vI2YvG8LYgDEnvN5fZZNVuvEDuMi9te3VLqb42N0fkLGA"
        )
        expected_rp_id = "localhost"
        expected_origin = "http://localhost:5000"
        credential_public_key = base64url_to_bytes(
            "pQECAyYgASFYIIeDTe-gN8A-zQclHoRnGFWN8ehM1b7yAsa8I8KIvmplIlgg4nFGT5px8o6gpPZZhO01wdy9crDSA_Ngtkx0vGpvPHI"
        )
        sign_count = 77

        verification = verify_authentication_response(
            credential=credential,
            expected_challenge=challenge,
            expected_rp_id=expected_rp_id,
            expected_origin=expected_origin,
            credential_public_key=credential_public_key,
            credential_current_sign_count=sign_count,
        )

        assert verification.credential_id == base64url_to_bytes(
            "EDx9FfAbp4obx6oll2oC4-CZuDidRVV4gZhxC529ytlnqHyqCStDUwfNdm1SNHAe3X5KvueWQdAX3x9R1a2b9Q"
        )
        assert verification.new_sign_count == 78
Esempio n. 25
0
    def test_raises_exception_on_incorrect_public_key(self):
        credential = AuthenticationCredential.parse_raw(
            """{
            "id": "FviUBZA3FGMxEm3A1K2T8MhuEBLp4qQsV9ScAKYrpdw2kbGnqx24tF4ev6PEHEYC3g8z6HMJh7dYHe3Uuq7_8Q",
            "rawId": "FviUBZA3FGMxEm3A1K2T8MhuEBLp4qQsV9ScAKYrpdw2kbGnqx24tF4ev6PEHEYC3g8z6HMJh7dYHe3Uuq7_8Q",
            "response": {
                "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAAJA",
                "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoienNmaU1aajE2VFVWQ3JUNXREUllYZFlsVXJKcDd6bl9VTmQ1Tm1Cb2NQYzRJMmRLWmJlRVdwd0JBd0E0czZvSGtWWDZfbHlfamdwNzQzZHlpV0hZWXciLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
                "signature": "MEQCIBX9B1LaLaQ0LYJsRv7cOyMS-Do1rJfFJoF9oO1tHMA4AiBRKdNneMKPlN53i8uoTZ5y9Gj4ORZySmiercS38655_g"
            },
            "type": "public-key",
            "clientExtensionResults": {}
        }"""
        )
        challenge = base64url_to_bytes(
            "zsfiMZj16TUVCrT5tDRYXdYlUrJp7zn_UNd5NmBocPc4I2dKZbeEWpwBAwA4s6oHkVX6_ly_jgp743dyiWHYYw"
        )
        expected_rp_id = "localhost"
        expected_origin = "http://localhost:5000"
        credential_public_key = base64url_to_bytes(
            "pAEDAzkBACBZAQDfV20epzvQP-HtcdDpX-cGzdOxy73WQEvsU7Dnr9UWJophEfpngouvgnRLXaEUn_d8HGkp_HIx8rrpkx4BVs6X_B6ZjhLlezjIdJbLbVeb92BaEsmNn1HW2N9Xj2QM8cH-yx28_vCjf82ahQ9gyAr552Bn96G22n8jqFRQKdVpO-f-bvpvaP3IQ9F5LCX7CUaxptgbog1SFO6FI6ob5SlVVB00lVXsaYg8cIDZxCkkENkGiFPgwEaZ7995SCbiyCpUJbMqToLMgojPkAhWeyktu7TlK6UBWdJMHc3FPAIs0lH_2_2hKS-mGI1uZAFVAfW1X-mzKL0czUm2P1UlUox7IUMBAAE"
        )
        sign_count = 35

        with self.assertRaisesRegex(
            InvalidAuthenticationResponse,
            "Could not verify authentication signature",
        ):
            verify_authentication_response(
                credential=credential,
                expected_challenge=challenge,
                expected_rp_id=expected_rp_id,
                expected_origin=expected_origin,
                credential_public_key=credential_public_key,
                credential_current_sign_count=sign_count,
                require_user_verification=True,
            )
Esempio n. 26
0
    def test_raises_exception_on_uv_required_but_false(self):
        credential = AuthenticationCredential.parse_raw(
            """{
            "id": "4-5MZF69j3n2B6Z99dUN0fNrAQmrjELJIebWVw8aKfw1EQKg28Tx40R_kw-1pcrfSgJFKm3mCtAtBgSRWgDMng",
            "rawId": "4-5MZF69j3n2B6Z99dUN0fNrAQmrjELJIebWVw8aKfw1EQKg28Tx40R_kw-1pcrfSgJFKm3mCtAtBgSRWgDMng",
            "response": {
                "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAIQ",
                "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoidW1HZW1YSklQQlhQeGtEOEhqYW51djlCRG9yOFo3TzNhUGR0T2dNQ2RXNFBBZnFEWDQzRUZsaHJzRjBQVzkwZGY1enJnYnQ3WVZNUkFhMjd0Q2RIenciLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
                "signature": "MEUCIGp5ADnU_SFvT4J_bKvQJ4Pc1GmANhbYq5GioOLjyUrxAiEA6Kk5qAZb8MLY-jyTiJLr_R9Fke02UHkxsRB0dnZt2X8"
            },
            "type": "public-key",
            "clientExtensionResults": {}
        }"""
        )
        challenge = base64url_to_bytes(
            "umGemXJIPBXPxkD8Hjanuv9BDor8Z7O3aPdtOgMCdW4PAfqDX43EFlhrsF0PW90df5zrgbt7YVMRAa27tCdHzw"
        )
        expected_rp_id = "localhost"
        expected_origin = "http://localhost:5000"
        credential_public_key = base64url_to_bytes(
            "pQECAyYgASFYIOQ5TKpXJR2cV76Wgfge9BkLkEhLxVjhFjM1jKHYOcqpIlggaiNy1blt3OU8Hsmg041HUYP7eajgL7fk3nSuTEjYCwU"
        )
        sign_count = 32

        with self.assertRaisesRegex(
            InvalidAuthenticationResponse,
            "User verification is required but user was not verified",
        ):
            verify_authentication_response(
                credential=credential,
                expected_challenge=challenge,
                expected_rp_id=expected_rp_id,
                expected_origin=expected_origin,
                credential_public_key=credential_public_key,
                credential_current_sign_count=sign_count,
                require_user_verification=True,
            )
Esempio n. 27
0
    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"
        )
Esempio n. 28
0
    def test_verify_authentication_response_with_RSA_public_key(self):
        credential = AuthenticationCredential.parse_raw(
            """{
                "id": "ZoIKP1JQvKdrYj1bTUPJ2eTUsbLeFkv-X5xJQNr4k6s",
                "rawId": "ZoIKP1JQvKdrYj1bTUPJ2eTUsbLeFkv-X5xJQNr4k6s",
                "response": {
                    "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAAAQ",
                    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiaVBtQWkxUHAxWEw2b0FncTNQV1p0WlBuWmExekZVRG9HYmFRMF9LdlZHMWxGMnMzUnRfM280dVN6Y2N5MHRtY1RJcFRUVDRCVTFULUk0bWFhdm5kalEiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
                    "signature": "iOHKX3erU5_OYP_r_9HLZ-CexCE4bQRrxM8WmuoKTDdhAnZSeTP0sjECjvjfeS8MJzN1ArmvV0H0C3yy_FdRFfcpUPZzdZ7bBcmPh1XPdxRwY747OrIzcTLTFQUPdn1U-izCZtP_78VGw9pCpdMsv4CUzZdJbEcRtQuRS03qUjqDaovoJhOqEBmxJn9Wu8tBi_Qx7A33RbYjlfyLm_EDqimzDZhyietyop6XUcpKarKqVH0M6mMrM5zTjp8xf3W7odFCadXEJg-ERZqFM0-9Uup6kJNLbr6C5J4NDYmSm3HCSA6lp2iEiMPKU8Ii7QZ61kybXLxsX4w4Dm3fOLjmDw",
                    "userHandle": "T1RWa1l6VXdPRFV0WW1NNVlTMDBOVEkxTFRnd056Z3RabVZpWVdZNFpEVm1ZMk5p"
                },
                "type": "public-key",
                "clientExtensionResults": {}
            }"""
        )
        challenge = base64url_to_bytes(
            "iPmAi1Pp1XL6oAgq3PWZtZPnZa1zFUDoGbaQ0_KvVG1lF2s3Rt_3o4uSzccy0tmcTIpTTT4BU1T-I4maavndjQ"
        )
        expected_rp_id = "localhost"
        expected_origin = "http://localhost:5000"
        credential_public_key = base64url_to_bytes(
            "pAEDAzkBACBZAQDfV20epzvQP-HtcdDpX-cGzdOxy73WQEvsU7Dnr9UWJophEfpngouvgnRLXaEUn_d8HGkp_HIx8rrpkx4BVs6X_B6ZjhLlezjIdJbLbVeb92BaEsmNn1HW2N9Xj2QM8cH-yx28_vCjf82ahQ9gyAr552Bn96G22n8jqFRQKdVpO-f-bvpvaP3IQ9F5LCX7CUaxptgbog1SFO6FI6ob5SlVVB00lVXsaYg8cIDZxCkkENkGiFPgwEaZ7995SCbiyCpUJbMqToLMgojPkAhWeyktu7TlK6UBWdJMHc3FPAIs0lH_2_2hKS-mGI1uZAFVAfW1X-mzKL0czUm2P1UlUox7IUMBAAE"
        )
        sign_count = 0

        verification = verify_authentication_response(
            credential=credential,
            expected_challenge=challenge,
            expected_rp_id=expected_rp_id,
            expected_origin=expected_origin,
            credential_public_key=credential_public_key,
            credential_current_sign_count=sign_count,
            require_user_verification=True,
        )

        assert verification.new_sign_count == 1
Esempio n. 29
0
def _get_webauthn_user_public_key_credential_descriptors(user, *, rp_id):
    """
    Returns a webauthn.WebAuthnUser instance corresponding
    to the given user model, with properties suitable for
    usage within the webauthn API.
    """
    return [
        PublicKeyCredentialDescriptor(
            id=base64url_to_bytes(credential.credential_id),
            transports=[
                AuthenticatorTransport.USB,
                AuthenticatorTransport.NFC,
                AuthenticatorTransport.BLE,
                AuthenticatorTransport.INTERNAL,
            ],
        )
        for credential in user.webauthn
    ]
    def test_can_parse_good_packed_attestation_object(self) -> None:
        attestation_object = base64url_to_bytes(
            "o2NmbXRmcGFja2VkZ2F0dFN0bXSjY2FsZyZjc2lnWEcwRQIgRpuZ6hdaLAgWgCFTIo4BGSTBAxwwqk4u3s1-JAzv_H4CIQCZnfoic34aOwlac1A09eflEtb0V1kO7yGhHOw5P5wVWmN4NWOBWQLBMIICvTCCAaWgAwIBAgIEKudiYzANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbjELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEnMCUGA1UEAwweWXViaWNvIFUyRiBFRSBTZXJpYWwgNzE5ODA3MDc1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKgOGXmBD2Z4R_xCqJVRXhL8Jr45rHjsyFykhb1USGozZENOZ3cdovf5Ke8fj2rxi5tJGn_VnW4_6iQzKdIaeP6NsMGowIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjEwEwYLKwYBBAGC5RwCAQEEBAMCBDAwIQYLKwYBBAGC5RwBAQQEEgQQbUS6m_bsLkm5MAyP6SDLczAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQByV9A83MPhFWmEkNb4DvlbUwcjc9nmRzJjKxHc3HeK7GvVkm0H4XucVDB4jeMvTke0WHb_jFUiApvpOHh5VyMx5ydwFoKKcRs5x0_WwSWL0eTZ5WbVcHkDR9pSNcA_D_5AsUKOBcbpF5nkdVRxaQHuuIuwV4k1iK2IqtMNcU8vL6w21U261xCcWwJ6sMq4zzVO8QCKCQhsoIaWrwz828GDmPzfAjFsJiLJXuYivdHACkeJ5KHMt0mjVLpfJ2BCML7_rgbmvwL7wBW80VHfNdcKmKjkLcpEiPzwcQQhiN_qHV90t-p4iyr5xRSpurlP5zic2hlRkLKxMH2_kRjhqSn4aGF1dGhEYXRhWMRJlg3liA6MaHQ0Fw9kdmBbj-SuuaKGMseZXPO6gx2XY0UAAAAqbUS6m_bsLkm5MAyP6SDLcwBAFsWBrFcw8yRjxV8z18Egh91o1AScNRYkIuUoY6wIlIhslDpP7eydKi1q5s9g1ugDP9mqBlPDDFPRbH6YLwHbtqUBAgMmIAEhWCAq3y0RWh8nLzanBZQwTA7yAbUy9KEDAM0b3N9Elrb0VCJYIJrX7ygtpyInb5mXBE7g9YEow6xWrJ400HhL2r4q5tzV",
        )

        output = parse_attestation_object(attestation_object)

        assert output.fmt == AttestationFormat.PACKED
        # attestation statement
        att_stmt = output.att_stmt
        assert att_stmt.sig and att_stmt.sig == base64url_to_bytes(
            "MEUCIEabmeoXWiwIFoAhUyKOARkkwQMcMKpOLt7NfiQM7_x-AiEAmZ36InN-GjsJWnNQNPXn5RLW9FdZDu8hoRzsOT-cFVo"
        )
        assert att_stmt.x5c and len(att_stmt.x5c) == 1
        assert att_stmt.response is None
        assert att_stmt.alg == COSEAlgorithmIdentifier.ECDSA_SHA_256
        assert att_stmt.ver is None
        assert att_stmt.cert_info is None
        assert att_stmt.pub_area is None
        # authenticator data
        auth_data = output.auth_data
        assert auth_data.rp_id_hash == base64url_to_bytes(
            "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2M")
        assert auth_data.flags.up
        assert auth_data.flags.uv
        assert auth_data.flags.at
        assert not auth_data.flags.ed
        assert auth_data.sign_count == 42
        # attested credential data
        assert auth_data.attested_credential_data
        attested_cred_data = auth_data.attested_credential_data
        assert attested_cred_data.aaguid == base64url_to_bytes(
            "bUS6m_bsLkm5MAyP6SDLcw")
        assert attested_cred_data.credential_id == base64url_to_bytes(
            "FsWBrFcw8yRjxV8z18Egh91o1AScNRYkIuUoY6wIlIhslDpP7eydKi1q5s9g1ugDP9mqBlPDDFPRbH6YLwHbtg"
        )
        assert attested_cred_data.credential_public_key == base64url_to_bytes(
            "pQECAyYgASFYICrfLRFaHycvNqcFlDBMDvIBtTL0oQMAzRvc30SWtvRUIlggmtfvKC2nIidvmZcETuD1gSjDrFasnjTQeEvavirm3NU"
        )
        # extensions
        assert auth_data.extensions is None