def test_parse_bytes_get_assertion(self): data = AuthenticatorData(_AUTH_DATA_GA) self.assertEqual(data.rp_id_hash, _RP_ID_HASH) self.assertEqual(data.flags, 0x01) self.assertEqual(data.counter, 29) self.assertIsNone(data.credential_data) self.assertIsNone(data.extensions)
def test_apple_attestation(self): attestation = Attestation.for_type("apple")() self.assertIsInstance(attestation, AppleAttestation) statement = { "alg": -7, "x5c": [ bytes.fromhex( "30820242308201c9a00302010202060176af5359ff300a06082a8648ce3d0403023048311c301a06035504030c134170706c6520576562417574686e204341203131133011060355040a0c0a4170706c6520496e632e3113301106035504080c0a43616c69666f726e6961301e170d3230313232383136323732345a170d3230313233313136323732345a3081913149304706035504030c4038303966626331313065613835663233613862323435616563363136333530663337646665393632313232373336653431663862646365663334366138306439311a3018060355040b0c114141412043657274696669636174696f6e31133011060355040a0c0a4170706c6520496e632e3113301106035504080c0a43616c69666f726e69613059301306072a8648ce3d020106082a8648ce3d030107034200041f46a2f159fde354598cdd47e005f1b6e7c9f00ed2a941ec7a88d222f5bcf55d6b078bc5b0be9552d85a974921f5bb848e2bbc3aecd6f71a386d2c87d6eafd37a3553053300c0603551d130101ff04023000300e0603551d0f0101ff0404030204f0303306092a864886f76364080204263024a1220420e56fb6212b3aae885294464fb10184b7fea62c48a6d78e61194e07ae6dacc132300a06082a8648ce3d040302036700306402301de8f0f238eee4f5ae80c59290b51e8c3f79397bf198e444ba162d4fccaab8558b072cf00a7c662f9058ff2a98af61ae0230149403b9643066e73a98d3659563dc4da49bf84e82b2b5bbeaf57755646fa243f36344d44b80a5798203bca023e030c7" # noqa E501 ), bytes.fromhex( "30820234308201baa003020102021056255395c7a7fb40ebe228d8260853b6300a06082a8648ce3d040303304b311f301d06035504030c164170706c6520576562417574686e20526f6f7420434131133011060355040a0c0a4170706c6520496e632e3113301106035504080c0a43616c69666f726e6961301e170d3230303331383138333830315a170d3330303331333030303030305a3048311c301a06035504030c134170706c6520576562417574686e204341203131133011060355040a0c0a4170706c6520496e632e3113301106035504080c0a43616c69666f726e69613076301006072a8648ce3d020106052b8104002203620004832e872f261491810225b9f5fcd6bb6378b5f55f3fcb045bc735993475fd549044df9bfe19211765c69a1dda050b38d45083401a434fb24d112d56c3e1cfbfcb9891fec0696081bef96cbc77c88dddaf46a5aee1dd515b5afaab93be9c0b2691a366306430120603551d130101ff040830060101ff020100301f0603551d2304183016801426d764d9c578c25a67d1a7de6b12d01b63f1c6d7301d0603551d0e04160414ebae82c4ffa1ac5b51d4cf24610500be63bd7788300e0603551d0f0101ff040403020106300a06082a8648ce3d0403030368003065023100dd8b1a3481a5fad9dbb4e7657b841e144c27b75b876a4186c2b1475750337227efe554457ef648950c632e5c483e70c102302c8a6044dc201fcfe59bc34d2930c1487851d960ed6a75f1eb4acabe38cd25b897d0c805bef0c7f78b07a571c6e80e07" # noqa E501 ), ], } auth_data = AuthenticatorData( bytes.fromhex( "c46cef82ad1b546477591d008b08759ec3e6d2ecb4f39474bfea6969925d03b7450000000000000000000000000000000000000000001473d9429f4052d84debd035eb5bb7e716e3b81863a50102032620012158201f46a2f159fde354598cdd47e005f1b6e7c9f00ed2a941ec7a88d222f5bcf55d2258206b078bc5b0be9552d85a974921f5bb848e2bbc3aecd6f71a386d2c87d6eafd37" # noqa E501 )) client_param = bytes.fromhex( "0d3ce80fabbc3adb9dd891deabb8db84603ea1fe2da8b5d4b46d6591aab342f3") res = attestation.verify(statement, auth_data, client_param) self.assertEqual(res.attestation_type, AttestationType.ANON_CA) self.assertEqual(len(res.trust_path), 2) verify_x509_chain(res.trust_path)
def test_parse_bytes_make_credential(self): data = AuthenticatorData(_AUTH_DATA_MC) self.assertEqual(data.rp_id_hash, _RP_ID_HASH) self.assertEqual(data.flags, 0x41) self.assertEqual(data.counter, 28) self.assertEqual(data.credential_data, _ATT_CRED_DATA) self.assertIsNone(data.extensions)
def test_authenticate_complete_invalid_signature(self): rp = PublicKeyCredentialRpEntity("Example", "example.com") server = Fido2Server(rp) state = { "challenge": "GAZPACHO!", "user_verification": UserVerificationRequirement.PREFERRED, } client_data = CollectedClientData.create( CollectedClientData.TYPE.GET, "GAZPACHO!", "https://example.com", ) _AUTH_DATA = bytes.fromhex( "A379A6F6EEAFB9A55E378C118034E2751E682FAB9F2D30AB13D2125586CE1947010000001D" ) with self.assertRaisesRegex(ValueError, "Invalid signature."): server.authenticate_complete( state, [AttestedCredentialData(_ATT_CRED_DATA)], _CRED_ID, client_data, AuthenticatorData(_AUTH_DATA), b"INVALID", )
def test_packed_attestation(self): attestation = Attestation.for_type("packed")() self.assertIsInstance(attestation, PackedAttestation) statement = { "alg": -7, "sig": bytes.fromhex( "304502200D15DAF337D727AB4719B4027114A2AC43CD565D394CED62C3D9D1D90825F0B3022100989615E7394C87F4AD91F8FDAE86F7A3326DF332B3633DB088AAC76BFFB9A46B" # noqa E501 ), "x5c": [ bytes.fromhex( "308202B73082019FA00302010202041D31330D300D06092A864886F70D01010B0500302A3128302606035504030C1F59756269636F2050726576696577204649444F204174746573746174696F6E301E170D3138303332383036333932345A170D3139303332383036333932345A306E310B300906035504061302534531123010060355040A0C0959756269636F20414231223020060355040B0C1941757468656E74696361746F72204174746573746174696F6E3127302506035504030C1E59756269636F205532462045452053657269616C203438393736333539373059301306072A8648CE3D020106082A8648CE3D030107034200047D71E8367CAFD0EA6CF0D61E4C6A416BA5BB6D8FAD52DB2389AD07969F0F463BFDDDDDC29D39D3199163EE49575A3336C04B3309D607F6160C81E023373E0197A36C306A302206092B0601040182C40A020415312E332E362E312E342E312E34313438322E312E323013060B2B0601040182E51C0201010404030204303021060B2B0601040182E51C01010404120410F8A011F38C0A4D15800617111F9EDC7D300C0603551D130101FF04023000300D06092A864886F70D01010B050003820101009B904CEADBE1F1985486FEAD02BAEAA77E5AB4E6E52B7E6A2666A4DC06E241578169193B63DADEC5B2B78605A128B2E03F7FE2A98EAEB4219F52220995F400CE15D630CF0598BA662D7162459F1AD1FC623067376D4E4091BE65AC1A33D8561B9996C0529EC1816D1710786384D5E8783AA1F7474CB99FE8F5A63A79FF454380361C299D67CB5CC7C79F0D8C09F8849B0500F6D625408C77CBBC26DDEE11CB581BEB7947137AD4F05AAF38BD98DA10042DDCAC277604A395A5B3EAA88A5C8BB27AB59C8127D59D6BBBA5F11506BF7B75FDA7561A0837C46F025FD54DCF1014FC8D17C859507AC57D4B1DEA99485DF0BA8F34D00103C3EEF2EF3BBFEC7A6613DE" # noqa E501 ) ], } auth_data = AuthenticatorData( bytes.fromhex( "0021F5FC0B85CD22E60623BCD7D1CA48948909249B4776EB515154E57B66AE124100000003F8A011F38C0A4D15800617111F9EDC7D004060A386206A3AACECBDBB22D601853D955FDC5D11ADFBD1AA6A950D966B348C7663D40173714A9F987DF6461BEADFB9CD6419FFDFE4D4CF2EEC1AA605A4F59BDAA50102032620012158200EDB27580389494D74D2373B8F8C2E8B76FA135946D4F30D0E187E120B423349225820E03400D189E85A55DE9AB0F538ED60736EB750F5F0306A80060FE1B13010560D" # noqa E501 )) client_param = bytes.fromhex( "985B6187D042FB1258892ED637CEC88617DDF5F6632351A545617AA2B75261BF") res = attestation.verify(statement, auth_data, client_param) self.assertEqual(res.attestation_type, AttestationType.BASIC) self.assertEqual(len(res.trust_path), 1) statement["sig"] = b"a" * len(statement["sig"]) with self.assertRaises(InvalidSignature): attestation.verify(statement, auth_data, client_param)
def test_fido_u2f_attestation(self): attestation = Attestation.for_type("fido-u2f")() self.assertIsInstance(attestation, FidoU2FAttestation) statement = { "sig": bytes.fromhex( "30450220324779C68F3380288A1197B6095F7A6EB9B1B1C127F66AE12A99FE8532EC23B9022100E39516AC4D61EE64044D50B415A6A4D4D84BA6D895CB5AB7A1AA7D081DE341FA" # noqa E501 ), "x5c": [ bytes.fromhex( "3082024A30820132A0030201020204046C8822300D06092A864886F70D01010B0500302E312C302A0603550403132359756269636F2055324620526F6F742043412053657269616C203435373230303633313020170D3134303830313030303030305A180F32303530303930343030303030305A302C312A302806035504030C2159756269636F205532462045452053657269616C203234393138323332343737303059301306072A8648CE3D020106082A8648CE3D030107034200043CCAB92CCB97287EE8E639437E21FCD6B6F165B2D5A3F3DB131D31C16B742BB476D8D1E99080EB546C9BBDF556E6210FD42785899E78CC589EBE310F6CDB9FF4A33B3039302206092B0601040182C40A020415312E332E362E312E342E312E34313438322E312E323013060B2B0601040182E51C020101040403020430300D06092A864886F70D01010B050003820101009F9B052248BC4CF42CC5991FCAABAC9B651BBE5BDCDC8EF0AD2C1C1FFB36D18715D42E78B249224F92C7E6E7A05C49F0E7E4C881BF2E94F45E4A21833D7456851D0F6C145A29540C874F3092C934B43D222B8962C0F410CEF1DB75892AF116B44A96F5D35ADEA3822FC7146F6004385BCB69B65C99E7EB6919786703C0D8CD41E8F75CCA44AA8AB725AD8E799FF3A8696A6F1B2656E631B1E40183C08FDA53FA4A8F85A05693944AE179A1339D002D15CABD810090EC722EF5DEF9965A371D415D624B68A2707CAD97BCDD1785AF97E258F33DF56A031AA0356D8E8D5EBCADC74E071636C6B110ACE5CC9B90DFEACAE640FF1BB0F1FE5DB4EFF7A95F060733F5" # noqa E501 ) ], } auth_data = AuthenticatorData( bytes.fromhex( "1194228DA8FDBDEEFD261BD7B6595CFD70A50D70C6407BCF013DE96D4EFB17DE41000000000000000000000000000000000000000000403EBD89BF77EC509755EE9C2635EFAAAC7B2B9C5CEF1736C3717DA48534C8C6B654D7FF945F50B5CC4E78055BDD396B64F78DA2C5F96200CCD415CD08FE420038A5010203262001215820E87625896EE4E46DC032766E8087962F36DF9DFE8B567F3763015B1990A60E1422582027DE612D66418BDA1950581EBC5C8C1DAD710CB14C22F8C97045F4612FB20C91" # noqa E501 )) client_param = bytes.fromhex( "687134968222EC17202E42505F8ED2B16AE22F16BB05B88C25DB9E602645F141") res = attestation.verify(statement, auth_data, client_param) self.assertEqual(res.attestation_type, AttestationType.BASIC) self.assertEqual(len(res.trust_path), 1) statement["sig"] = b"a" * len(statement["sig"]) with self.assertRaises(InvalidSignature): attestation.verify(statement, auth_data, client_param)
def sign(self, client_data): authenticator_data = AuthenticatorData.create( sha256(self.app_id), flags=AuthenticatorData.FLAG.USER_PRESENT, counter=0 ) signature = self.priv_key.sign( authenticator_data + client_data.hash, ec.ECDSA(hashes.SHA256()) ) return authenticator_data, signature
def test_none_windows_hello_attestation(self): attestation = Attestation.for_type("none")() self.assertIsInstance(attestation, NoneAttestation) auth_data = AuthenticatorData( bytes.fromhex( "54ce651ed715b4aaa755eecebd4ea0950815b334bd07d109893e963018cddbd945000000006028b017b1d44c02b4b3afcdafc96bb200201decfcd6d6a05c2826d52348afdc70a9800df007845047b1a23706aa6e2f315ca401030339010020590100af59f4ad4f71da800bb91045b267e240e06317f7b2b1d76f78e239a433811faeca58a1869fb00225eb2727f81b6b20cbc18c0ad8d38fa450e8df11b4ad3bc3ee5d13c77ed172fa3af0195ec6ac0c4bac8c950115dfce6d38737cbafefbe117d8401cd56c638043a0d585131bc48a153b17a8dcb96671e15a90ba1b4ff810b138b77ac0a050b039b87b6089dd8dfa45611b992109d554aad3e6b72ac82d801496e4d2d230aa466090bbbf4f5632fe4b588e4f571462378fa6f514a536a5945b223c8d98f730b7cf85de86b98c217090f9e9ebf9643cf3feceeacb837d7a18542e03271cd8c70cf81186cdb63e4cbf4efc0cbbd3c93231b06f19580d0a980264d12143010001" # noqa )) # noqa res = attestation.verify({}, auth_data, b"deadbeef" * 8) self.assertEqual(res.attestation_type, AttestationType.NONE) self.assertEqual(res.trust_path, []) with self.assertRaises(InvalidData): attestation.verify({"not": "empty"}, auth_data, b"deadbeef" * 8)
def test_none_attestation(self): attestation = Attestation.for_type("none")() self.assertIsInstance(attestation, NoneAttestation) auth_data = AuthenticatorData( bytes.fromhex( "0021F5FC0B85CD22E60623BCD7D1CA48948909249B4776EB515154E57B66AE12410000002BF8A011F38C0A4D15800617111F9EDC7D0040A17370D9C1759005700C8DE77E7DFD3A0A5300E0A26E5213AA40D6DF10EE4028B58B5F34167035D840BEBAE0C5CE8FD05AD9BD33E3BE7D1C558D81AB4803570BA5010203262001215820A5FD5CE1B1C458C530A54FA61B31BF6B04BE8B97AFDE54DD8CBB69275A8A1BE1225820FA3A3231DD9DEED9D1897BE5A6228C59501E4BCD12975D3DFF730F01278EA61C" # noqa E501 )) res = attestation.verify({}, auth_data, b"deadbeef" * 8) self.assertEqual(res.attestation_type, AttestationType.NONE) self.assertEqual(res.trust_path, []) with self.assertRaises(InvalidData): attestation.verify({"not": "empty"}, auth_data, b"deadbeef" * 8)
def test_android_safetynet_attestation(self): attestation = Attestation.for_type("android-safetynet")() self.assertIsInstance(attestation, AndroidSafetynetAttestation) statement = { "ver": "14574037", "response": b"eyJhbGciOiJSUzI1NiIsIng1YyI6WyJNSUlGa2pDQ0JIcWdBd0lCQWdJUVJYcm9OMFpPZFJrQkFBQUFBQVB1bnpBTkJna3Foa2lHOXcwQkFRc0ZBREJDTVFzd0NRWURWUVFHRXdKVlV6RWVNQndHQTFVRUNoTVZSMjl2WjJ4bElGUnlkWE4wSUZObGNuWnBZMlZ6TVJNd0VRWURWUVFERXdwSFZGTWdRMEVnTVU4eE1CNFhEVEU0TVRBeE1EQTNNVGswTlZvWERURTVNVEF3T1RBM01UazBOVm93YkRFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDa05oYkdsbWIzSnVhV0V4RmpBVUJnTlZCQWNURFUxdmRXNTBZV2x1SUZacFpYY3hFekFSQmdOVkJBb1RDa2R2YjJkc1pTQk1URU14R3pBWkJnTlZCQU1URW1GMGRHVnpkQzVoYm1SeWIybGtMbU52YlRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTmpYa3owZUsxU0U0bSsvRzV3T28rWEdTRUNycWRuODhzQ3BSN2ZzMTRmSzBSaDNaQ1laTEZIcUJrNkFtWlZ3Mks5RkcwTzlyUlBlUURJVlJ5RTMwUXVuUzl1Z0hDNGVnOW92dk9tK1FkWjJwOTNYaHp1blFFaFVXWEN4QURJRUdKSzNTMmFBZnplOTlQTFMyOWhMY1F1WVhIRGFDN09acU5ub3NpT0dpZnM4djFqaTZIL3hobHRDWmUybEorN0d1dHpleEtweHZwRS90WlNmYlk5MDVxU2xCaDlmcGowMTVjam5RRmtVc0FVd21LVkFVdWVVejR0S2NGSzRwZXZOTGF4RUFsK09raWxNdElZRGFjRDVuZWw0eEppeXM0MTNoYWdxVzBXaGg1RlAzOWhHazlFL0J3UVRqYXpTeEdkdlgwbTZ4RlloaC8yVk15WmpUNEt6UEpFQ0F3RUFBYU9DQWxnd2dnSlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBVEFNQmdOVkhSTUJBZjhFQWpBQU1CMEdBMVVkRGdRV0JCUXFCUXdHV29KQmExb1RLcXVwbzRXNnhUNmoyREFmQmdOVkhTTUVHREFXZ0JTWTBmaHVFT3ZQbSt4Z254aVFHNkRyZlFuOUt6QmtCZ2dyQmdFRkJRY0JBUVJZTUZZd0p3WUlLd1lCQlFVSE1BR0dHMmgwZEhBNkx5OXZZM053TG5CcmFTNW5iMjluTDJkMGN6RnZNVEFyQmdnckJnRUZCUWN3QW9ZZmFIUjBjRG92TDNCcmFTNW5iMjluTDJkemNqSXZSMVJUTVU4eExtTnlkREFkQmdOVkhSRUVGakFVZ2hKaGRIUmxjM1F1WVc1a2NtOXBaQzVqYjIwd0lRWURWUjBnQkJvd0dEQUlCZ1puZ1F3QkFnSXdEQVlLS3dZQkJBSFdlUUlGQXpBdkJnTlZIUjhFS0RBbU1DU2dJcUFnaGg1b2RIUndPaTh2WTNKc0xuQnJhUzVuYjI5bkwwZFVVekZQTVM1amNtd3dnZ0VFQmdvckJnRUVBZFo1QWdRQ0JJSDFCSUh5QVBBQWR3Q2t1UW1RdEJoWUZJZTdFNkxNWjNBS1BEV1lCUGtiMzdqamQ4ME95QTNjRUFBQUFXWmREM1BMQUFBRUF3QklNRVlDSVFDU1pDV2VMSnZzaVZXNkNnK2dqLzl3WVRKUnp1NEhpcWU0ZVk0Yy9teXpqZ0loQUxTYmkvVGh6Y3pxdGlqM2RrM3ZiTGNJVzNMbDJCMG83NUdRZGhNaWdiQmdBSFVBVmhRR21pL1h3dXpUOWVHOVJMSSt4MFoydWJ5WkVWekE3NVNZVmRhSjBOMEFBQUZtWFE5ejVBQUFCQU1BUmpCRUFpQmNDd0E5ajdOVEdYUDI3OHo0aHIvdUNIaUFGTHlvQ3EySzAreUxSd0pVYmdJZ2Y4Z0hqdnB3Mm1CMUVTanEyT2YzQTBBRUF3Q2tuQ2FFS0ZVeVo3Zi9RdEl3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUk5blRmUktJV2d0bFdsM3dCTDU1RVRWNmthenNwaFcxeUFjNUR1bTZYTzQxa1p6d0o2MXdKbWRSUlQvVXNDSXkxS0V0MmMwRWpnbG5KQ0YyZWF3Y0VXbExRWTJYUEx5RmprV1FOYlNoQjFpNFcyTlJHelBodDNtMWI0OWhic3R1WE02dFg1Q3lFSG5UaDhCb200L1dsRmloemhnbjgxRGxkb2d6L0syVXdNNlM2Q0IvU0V4a2lWZnYremJKMHJqdmc5NEFsZGpVZlV3a0k5Vk5NakVQNWU4eWRCM29MbDZnbHBDZUY1ZGdmU1g0VTl4MzVvai9JSWQzVUUvZFBwYi9xZ0d2c2tmZGV6dG1VdGUvS1Ntcml3Y2dVV1dlWGZUYkkzenNpa3daYmtwbVJZS21qUG1odjRybGl6R0NHdDhQbjhwcThNMktEZi9QM2tWb3QzZTE4UT0iLCJNSUlFU2pDQ0F6S2dBd0lCQWdJTkFlTzBtcUdOaXFtQkpXbFF1REFOQmdrcWhraUc5dzBCQVFzRkFEQk1NU0F3SGdZRFZRUUxFeGRIYkc5aVlXeFRhV2R1SUZKdmIzUWdRMEVnTFNCU01qRVRNQkVHQTFVRUNoTUtSMnh2WW1Gc1UybG5iakVUTUJFR0ExVUVBeE1LUjJ4dlltRnNVMmxuYmpBZUZ3MHhOekEyTVRVd01EQXdOREphRncweU1URXlNVFV3TURBd05ESmFNRUl4Q3pBSkJnTlZCQVlUQWxWVE1SNHdIQVlEVlFRS0V4VkhiMjluYkdVZ1ZISjFjM1FnVTJWeWRtbGpaWE14RXpBUkJnTlZCQU1UQ2tkVVV5QkRRU0F4VHpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURRR005RjFJdk4wNXprUU85K3ROMXBJUnZKenp5T1RIVzVEekVaaEQyZVBDbnZVQTBRazI4RmdJQ2ZLcUM5RWtzQzRUMmZXQllrL2pDZkMzUjNWWk1kUy9kTjRaS0NFUFpSckF6RHNpS1VEelJybUJCSjV3dWRnem5kSU1ZY0xlL1JHR0ZsNXlPRElLZ2pFdi9TSkgvVUwrZEVhbHROMTFCbXNLK2VRbU1GKytBY3hHTmhyNTlxTS85aWw3MUkyZE44RkdmY2Rkd3VhZWo0YlhocDBMY1FCYmp4TWNJN0pQMGFNM1Q0SStEc2F4bUtGc2JqemFUTkM5dXpwRmxnT0lnN3JSMjV4b3luVXh2OHZObWtxN3pkUEdIWGt4V1k3b0c5aitKa1J5QkFCazdYckpmb3VjQlpFcUZKSlNQazdYQTBMS1cwWTN6NW96MkQwYzF0Skt3SEFnTUJBQUdqZ2dFek1JSUJMekFPQmdOVkhROEJBZjhFQkFNQ0FZWXdIUVlEVlIwbEJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0hRWURWUjBPQkJZRUZKalIrRzRRNjgrYjdHQ2ZHSkFib090OUNmMHJNQjhHQTFVZEl3UVlNQmFBRkp2aUIxZG5IQjdBYWdiZVdiU2FMZC9jR1lZdU1EVUdDQ3NHQVFVRkJ3RUJCQ2t3SnpBbEJnZ3JCZ0VGQlFjd0FZWVphSFIwY0RvdkwyOWpjM0F1Y0d0cExtZHZiMmN2WjNOeU1qQXlCZ05WSFI4RUt6QXBNQ2VnSmFBamhpRm9kSFJ3T2k4dlkzSnNMbkJyYVM1bmIyOW5MMmR6Y2pJdlozTnlNaTVqY213d1B3WURWUjBnQkRnd05qQTBCZ1puZ1F3QkFnSXdLakFvQmdnckJnRUZCUWNDQVJZY2FIUjBjSE02THk5d2Eya3VaMjl2Wnk5eVpYQnZjMmwwYjNKNUx6QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFHb0ErTm5uNzh5NnBSamQ5WGxRV05hN0hUZ2laL3IzUk5Ha21VbVlIUFFxNlNjdGk5UEVhanZ3UlQyaVdUSFFyMDJmZXNxT3FCWTJFVFV3Z1pRK2xsdG9ORnZoc085dHZCQ09JYXpwc3dXQzlhSjl4anU0dFdEUUg4TlZVNllaWi9YdGVEU0dVOVl6SnFQalk4cTNNRHhyem1xZXBCQ2Y1bzhtdy93SjRhMkc2eHpVcjZGYjZUOE1jRE8yMlBMUkw2dTNNNFR6czNBMk0xajZieWtKWWk4d1dJUmRBdktMV1p1L2F4QlZielltcW13a201ekxTRFc1bklBSmJFTENRQ1p3TUg1NnQyRHZxb2Z4czZCQmNDRklaVVNweHU2eDZ0ZDBWN1N2SkNDb3NpclNtSWF0ai85ZFNTVkRRaWJldDhxLzdVSzR2NFpVTjgwYXRuWnoxeWc9PSJdfQ.eyJub25jZSI6InpiNVE5NFVPaHFOWnRVUWEraWY0NnF1UDRwZWZQN2JnQWRpQ3hraDFZRGs9IiwidGltZXN0YW1wTXMiOjE1NDM0ODI1Njg4NTgsImFwa1BhY2thZ2VOYW1lIjoiY29tLmdvb2dsZS5hbmRyb2lkLmdtcyIsImFwa0RpZ2VzdFNoYTI1NiI6InIxYzZiTkJmQ0hjZHcvZWpKSE1NWjhoakIrU0xXa1BSM0lreTZjV1dhNE09IiwiY3RzUHJvZmlsZU1hdGNoIjp0cnVlLCJhcGtDZXJ0aWZpY2F0ZURpZ2VzdFNoYTI1NiI6WyI4UDFzVzBFUEpjc2x3N1V6UnNpWEw2NHcrTzUwRWQrUkJJQ3RheTFnMjRNPSJdLCJiYXNpY0ludGVncml0eSI6dHJ1ZX0.Lq9WpOJ_GilocvPCTbIN2K5FtppXW2fTQzCW2pvb1Bo5qOZnJ0oOYBUqMgxx-zghlluSkkIIfPTvYl2zZUQsY-SNlBx7JASqDbksMyRsdU9r1Jn8D2zEtipFgjmZUkozi7AngnHoA5d0Yp-NF6slmr_FLMpAOnLZY9lREw8Cxnmso3Ph7zYUu7O5SxaRGwj8eMKydYJYHa23h2C8acuQKgSWL2YlG9T-oKT0CJ8jOSrKnHr39eMo7PFX0464diUvXUsv_M9kRIIQqCP0LzilGMdJVUrvFU7kg8csnFP6KMDfY70RGZ5ey3eNqs_D5-pjPfC4XPsPsksmy_wf-3UOmw", # noqa E501 } auth_data = AuthenticatorData( bytes.fromhex( "720c20fde835785e0f5ebcad8ef6a7bd88804a91612a2e820e0059b8d5358797450000000000000000000000000000000000000000004101c8fd9b533d6adacf6710ebcfb39f6361c4d7e8787db47dc0a75ae0e7c862198c9c83b81ef2547bb5669314095fc846af4ecac6875f7b230cac7359c76b0c20f7a5010203262001215820a28851e2d411b5b2c289da50d41cc41be88498941fc256dab500b21c8dafe8d1225820d289dd467715be06a622771a7b21e1bbe2372f8713d20dd7888a6e7ae1845ca8" # noqa E501 )) client_param = bytes.fromhex( "8422c80f3428e4e6465f76ebc8a4a93759a0a2e1fb845ee5eea7a02027408520") res = attestation.verify(statement, auth_data, client_param) self.assertEqual(res.attestation_type, AttestationType.BASIC) verify_x509_chain(res.trust_path + [_GSR2_DER])
def authenticate_complete(): if not credentials: abort(404) data = cbor.decode(request.get_data()) credential_id = data["credentialId"] client_data = CollectedClientData(data["clientDataJSON"]) auth_data = AuthenticatorData(data["authenticatorData"]) signature = data["signature"] print("clientData", client_data) print("AuthenticatorData", auth_data) server.authenticate_complete( session.pop("state"), credentials, credential_id, client_data, auth_data, signature, ) print("ASSERTION OK") return cbor.encode({"status": "OK"})
def test_tpm_windows_hello_attestation(self): attestation = Attestation.for_type("tpm")() self.assertIsInstance(attestation, TpmAttestation) statement = { "alg": -65535, "sig": bytes.fromhex("""80e564d8cbb236577de68d2e68ecae200a8eaf6992889b5 fdc24624a4cb69caaab18df965058fbac39df9714b9c80b9a12d715cfc4dd15ed3a6e191a6d26e 7206fd402b0733c2c8b91f62ad44e4d41c940e2e914253b1d1a1c8889b1cdaf668b5449245dc33 1fab12e0b0dcdfc530cbe1f370e1f2b06c163fbd6177925a1a8998edd2e726989246a1980fa34e 6d65d3ca284944cb10254d85db0d8948294fb8174a41206c6b5e36406bae447343f8c9f97420e3 9f361815dfb268b33ccde5f29e4348a70f95abc30754c839fa7126e5bd882377d6abe3c0c95ba5 c21190a5e4fff5380b2c23cc1655e593244019e172ba8284618471d95b92c231c1ffe98ff23 """.replace("\n", "")), "x5c": [ bytes.fromhex( """308204b23082039aa0030201020210789e1a3657344c52bad2 2ed1ceb1bfaf300d06092a864886f70d01010b05003041313f303d060355040313364e43552d4e 54432d4b455949442d394642423739414130463532363237384245443135303932394137313731 45393641333542454637301e170d3139303430313038353934305a170d32393034303130383539 34305a300030820122300d06092a864886f70d01010105000382010f003082010a0282010100a6 60d1fe41564c26f943c70ff89fbd9ed6d957191d5ecaf727393d73cfff85e3ccfb9830027fe84b 171cc4b0b13811df4d9deff2bce4d8a8f9797169f7b8fc25016d9ba687c003083693716180c8f1 eccaa4410a9a7fe07b198ad7ba94ecf744e9bef0273a5e0723a4ac197994ca1ac0e5f595433970 0cf14ead419ae7cde8c3e81389771d5fa3d339f8d0856e918fd3746fa9a944d3c1f1c6a4e0ce3f 99b5ac5ba05166b3b8695405ae7d3777f9cc8e3ab8570f2191ba4f2cfc4c544337596f48d3d5f5 f9ae80575bf9eb81d5c477e99c58854645d587dd0ccdea2b0e3d482e69b326b289e65741e6b214 3fc2bca35ca7dd60e554affdcb85000762ff09b0410203010001a38201e5308201e1300e060355 1d0f0101ff040403020780300c0603551d130101ff04023000306d0603551d200101ff04633061 305f06092b060104018237151f3052305006082b0601050507020230441e420054004300500041 002000200054007200750073007400650064002000200050006c006100740066006f0072006d00 200020004900640065006e007400690074007930100603551d250409300706056781050803304a 0603551d110101ff0440303ea43c303a3138300e060567810502030c0569643a31333010060567 810502020c074e5043543678783014060567810502010c0b69643a3445353434333030301f0603 551d23041830168014c799ef2371327cb2e9e03838d0a9009fe9ed29e7301d0603551d0e041604 1429fb5f05c6187d8463b8b250b8f0ff128fd3a0713081b306082b060105050701010481a63081 a33081a006082b0601050507300286819368747470733a2f2f617a637370726f646e637561696b 7075626c6973682e626c6f622e636f72652e77696e646f77732e6e65742f6e63752d6e74632d6b 657969642d39666262373961613066353236323738626564313530393239613731373165393661 3335626566372f66383530353438392d303235612d343235322d383239302d3934646532633633 643039362e636572300d06092a864886f70d01010b0500038201010084bc4b9ac3ab6c2438bdec dd3d99e6179bfc465995481d856683602bdcf0c26327b8ab77f7b695c8c6aab5f283b079c29369 29727b839e5bf08c687a33fc59bf281ebf28e9d04e78fd626573028014028badca038e68361017 a4501b18d56a6a73e35f00e043d8febb7a4c719c837bc5cb801efe23570d6c8b40699ba411fe66 f6fe5558f7d1c56a7646ba483cd601690a9323caba9257ae561781b13c658083ad1281047d94d4 c1ab9759d90a16fbe167cec388e7b67027a20dbc1b88986dbb636107ef91ffec22c413ac5fbfec 3de9ee4aa1c6e4c173e43246193890c8b024587fcc8028eb379f515de3c678b11dfb81aef3547c 3c6e790577d52f775f9148""".replace("\n", "")), bytes.fromhex( """308205e8308203d0a003020102021333000000a5304bb34bf0 bee43e0000000000a5300d06092a864886f70d01010b050030818c310b30090603550406130255 53311330110603550408130a57617368696e67746f6e3110300e060355040713075265646d6f6e 64311e301c060355040a13154d6963726f736f667420436f72706f726174696f6e313630340603 550403132d4d6963726f736f66742054504d20526f6f7420436572746966696361746520417574 686f726974792032303134301e170d3136303831383230323032305a170d323931323331323032 3032305a3041313f303d060355040313364e43552d4e54432d4b455949442d3946424237394141 304635323632373842454431353039323941373137314539364133354245463730820122300d06 092a864886f70d01010105000382010f003082010a0282010100e0b963203494ff3b8b93855f4d 0086aabf9f5038fe2a2c04311609074565097dd16de61ae1e6086f5d16997dc7ee5342bf9988f6 bb73ca614f3f5d8ea084fd047112892ae22db792e2efbe24bcb07fd01af124666db7ad53677e45 6a95e972a659c04fe3569e882afbf019c3c5890c52d2e81d175f97234fbe341406cbf834cafa76 184c077c9bd058fbe14b4032039142128fe985ee6041819eee86a62a43491d11af9d78f08e722a 28c0e9b522fed12f172dddfd032a634a6eba2fc90c332997d3ba5f297230cd7d666b6925c0e6ea 79b2459f68fc283cd7a09e09973a610fb88eb63bb1cc29e0dc5e033ace6b966c78038c1adc049e f5360ae28696825ed10203010001a382018b30820187300b0603551d0f040403020186301b0603 551d250414301206092b06010401823715240605678105080330160603551d20040f300d300b06 092b060104018237151f30120603551d130101ff040830060101ff020100301d0603551d0e0416 0414c799ef2371327cb2e9e03838d0a9009fe9ed29e7301f0603551d230418301680147a8c0ace 2f486217e294d1ae55c152ec7174a45630700603551d1f046930673065a063a061865f68747470 3a2f2f7777772e6d6963726f736f66742e636f6d2f706b696f70732f63726c2f4d6963726f736f 667425323054504d253230526f6f742532304365727469666963617465253230417574686f7269 7479253230323031342e63726c307d06082b060105050701010471306f306d06082b0601050507 30028661687474703a2f2f7777772e6d6963726f736f66742e636f6d2f706b696f70732f636572 74732f4d6963726f736f667425323054504d253230526f6f742532304365727469666963617465 253230417574686f72697479253230323031342e637274300d06092a864886f70d01010b050003 820201003e91d074e6d6b9719bf13ffd7cd16b733938c092edaa580136ac7d8bb5295242e432f6 7c3ca5b1c8968b994665e99796a39d579a85cbe6eab02dfce1d08a4ce802b41bf6b00a01533c7c f3b96c7d0b9c0f3a5d2e04350037aea5140a5cc781ca73f370998110bd1031cfa427760920574a 5d7709a1765921d61cb36d91d2ce9d3301f0798ae4b23592b080e70bb535cdf57403f96fe6f0ff 4c0f0363f785a918a1fd3debfaaaebe6b08724a216b491e95e6e300e3d43e4e156fe3c036afba1 7ad2b442f904568af1cc3fd9ad1888cbbd9ec98d42e55af5b26fa8790b6b7da677a585fff6ae90 18e492742d4e9c5ca1a06990a3abff76c6bc4b1e22d8c226d09a96fdcc12801345b647e15850d1 0d0cdb609160b1a7a7c2c6f0eb3dbc2fcd42b765fd22a5672b26009b9a83b44388b62cb89e9169 a455ff5be5ce8f7bde0420b5d7d24ec254affdc2e7e946c961ec159b6dfc703e3934f9445b0072 8e137e11a7c66f76709ca2177b39159fc08593aaa83724b159abb93e535aef53d7d6066a317f92 d42d17888534fee9daf844260de901c3b18b49ccb2a5f81f0f4639f2e2cfa1ce1d7c791cef6f48 5d10df989aac02b1e9afd1094603f5307133f5f59ce105a5910700f98fea5a5fcf8f5cf4c797bd 79d440cc4f9161f5cc61e0e8f06592050cd1f0f0fd066bd1d6335710fdf8159b75281ee1082bff 1da2fc0b631bd346ac""".replace("\n", "")), ], "certInfo": bytes.fromhex("""ff54434780170022000b68cec627cc6411099a1f80 9fde4379f649aa170c7072d1adf230de439efc80810014f7c8b0cdeb31328648130a19733d6fff 16e76e1300000003ef605603446ed8c56aa7608d01a6ea5651ee67a8a20022000bdf681917e185 29c61e1b85a1e7952f3201eb59c609ed5d8e217e5de76b228bbd0022000b0a10d216b0c3ab82bf dc1f0a016ab9493384c7aee1937ee8800f76b30c9b71a7""".replace("\n", "")), "pubArea": bytes.fromhex("""0001000b0006047200209dffcbf36c383ae699fb986 8dc6dcb89d7153884be2803922c124158bfad22ae001000100800000000000100c706586c7f46c dffede0ee0c5ebc8b7a08b36555c8091669e9ef2cb4fd858134a01e9522d3ef924069aeeec2271 823fe9879b5079eb3123be2eb39a7e954f8b83b5ebefefda25aed01bd19eab6db1962a3713985b 7a2dd1aa7770b5c1567fb0d18521e14abebbccc16832ef10bb05dcc818bbb70c91c224475928ad a6f6181ed64f1cfb40db5e01687454cfacafa8318bdc6a677550baa6e24f8af864fa5324e9d930 a97cdeb1995b476f21a017b33ab7fe4139f2524c784fcb04cf5241c89f0c145eb23da914ad1722 d47a843692a0b2a567d94dd808c13678a51c5a0583dc042dcbba1b9ceff12b159d0539248b0994 ee18128ed50dd7a855e54d2459db005""".replace("\n", "")), } auth_data = AuthenticatorData( bytes.fromhex( "54ce651ed715b4aaa755eecebd4ea0950815b334bd07d109893e963018cddbd9450000000008987058cadc4b81b6e130de50dcbe9600206053b7b599d16fb3fb11ea17a344850ebd0d18183a5b7ca6dfbd20c63cdb462aa401030339010020590100c706586c7f46cdffede0ee0c5ebc8b7a08b36555c8091669e9ef2cb4fd858134a01e9522d3ef924069aeeec2271823fe9879b5079eb3123be2eb39a7e954f8b83b5ebefefda25aed01bd19eab6db1962a3713985b7a2dd1aa7770b5c1567fb0d18521e14abebbccc16832ef10bb05dcc818bbb70c91c224475928ada6f6181ed64f1cfb40db5e01687454cfacafa8318bdc6a677550baa6e24f8af864fa5324e9d930a97cdeb1995b476f21a017b33ab7fe4139f2524c784fcb04cf5241c89f0c145eb23da914ad1722d47a843692a0b2a567d94dd808c13678a51c5a0583dc042dcbba1b9ceff12b159d0539248b0994ee18128ed50dd7a855e54d2459db0052143010001" # noqa )) client_param = bytes.fromhex( "057a0ecbe7e3e99e8926941614f6af078c802b110be89eb221d69be2e17a1ba4") res = attestation.verify(statement, auth_data, client_param) self.assertEqual(res.attestation_type, AttestationType.ATT_CA) verify_x509_chain(res.trust_path)