{"id":22006357,"url":"https://github.com/a-sit-plus/warden","last_synced_at":"2025-05-05T22:36:16.441Z","repository":{"id":154529020,"uuid":"629574777","full_name":"a-sit-plus/warden","owner":"a-sit-plus","description":"Server-Side Mobile Client Attestation Library","archived":false,"fork":false,"pushed_at":"2025-04-29T16:33:21.000Z","size":1531,"stargazers_count":21,"open_issues_count":5,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-29T17:39:10.246Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://a-sit-plus.github.io/warden/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/a-sit-plus.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-04-18T15:29:02.000Z","updated_at":"2025-04-23T08:56:24.000Z","dependencies_parsed_at":"2023-10-18T18:45:36.764Z","dependency_job_id":"898d57b9-3a23-45c0-baa5-05bd6a0b52ff","html_url":"https://github.com/a-sit-plus/warden","commit_stats":null,"previous_names":["a-sit-plus/warden","a-sit-plus/attestation-service"],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-sit-plus%2Fwarden","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-sit-plus%2Fwarden/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-sit-plus%2Fwarden/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-sit-plus%2Fwarden/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/a-sit-plus","download_url":"https://codeload.github.com/a-sit-plus/warden/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252587639,"owners_count":21772510,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-30T01:11:45.170Z","updated_at":"2025-05-05T22:36:16.434Z","avatar_url":"https://github.com/a-sit-plus.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n![WARDEN](warden.png)\n\n# Server-Side Mobile Client Attestation Library\n\n[![A-SIT Plus Official](https://img.shields.io/badge/A--SIT_Plus-official-005b79?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNDMuNzYyODYgMTg0LjgxOTk5Ij48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiIGNsaXBQYXRoVW5pdHM9InVzZXJTcGFjZU9uVXNlIj48cGF0aCBkPSJNMCA1OTUuMjhoODQxLjg5VjBIMFoiLz48L2NsaXBQYXRoPjwvZGVmcz48ZyBjbGlwLXBhdGg9InVybCgjYSkiIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMyAwIDAgLTEuMzMzMzMzMyAtNDgyLjI1IDUxNy41MykiPjxwYXRoIGZpbGw9IiMwMDViNzkiIGQ9Ik00MTUuNjcgMjQ5LjUzYy03LjE1LjA4LTEzLjk0IDEtMjAuMTcgMi43NWE1Mi4zMyA1Mi4zMyAwIDAgMC0xNy40OCA4LjQ2IDQwLjQzIDQwLjQzIDAgMCAwLTExLjk2IDE0LjU2Yy0yLjY4IDUuNDEtNC4xNCAxMS44NC00LjM1IDE5LjA5bC0uMDIgNi4xMnYyLjE3YS43MS43MSAwIDAgMCAuNy43M2gxNi41MmMuMzkgMCAuNy0uMzIuNzEtLjdsLjAxLTIuMmMwLTIuNi4wMi01LjgyLjAzLTYuMDcuMi00LjYgMS4yNC04LjY2IDMuMDgtMTIuMDZhMjguNTIgMjguNTIgMCAwIDEgOC4yMy05LjU4IDM1LjI1IDM1LjI1IDAgMCAxIDExLjk2LTUuNTggNTUuMzggNTUuMzggMCAwIDEgMTIuNTgtMS43NmM0LjMyLjEgOC42LjcgMTIuNzQgMS44YTM1LjA3IDM1LjA3IDAgMCAxIDExLjk2IDUuNTcgMjguNTQgMjguNTQgMCAwIDEgOC4yNCA5LjU3YzEuOTYgMy42NCAzIDguMDIgMy4xMiAxMy4wMnYyNC4wOUgzNjIuNGEuNy43IDAgMCAwLS43MS43VjMzNWMwIDguNDMuMDEgOC4wNS4wMSA4LjE0LjIgNy4zIDEuNjcgMTMuNzcgNC4zNiAxOS4yMmE0MC40MyA0MC40MyAwIDAgMCAxMS45NiAxNC41N2M1IDMuNzYgMTAuODcgNi42MSAxNy40OCA4LjQ2YTc3LjUgNzcuNSAwIDAgMCAyMC4wMiAyLjc3YzcuMTUtLjA3IDEzLjk0LTEgMjAuMTctMi43NGE1Mi4zIDUyLjMgMCAwIDAgMTcuNDgtOC40NiA0MC40IDQwLjQgMCAwIDAgMTEuOTUtMTQuNTdjMS42Mi0zLjI2IDMuNzctMTAuMDQgMy43Ny0xNC42OCAwLS4zOC0uMTctLjc0LS41NC0uODJsLTE2Ljg5LS40Yy0uMi0uMDQtLjM0LjM0LS4zNC41NCAwIC4yNy0uMDMuNC0uMDYuNi0uNSAyLjgyLTEuMzggNS40LTIuNjEgNy42OWEyOC41MyAyOC41MyAwIDAgMS04LjI0IDkuNTggMzUuMDEgMzUuMDEgMCAwIDEtMTEuOTYgNS41NyA1NS4yNSA1NS4yNSAwIDAgMS0xMi41NyAxLjc3Yy00LjMyLS4xLTguNjEtLjcxLTEyLjc1LTEuOGEzNS4wNSAzNS4wNSAwIDAgMS0xMS45Ni01LjU3IDI4LjUyIDI4LjUyIDAgMCAxLTguMjMtOS41OGMtMS44Ni0zLjQ0LTIuOS03LjU1LTMuMDktMTIuMmwtLjAxLTcuNDdoODkuMTZhLjcuNyAwIDAgMCAuNy0uNzJ2LTM5LjVjLS4xLTcuNjUtMS41OC0xNC40LTQuMzgtMjAuMDZhNDAuNCA0MC40IDAgMCAwLTExLjk1LTE0LjU2IDUyLjM3IDUyLjM3IDAgMCAwLTE3LjQ4LTguNDcgNzcuNTYgNzcuNTYgMCAwIDAtMjAuMDEtMi43N1oiLz48cGF0aCBmaWxsPSIjY2U0OTJlIiBkPSJNNDE5LjM4IDI4MC42M2gtNy41N2EuNy43IDAgMCAwLS43MS43MXYxNS40MmE4LjE3IDguMTcgMCAwIDAtMy43OCA2LjkgOC4yOCA4LjI4IDAgMCAwIDE2LjU0IDAgOC4yOSA4LjI5IDAgMCAwLTMuNzYtNi45di0xNS40MmEuNy43IDAgMCAwLS43Mi0uNzEiLz48L2c%2BPC9zdmc%2B\u0026logoColor=white\u0026labelColor=white)](https://a-sit-plus.github.io)\n[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-brightgreen.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0) \n[![Kotlin](https://img.shields.io/badge/kotlin-2.0.20-blue.svg?logo=kotlin)](http://kotlinlang.org)\n![Java](https://img.shields.io/badge/java-17-blue.svg?logo=OPENJDK)\n![Build artifacts](https://github.com/a-sit-plus/warden/actions/workflows/gradle.yml/badge.svg)\n[![Maven Central](https://img.shields.io/maven-central/v/at.asitplus/warden)](https://mvnrepository.com/artifact/at.asitplus/warden/)\n\n\u003c/div\u003e\n\nServer-side library providing a unified interface for key attestation compatible with Android and iOS (yes, even iOS!).\nIt also provides App attestation on both platforms (see [our 2019 Paper](https://graz.elsevierpure.com/en/publications/fides-unleashing-the-full-potential-of-remote-attestation) \non how to remotely establish trust in Android applications for more Android-specifics on this matter).\n\nUnder the hood, this library depends on the [WARDEN-roboto](https://github.com/a-sit-plus/warden-roboto) Android attestation library and\n[Vincent Haupert's](https://github.com/veehaitch) excellent [DeviceCheck/AppAttest](https://github.com/veehaitch/devicecheck-appattest) library.\n\nFull API docs are available [here](https://a-sit-plus.github.io/warden/).\n\n## Demonstration / Usage Example\nThis library is intended for integration into back-end services which need to remotely establish trust in mobile clients\n(both Android and iOS). Usually, this means that a mobile client initially request a binding certificate from the back-end\nbased on a public/private key pair stored inside cryptographic hardware.\nThis binding is only granted if device and app integrity can be verified, and if the key can be proven to be stored in hardware.\n\u003cbr\u003e\nOnce a binding has been obtained, mobile clients can subsequently authenticate to the back-end (e.g. to access some protected\nresource). However, far more flexible scenarios can be implemented. Hence, Figure\u0026nbsp;1 depicts an abstract version of\nestablishing trust in mobile clients.\n\nSee the provided [sample service](https://github.com/a-sit-plus/warden/tree/main/sample/backend) and its accompanying mobile clients for an MWE that integrates this library.\n(The sample also contains the Android and iOS clients.)\n\n\u003cdiv align=\"center\"\u003e\n\n![flow.png](flow.png)\n\nFigure 1: Abstract example usage: remotely establishing trust in mobile clients\n\n\u003c/div\u003e\n\n## Background\nApple and Google pursue different strategies wrt. establishing trust in mobile clients.\nOn Android, things are kept rather simpler from an architectural point of view, while iOS attestation depends on infrastructure operated by Apple.\n\n### Android\nDuring a device's manufacturing process, manufacturers provision signing keys and matching certificates into every device's\ncryptographic hardware.\nThe device manufacturers' certificates are signed by Google, resulting in a certificate chain from a certificate signed\nby the [attestation root key published by Google](https://developer.android.com/training/articles/security-key-attestation#root_certificate).\ndown to every individual Android device that ships with Google play services.\nApps can then generate cryptographic keys, which are again securely stored in cryptographic hardware on the device\nand have this hardware module issue certificates for those keys.\nThese certificates are signed by the previously mentioned device manufacturer signing key provisioned during the manufacturing process.\nIn the end, this leads to a chain of trust from the Google root certificate to the cryptographic material created\non the device.\n\u003cbr\u003e\nThe cryptographic material referenced by the leaf certificate of the aforementioned chain can be used by the app as desired (e.g. to perform\nsignatures, etc.).\n\nTo establish trust in an Android device and a client app, quite some properties of such a leaf certificate need to be evaluated\nin a particular manner.\nFrom a high-level point of view, it really is simple: Validate the certificate chain just like any certificate chain, and evaluate\na well-documented extension of the leaf certificate to establish trust in an Android client app (Figure\u0026nbsp;2 illustrates this high-level concept in more detail).\nThis is one core feature of this library -- make establishing trust in client apps just as simple and straight-forward.\nThe other one is providing a unified API to provide a inified API to achieve the same for iOS clients.\n\n\u003cdiv align=\"center\"\u003e\n\n![android.png](android.png)\n\nFigure 2: High-level structure of an Android key attestation result\n\n\u003c/div\u003e\n\n### iOS\niOS's attestation, is a rather different beast compared to Android.\nApple relies on their own heuristics employed as part of a service operated by the company to assess whether a device\nand an app can be trusted or not.\nWhile some of the same basic principles apply here as well (i.e. keys generated in hardware come with chain of trust rooted in\nthe manufacturer's certificate), the semantics are quite different.\nAndroid primarily attests the properties of a cryptographic key.\nApple's [App Attest](https://developer.apple.com/documentation/devicecheck/establishing_your_app_s_integrity), on the\nother hand, attests the integrity of apps.\nThe cryptographic material is in this case a mere vehicle to realise the idea of attesting app integrity.\nTherefore, the involved key material cannot be used for arbitrary cryptographic operations, but is only employed to sign\nattestations (and related assertions; see below).\n\nThis begs the question: How to enable key attestation on iOS?\nAfter all, many applications exist, which require some proof that a key used for critical operations resides in hardware.\n\n#### Legacy Attestation Format (Deprecated, but still Supported since Version 2.2.0)\nTo emulate key attestation, the ability to obtain a so-called *assertion* comes to the rescue: iOS allows generating an *assertion* for some\ndata by signing it using the same key backing a previously obtained attestation.\nBy that logic, computing an assertion over the public key of a freshly generated public/private key pair proves that an\nauthentic, uncompromised app on a non-jailbroken device was used to generate this key pair as intended by the app developer.\n\n#### Supreme Attestation Format (Supported Since Version 2.2.0)\nFollowing Apple's attestation format makes it clear that no data, but only hashes are ever encoded and signed.\nHence, it allows for a lot of flexibility when it comes to the data to be hashed.\nThe new _Supreme_ attestation format exploits this and does not only pass the hash over a challenge to the AppAttest\nservice, but instead constructs a structured (JSON) client data object, inspired by WebAuthn and passes tha hash of this data to DCAppAttest. This means that:\n\n1. A `ClientData` object is created based on the challenge and the public key to attest.\n2. The ClientData is serialized to JSON, and the `ByteArray`-representation of this JSON string are hashed using SHA-256:\n   * `val clientDataJSON = Json.encodeToString(clientData).encodeToByteArray()`\n   * `val clientDataHash = Digest.SHA256.digest(clientDataJSON).toNSData()`\n3. This hash is then passed to DCAppAttest.  \n   If your mobile clients are using the Supreme KMP crypto provider, this is procedure already implemented, and you don't have to worry about it.\n4. The `IosHomebrewAttestation` provided by Signum's _Indispensable_ module lets you access both the raw bytes of this client data\n   as well as the original `ClientData` object, so you can easily verify both the hash of this data and its contents.\n\nFor this whole routine to work, clients need to create a Secure-Enclave-protected key pair before calling `DCAppattest` and construct the structured\nclient data, containing the public part of this key pair and the server challenge.\nThe client data format is defined in the _Signum's\n[Indispensable](https://a-sit-plus.github.io/signum/dokka/indispensable/at.asitplus.signum.indispensable/-ios-homebrew-attestation/-client-data/index.html)_\nmodule, as is the [IosHomebrewAttestation](https://a-sit-plus.github.io/signum/dokka/indispensable/at.asitplus.signum.indispensable/-ios-homebrew-attestation/index.html) containing it.\n\nThis library abstracts away all the nitty-gritty details of this verification process and provides a unified API\nwhich works with both Android and iOS. (The [AndroidKeyStoreAttestation](https://a-sit-plus.github.io/signum/dokka/indispensable/at.asitplus.signum.indispensable/-android-keystore-attestation/index.html) contains simply the certificate chain attached to an attested key.)  \nThe test resources contain examples of [Android](https://github.com/a-sit-plus/warden/tree/main/warden/src/test/resources/aksattest.json) and [iOS](https://github.com/a-sit-plus/warden/tree/main/warden/src/test/resources/ios-appattest.json) attestation proofs.\n\n## Usage\nWritten in Kotlin, plays nicely with Java (cf. `@JvmOverloads`), published at maven central.\n\n### Gradle\nAdd the dependency:\n```kotlin\n dependencies {\n     implementation(\"at.asitplus:warden:$version\")\n }\n```\n### Configuration\nEvery parameter is configurable and multiple instance of an attestation service can be created and used in parallel.\n\nAndroid and iOS attestation require different configuration parameters. Hence, distinct configuration classes exist.\nThe following snippet lists all configuration values:\n\n```kotlin\nval warden = Warden(\n    androidAttestationConfiguration = AndroidAttestationConfiguration(\n       applications= listOf(   //REQUIRED: add applications to be attested\n           AndroidAttestationConfiguration.AppData(\n               packageName = \"at.asitplus.attestation_client\",\n               signatureDigests = listOf(\"NLl2LE1skNSEMZQMV73nMUJYsmQg7=\".encodeToByteArray()),\n               appVersion = 5\n           ),\n           AndroidAttestationConfiguration.AppData( //we have a dedicated app for latest android version\n               packageName = \"at.asitplus.attestation_client-tiramisu\",\n               signatureDigests = listOf(\"NLl2LE1skNSEMZQMV73nMUJYsmQg7=\".encodeToByteArray()),\n               appVersion = 2, //with a different versioning scheme\n               androidVersionOverride = 130000, //so we need to override this\n               patchLevelOverride = PatchLevel(2023, 6) //also override patch level\n           )\n       ),\n       androidVersion = 110000,                //OPTIONAL, null by default\n       patchLevel = PatchLevel(2022, 12),      //OPTIONAL, null by default\n       requireStrongBox = false,               //OPTIONAL, defaults to false\n       allowBootloaderUnlock = false,          //OPTIONAL, defaults to false\n       requireRollbackResistance = false,      //OPTIONAL, defaults to false\n       ignoreLeafValidity = false,             //OPTIONAL, defaults to false\n       hardwareAttestationTrustAnchors = linkedSetOf(*DEFAULT_HARDWARE_TRUST_ANCHORS), //OPTIONAL, defaults shown here\n       softwareAttestationTrustAnchors = linkedSetOf(*DEFAULT_SOFTWARE_TRUST_ANCHORS), //OPTIONAL, defaults shown here\n       verificationSecondsOffset = -300,       //OPTIONAL, defaults to 0\n       disableHardwareAttestation = false,     //OPTIONAL, defaults to false. Set to true to disable HW attestation\n       enableNougatAttestation = false,        //OPTIONAL, defaults to false. Set to true to enable hybrid attestation\n       enableSoftwareAttestation = false,      //OPTIONAL, defaults to false. Set to true to enable SW attestation\n       attestationStatementValiditySeconds = 300 //OPTIONAL, defaults to 300s\n   ),\n   iosAttestationConfiguration = IOSAttestationConfiguration(\n      applications = listOf(\n        IOSAttestationConfiguration.AppData(\n          teamIdentifier = \"9CYHJNG644\",\n          bundleIdentifier = \"at.asitplus.attestation-client\",\n          iosVersionOverride = \"16.0\",     //OPTIONAL, null by default\n          sandbox = false                  //OPTIONAL, defaults to false\n          )\n      ),\n      iosVersion = 14,                                               //OPTIONAL, null by default\n      attestationStatementValiditySeconds = 300                      //OPTIONAL, defaults to 300s\n   ),\n   clock = FixedTimeClock(Instant.parse(\"2023-04-13T00:00:00Z\")),   //OPTIONAL, system clock by default,\n   verificationTimeOffset = Duration.ZERO                           //OPTIONAL, defaults to zero\n)\n```\n\nThe (nullable) properties like patch level, iOS version or Android app version essentially allow for excluding outdated devices.\nDefining a custom logic to verify the attestation challenge for Android is unsupported by design, considering iOS constraints and inconsistencies between platforms resulting from such a customisation.\nMore details on the configuration can be found in the API documentation\n\n#### A Note on Android Attestation\nThis library allows for using combining different flavours of Android attestation, ranging from full hardware attestation\nto (rather useless in practice) software-only attestation (see [WARDEN-roboto](https://github.com/a-sit-plus/warden-roboto) for details).\nHardware attestation is enabled by default, while hybrid and software-only attestation need to be explicitly enabled\nthrough `enableNougatAttestation` and `enableSoftwareAttestation`, respectively. Doing so, will chain the corresponding\n`AndroidAttestationChecker`s initially from strictest (hardware) to most useless (software-only).\nNaturally, hardware attestation can also be disabled by setting `disableHardwareAttestation = true` although there is probably\nno real use case for such a configuration.\nNote that not all flavours use different the same root of trust by default.\n\n### Example Usage\nWhile still not complete, the test suite in this repository should provide a nice overview.\n\u003cbr\u003e\nSee also the provided [sample service](https://github.com/a-sit-plus/warden/tree/main/sample/backend) and its mobile clients for an MWE that integrates this library.\nThe sample also contains Android and iOS clients.\n\n#### Obtaining a Key Attestation Result\n* The general workflow this library caters to assumes a back-end service, sending an attestation challenge to the mobile app. This challenge needs to be kept for future reference\n* The app is assumed to generate a key pair with attestation (passing the received challenge to the platform's respective crypto APIs)\n* The app responds with a platform-dependent attestation proof, the public key just created, and the challenge.\n\n**DEPRECETED, but still supported**\n  * On Android, this proof is simply the certificate chain associated with the newly created key pair, which obtainable through the Android KeyStore API.\n    * The certificate chain needs to be encoded into a list of byte arrays.\n    * The first (index `0`) certificate is assumed to be the leaf, while tha last is assumed to be a certificate signed by the Google hardware attestation root key.\n  * On iOS, the list of byte arrays must contain exactly two entries:\n    * Index `0` contains an attestation object\n    * Index `1` contains an assertion over the to-be-attested public key (either ANSI X9.63 encoded or DER encoded)\n\n**END DEPRECATION. The structure of the platform-specific proofs can be found [here](https://a-sit-plus.github.io/signum/dokka/indispensable/at.asitplus.signum.indispensable/-ios-homebrew-attestation/index.html).**\n\n\n* On the back-end, a single call to `verifyKeyAttestation()`  is sufficient to remotely verify\n   whether the key is indeed stored in HW (and whether the app can be trusted). This call requires the challenge from step 1.\n\nVarious advanced, platform-specific variants of this `verifyKeyAttestation()` call exist, to cater towards features specific to Android and iOS\n(do see [FeatureDemonstration](https://github.com/a-sit-plus/warden/blob/main/warden/src/test/kotlin/FeatureDemonstration.kt) for details).\nHowever, only `verifyKeyAttestation()` works for both Android and iOS and returns a [KeyAttestation](https://github.com/a-sit-plus/warden/blob/main/warden/src/main/kotlin/AttestationService.kt#L293) object:\n\n```kotlin\nfun verifyKeyAttestation(\n  attestationProof: Attestation,\n  challenge: ByteArray)\n: KeyAttestation\u003cPublicKey\u003e\n```\nThe returned `KeyAttestation` object contains the attested key on success, or an error on failure.\n\n#### Semantics\nThe call succeeds if attestation data structures of the client (in `attestationProof`) can be verified and `expectedChallenge` matches\nthe attestation challenge and if `keyToBeAttested` matches the key contained in the proof.\n\nAs mentioned, the contents of **attestationProof** are platform-specific!\nOn Android, this is simply the certificate chain from the attestation certificate\n(i.e. the certificate corresponding to the key to be attested) up to one of the\n[Google hardware attestation root certificates](https://developer.android.com/training/articles/security-key-attestation#root_certificate).\non iOS this must contain the [AppAttest attestation statement](https://developer.apple.com/documentation/devicecheck/validating_apps_that_connect_to_your_server#3576643)\nat index `0` and an [assertion](https://developer.apple.com/documentation/devicecheck/validating_apps_that_connect_to_your_server#3576644)\nat index `1`, which, is verified for integrity and to match `keyToBeAttested` **if the deprecated ios Attestation is used**.\nThe signature counter in the attestation must be `0` (and the signature counter in the assertion must be `1` **if the deprecated ios Attestation is used**).\n\nPassing a public key created in the same app on an iDevice's secure hardware as `clientData` to create an assertion effectively\nemulates Android's key attestation: Attesting such a secondary key through an assertion proves that\nit was also created within the same app, on the same device, resulting in an attested key, which can then be used\nfor general-purpose crypto.\n\u003cbr\u003e\n**Limitation: supports only EC key on iOS (either ANSI X9.63 encoded or DER encoded).**\nThe key can be passed in either encoding to the secure enclave when creating an assertion.\n\n\n## Recording and Replaying Attestation Checks\nSince WARDEN 2.4.0, `Warden` has methods to record the current config and an attestation statement to-be-checked.\nMultiple methods called `collectDebugInfo` exist and their signatures correspond to all the variants of `verifyAttestation` and `verifyKeyAttestation`.\n\nThe resulting class can be serialized to JSON by invoking `.serialize()` (or `serializeCompact()`) on it.\nIt can later be deserialized by calling `deserialize()` (or `deserializeCompact()`) on its companion.\nBy finally calling `replaySmart()` on the deserialized debug info object, an attestation verification is performed.\n\nAttaching a debugger allows for step-by-step debugging of any attestation errors encountered.\n\n\u003cbr\u003e\n\n## Contributing\nExternal contributions are greatly appreciated!\nJust be sure to observe the contribution guidelines (see [CONTRIBUTING.md](CONTRIBUTING.md)).\n\n---\n\u003cp align=\"center\"\u003e\nThis project has received funding from the European Union’s Horizon 2020 research and innovation\nprogramme under grant agreement No 959072.\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"eu.svg\" alt=\"EU flag\"\u003e\n\u003c/p\u003e\n\n\n\u003cp align=\"center\"\u003e\nThe Apache License does not apply to the logos, (including the A-SIT logo) and the project/module name(s), as these are the sole property of\nA-SIT/A-SIT Plus GmbH and may not be used in derivative works without explicit permission!\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa-sit-plus%2Fwarden","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fa-sit-plus%2Fwarden","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa-sit-plus%2Fwarden/lists"}