{"id":13648518,"url":"https://github.com/rustls/rustls-platform-verifier","last_synced_at":"2025-06-10T12:11:03.001Z","repository":{"id":60031727,"uuid":"540649662","full_name":"rustls/rustls-platform-verifier","owner":"rustls","description":"A certificate verification library for rustls that uses the operating system's verifier","archived":false,"fork":false,"pushed_at":"2025-06-01T20:18:13.000Z","size":403,"stargazers_count":102,"open_issues_count":16,"forks_count":28,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-06-08T00:08:38.058Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/rustls.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":null,"license":"LICENSE-APACHE","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":"2022-09-23T23:33:09.000Z","updated_at":"2025-06-07T07:31:48.000Z","dependencies_parsed_at":"2024-01-30T12:02:34.484Z","dependency_job_id":"e4f149ee-7459-43e5-8be8-2513020c00ee","html_url":"https://github.com/rustls/rustls-platform-verifier","commit_stats":{"total_commits":104,"total_committers":10,"mean_commits":10.4,"dds":"0.46153846153846156","last_synced_commit":"7d334a707ecf1ce5ab56c66138952dcb38f5a821"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustls%2Frustls-platform-verifier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustls%2Frustls-platform-verifier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustls%2Frustls-platform-verifier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustls%2Frustls-platform-verifier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rustls","download_url":"https://codeload.github.com/rustls/rustls-platform-verifier/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustls%2Frustls-platform-verifier/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":258788487,"owners_count":22758222,"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-08-02T01:04:19.264Z","updated_at":"2025-06-10T12:11:02.969Z","avatar_url":"https://github.com/rustls.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# rustls-platform-verifier\n\n[![crates.io version](https://img.shields.io/crates/v/rustls-platform-verifier.svg)](https://crates.io/crates/rustls-platform-verifier)\n[![crate documentation](https://docs.rs/rustls-platform-verifier/badge.svg)](https://docs.rs/rustls-platform-verifier)\n![MSRV](https://img.shields.io/badge/rustc-1.64+-blue.svg)\n[![crates.io downloads](https://img.shields.io/crates/d/rustls-platform-verifier.svg)](https://crates.io/crates/rustls-platform-verifier)\n![CI](https://github.com/1Password/rustls-platform-verifier/workflows/CI/badge.svg)\n\nA Rust library to verify the validity of TLS certificates based on the operating system's certificate facilities.\nOn operating systems that don't have these, `webpki` and/or `rustls-native-certs` is used instead.\n\nThis crate is advantageous over `rustls-native-certs` on its own for a few reasons:\n- Improved correctness and security, as the OSes [CA constraints](https://support.apple.com/en-us/HT212865) will be taken into account.\n- Better integration with OS certificate stores and enterprise CA deployments.\n- Revocation support via verifying validity via OCSP and CRLs.\n- Less I/O and memory overhead because all the platform CAs don't need to be loaded and parsed.\n\nThis library supports the following platforms and flows:\n\n| OS             | Certificate Store                             | Verification Method                  | Revocation Support |\n|----------------|-----------------------------------------------|--------------------------------------|--------------------|\n| Windows        | Windows platform certificate store            | Windows API certificate verification | Yes                |\n| macOS (10.14+) | macOS platform roots and keychain certificate | macOS `Security.framework`           | Yes                |\n| iOS            | iOS platform roots and keychain certificates  | iOS `Security.framework`             | Yes                |\n| Android        | Android System Trust Store                    | Android Trust Manager                | Sometimes[^1]      |\n| Linux          | System CA bundle, or user-provided certs[^3]  | webpki                               | No[^2]             |\n| WASM           | webpki roots                                  | webpki                               | No[^2]             |\n\n[^1]: On Android, revocation checking requires API version \u003e= 24 (e.g. at least Android 7.0, August 2016).\nWhen available, revocation checking is only performed for the end-entity certificate. If a stapled OCSP\nresponse for the end-entity cert isn't provided, and the certificate omits both a OCSP responder URL and\nCRL distribution point to fetch revocation information from, revocation checking may fail.\n\n[^2]: The fall-back webpki verifier configured for Linux/WASM does not support providing CRLs for revocation\nchecking. If you require revocation checking on these platforms, prefer constructing your own\n`WebPkiServerVerifier`, providing necessary CRLs. See the Rustls [`ServerCertVerifierBuilder`] docs for more\ninformation.\n\n[^3]: On Linux the [rustls-native-certs] and [openssl-probe] crates are used to try and discover the system CA bundle.\nUsers may wish to augment these certificates with [webpki-roots] using [`Verifier::new_with_extra_roots`] in case\na system CA bundle is unavailable.\n\n[`ServerCertVerifierBuilder`]: https://docs.rs/rustls/latest/rustls/client/struct.ServerCertVerifierBuilder.html\n[`Verifier::new_with_extra_roots`]: https://docs.rs/rustls-platform-verifier/latest/rustls_platform_verifier/struct.Verifier.html#method.new_with_extra_roots\n[rustls-native-certs]: https://github.com/rustls/rustls-native-certs\n[openssl-probe]: https://github.com/alexcrichton/openssl-probe\n[webpki-roots]: https://github.com/rustls/webpki-roots\n\n## Deployment Considerations\n\nWhen choosing to use `rustls-platform-verifier` or another trust store option, these differences are important to consider. They\nare primarily about root certificate availability:\n\n| Backend                                         | Updates                         | Roots used                                                                                            | Supports system-local roots  |\n|-------------------------------------------------|---------------------------------|-------------------------------------------------------------------------------------------------------|------------------------------|\n| `rustls-platform-verifier` (non-Linux/BSD)      | Updated by OS                   | System store, with full (dis)trust decisions from every source available.                             | Yes                          |\n| `rustls-native-certs` + `webpki`                | Updated by OS                   | System store, with no (dis)trust decisions. All roots are treated equally regardless of their status. | Yes, with exceptions         |\n| `webpki-roots` + `webpki`                       | Static, manual updates required | Hardcoded Mozilla CA roots, limited support for constrained roots.                                    | No                           |\n\n**In general**: It is the opinion of the `rustls` and `rustls-platform-verifier` teams that this is the best default available for client-side libraries and applications\nmaking connections to TLS servers when running on common operating systems. This is because it gets both live trust information (new roots, explicit markers, and auto-managed CRLs)\nand better matches the common expectation of apps running on that platform (to use proxies, for example). Otherwise, it becomes your maintenance burden to\nship updates right away in order to handle increasing numbers of positive and negative trust events in the WebPKI/certificate ecosystem, or risk availability and security concerns.\n\n#### Linux/BSD\nAs of the time of writing, `rustls-platform-verifier` on these OSes only loads the trust stores from the OS once upon startup. This is the same behavior as `rustls-native-certs`, but the\nabstraction allows better behavior on the other platforms without extra work for downstreams.\n\n#### Other\n\nAlternatively, there is a clear answer to use static `webpki-roots` in your application instead if you are deploying containerized applications frequently, where root store changes\nwill make it to production faster and any possibly used trust root is static by definition.\n\nEven though platform verifiers are sometimes implemented in memory-unsafe languages, it is very unlikely that Rust apps using this library will become a point of weakness.\nThis is due to either using a smaller set of servers or just being less exposed then other critical functions of the operating system, default web browser, etc.\nBut if your activity is identical or close to one of the following examples that process large amounts of untrusted input, a 100% Rust option like `webpki` is a more secure option: \n- Seeing how many TLS servers `rustls` with a specific configuration can connect to.\n- Harvesting data from various untrusted TLS endpoints exposed on the internet.\n- Extracting info from a known-evil endpoint.\n- Scanning all TLS certificates on the open internet.\n\n`rustls-platform-verifier` is widely deployed by several applications that use the `rustls` stack, such as 1Password, Bitwarden, Signal, and `rustup`, on a wide set of OSes. \nThis means that it has received lots of exposure to edge cases and has real-world experience/expertise invested into it to ensure optimal compatibility and security.\n\n## Installation and setup\nOn most platforms, no setup should be required beyond adding the dependency via `cargo`:\n```toml\nrustls-platform-verifier = \"0.5\"\n```\n\nTo get a rustls `ClientConfig` configured to use the platform verifier use:\n\n```rust\nuse rustls::ClientConfig;\nuse rustls_platform_verifier::ConfigVerifierExt;\nlet config = ClientConfig::with_platform_verifier();\n```\n\nThis crate will use the [rustls process-default crypto provider](https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html#using-the-per-process-default-cryptoprovider). To construct a `ClientConfig` with a different `CryptoProvider`, use:\n\n```rust\nuse rustls::ClientConfig;\nuse rustls_platform_verifier::BuilderVerifierExt;\nlet arc_crypto_provider = std::sync::Arc::new(rustls::crypto::ring::default_provider());\nlet config = ClientConfig::builder_with_provider(arc_crypto_provider)\n    .with_safe_default_protocol_versions()\n    .unwrap()\n    .with_platform_verifier()\n    .unwrap()\n    .with_no_client_auth();\n```\n\n### Android\nSome manual setup is required, outside of `cargo`, to use this crate on Android. In order to\nuse Android's certificate verifier, the crate needs to call into the JVM. A small Kotlin\ncomponent must be included in your app's build to support `rustls-platform-verifier`.\n\n#### Gradle Setup\n\n`rustls-platform-verifier` bundles the required native components in the crate, but the project must be setup to locate them\nautomatically and correctly. These steps assume you are using `.gradle` Groovy files because they're the most common, but if you are using\nKotlin scripts (`.gradle.kts`) for configuration instead, an example snippet is included towards the end of this section.\n\nInside of your project's `build.gradle` file, add the following code and Maven repository definition. If applicable, this should only be the one \"app\" sub-project that\nwill actually be using this crate at runtime. With multiple projects running this, your Gradle configuration performance may degrade.\n\n`$PATH_TO_DEPENDENT_CRATE` is the relative path to the Cargo manifest (`Cargo.toml`) of any crate in your workspace that depends on `rustls-platform-verifier` from\nthe location of your `build.gradle` file:\n\n```groovy\nimport groovy.json.JsonSlurper\n\n// ...Your own script code could be here...\n\nrepositories {\n    // ... Your other repositories could be here...\n    maven {\n        url = findRustlsPlatformVerifierProject()\n        metadataSources.artifact()\n    }\n}\n\nString findRustlsPlatformVerifierProject() {\n    def dependencyText = providers.exec {\n        it.workingDir = new File(\"../\")\n        commandLine(\"cargo\", \"metadata\", \"--format-version\", \"1\", \"--filter-platform\", \"aarch64-linux-android\", \"--manifest-path\", \"$PATH_TO_DEPENDENT_CRATE/Cargo.toml\")\n    }.standardOutput.asText.get()\n\n    def dependencyJson = new JsonSlurper().parseText(dependencyText)\n    def manifestPath = file(dependencyJson.packages.find { it.name == \"rustls-platform-verifier-android\" }.manifest_path)\n    return new File(manifestPath.parentFile, \"maven\").path\n}\n```\n\nThen, wherever you declare your dependencies, add the following:\n```groovy\nimplementation \"rustls:rustls-platform-verifier:latest.release\"\n```\n\nCargo automatically handles finding the downloaded crate in the correct location for your project. It also handles updating the version when\nnew releases of `rustls-platform-verifier` are published. If you only use published releases, no extra maintenance should be required.\n\nThese script snippets can be tweaked as best suits your project, but the `cargo metadata` invocation must be included so that the Android\nimplementation part can be located on-disk.\n\n##### Kotlin and Gradle\n\n\u003cdetails\u003e\n\u003csummary\u003eKotlin script example\u003c/summary\u003e\n\n`build.gradle.kts`:\n```kotlin\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.json.Json\nimport kotlinx.serialization.json.JsonObject\nimport kotlinx.serialization.json.jsonArray\nimport kotlinx.serialization.json.jsonObject\nimport kotlinx.serialization.json.jsonPrimitive\n\nbuildscript {\n    dependencies {\n        classpath(libs.kotlinx.serialization.json)\n    }\n}\n\nrepositories {\n    rustlsPlatformVerifier()\n}\n\nfun RepositoryHandler.rustlsPlatformVerifier(): MavenArtifactRepository {\n    @Suppress(\"UnstableApiUsage\")\n    val manifestPath = let {\n        val dependencyJson = providers.exec {\n            workingDir = File(project.rootDir, \"../\")\n            commandLine(\"cargo\", \"metadata\", \"--format-version\", \"1\", \"--filter-platform\", \"aarch64-linux-android\", \"--manifest-path\", \"$PATH_TO_DEPENDENT_CRATE/Cargo.toml\")\n        }.standardOutput.asText\n\n        val path = Json.decodeFromString\u003cJsonObject\u003e(dependencyJson.get())\n            .getValue(\"packages\")\n            .jsonArray\n            .first { element -\u003e\n                element.jsonObject.getValue(\"name\").jsonPrimitive.content == \"rustls-platform-verifier-android\"\n            }.jsonObject.getValue(\"manifest_path\").jsonPrimitive.content\n\n        File(path)\n    }\n\n    return maven {\n        url = uri(File(manifestPath.parentFile, \"maven\").path)\n        metadataSources.artifact()\n    }\n}\n\ndependencies {\n    // `rustls-platform-verifier` is a Rust crate, but it also has a Kotlin component.\n    implementation(libs.rustls.platform.verifier)\n}\n```\n\n`libs.version.toml`:\n```toml\n# We always use the latest release because `cargo` keeps it in sync with the associated Rust crate's version.\nrustls-platform-verifier = { group = \"rustls\", name = \"rustls-platform-verifier\", version = \"latest.release\" }\n```\n\u003c/details\u003e\n\n#### Proguard\n\nIf your Android application makes use of Proguard for optimizations, its important to make sure that the Android verifier component isn't optimized\nout because it looks like dead code. Proguard is unable to see any JNI usage, so your rules must manually opt into keeping it. The following rule\ncan do this for you:\n```text\n-keep, includedescriptorclasses class org.rustls.platformverifier.** { *; }\n```\n\n#### Crate initialization\n\nIn order for the crate to call into the JVM, it needs handles from Android. These\nare provided either the `init_external` or `init_hosted` function. These give `rustls-platform-verifier`\nthe resources it needs to make calls into the Android certificate verifier.\n\nAs an example, if your Rust Android component which the \"native\" Android\npart of your app calls at startup has an initialization, like this:\n```rust ,ignore\n#[export_name = \"Java_com_orgname_android_rust_init\"]\nextern \"C\" fn java_init(\n    env: JNIEnv,\n    _class: JClass,\n    context: JObject,\n) -\u003e jboolean {\n    // ... initialize your app's other parts here.\n}\n```\n\nIn the simplest case, you should to insert a call to `rustls_platform_verifier::android::init_hosted()` here,\nbefore any networking has a chance to run. This only needs to be called once and\nthe verifier will be valid for the lifetime of your app's process.\n\n```rust ,ignore\nextern \"C\" fn java_init(\n    env: JNIEnv,\n    _class: JClass,\n    context: JObject,\n) -\u003e jboolean {\n    // ... initialize your app's other parts here.\n\n    // Then, initialize the certificate verifier for future use.\n    rustls_platform_verifier::android::init_hosted(\u0026env, context);\n}\n```\n\nIn more advanced cases, such as where your code already stores long-lived handles into\nthe Android environment, you can alternatively use `init_external`. This function takes\na `\u0026'static` reference to something that implements the `android::Runtime` trait, which the\ncrate then uses to obtain the access when required to the JVM.\n\n## Credits\nMade with ❤️ by the [1Password](https://1password.com/) and `rustls` teams. Portions of the Android and Windows verifier\nimplementations were adapted and referenced from Chromium's previous verifier implementations as well.\n\n#### License\n\n\u003csup\u003e\nLicensed under either of \u003ca href=\"LICENSE-APACHE\"\u003eApache License, Version\n2.0\u003c/a\u003e or \u003ca href=\"LICENSE-MIT\"\u003eMIT license\u003c/a\u003e at your option.\n\u003c/sup\u003e\n\n\u003cbr\u003e\n\n\u003csub\u003e\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in this crate by you, as defined in the Apache-2.0 license, shall\nbe dual licensed as above, without any additional terms or conditions.\n\u003c/sub\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustls%2Frustls-platform-verifier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frustls%2Frustls-platform-verifier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustls%2Frustls-platform-verifier/lists"}