diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ffe3760..f100755 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,6 +23,12 @@ jobs: run: | echo "${{ secrets.BUILDBUDDY_BAZELRC }}" > .bazelrc.user && echo "build --compilation_mode=opt" >> .bazelrc.user + - name: Verify CA trust bundle + run: | + bazel build //php:php-fpm-8.4_cacerts @php-common//ca-certificates:data + python3 tests/check_ca_trust.py \ + "$(bazel cquery //php:php-fpm-8.4_cacerts --output=files)" \ + "$(bazel cquery @php-common//ca-certificates:data --output=files)" - name: Setup Steiger run: | curl -Lo steiger https://github.com/brainhivenl/steiger/releases/download/v0.0.1/steiger-x86_64-unknown-linux-gnu && diff --git a/MODULE.bazel b/MODULE.bazel index 4ba1523..815efd2 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -24,15 +24,6 @@ PHP_VERSIONS = [ "8.5", ] -http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "ca-certificates", - build_file_content = 'exports_files(["data.tar.xz", "control.tar.xz"])', - sha256 = "ef590f89563aa4b46c8260d49d1cea0fc1b181d19e8df3782694706adf05c184", - urls = ["https://snapshot.debian.org/archive/debian/20250827T085636Z/pool/main/c/ca-certificates/ca-certificates_20250419_all.deb"], -) - llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm") llvm.toolchain( name = "llvm_toolchain", diff --git a/README.md b/README.md index f20030f..61b0dbd 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,30 @@ Distroless PHP images built with Bazel, using [rules_distroless](https://github.com/GoogleContainerTools/rules_distroless). +## CA trust bundle + +All PHP versions generate their CA bundle from the same `php-common` package that +supplies the image's raw root certificates. Keep the version constraint in +`php/common.yaml` and the amd64/arm64 entries in `php/common.lock.json` aligned. +The minimum fixed package for the October 2026 eMudhra incident is +`20250419~deb12u2` ([DLA-4845-1](https://lists.debian.org/debian-lts-announce/2026/10/msg00039.html)). +Both emSign ECC Root CA - G3 and AAA Certificate Services must be absent: removing +only the first leaves a cross-signed trust path. + +Run the same focused regression check as CI (Python 3 and OpenSSL 3 required): + +```sh +bazel build //php:php-fpm-8.4_cacerts @php-common//ca-certificates:data +python3 tests/check_ca_trust.py \ + "$(bazel cquery //php:php-fpm-8.4_cacerts --output=files)" \ + "$(bazel cquery @php-common//ca-certificates:data --output=files)" +``` + +The check validates both the generated layer and installed raw certificates, +retains unaffected roots, and rejects offline chains through both affected roots. +Existing published images do not update automatically: rebuild and roll out all +supported PHP versions and architectures after merging a trust-store update. + ## Updating Debian package snapshots The YAML manifests pin Debian packages to a specific [snapshot.debian.org](https://snapshot.debian.org) timestamp for reproducibility. When snapshots expire or return 404s, you need to update the timestamps and regenerate the lock files. diff --git a/php/common.lock.json b/php/common.lock.json index 9972775..6c3f620 100644 --- a/php/common.lock.json +++ b/php/common.lock.json @@ -213,13 +213,13 @@ "version": "12.2.0-14+deb12u1" } ], - "key": "ca-certificates_20230311-p-deb12u1_amd64", + "key": "ca-certificates_20250419_deb12u2_amd64", "name": "ca-certificates", - "sha256": "0d5f444f594e48c1e16a41d8fc628a09b24c658916a1274025c2330f2a802bed", + "sha256": "b9f76b5271a7ac373fd5e7e1b5b826a71ddd702b42a0d104955ecb1acfffc94b", "urls": [ - "https://snapshot.debian.org/archive/debian/20260716T082409Z/pool/main/c/ca-certificates/ca-certificates_20230311+deb12u1_all.deb" + "https://snapshot.debian.org/archive/debian-security/20261020T213255Z/pool/updates/main/c/ca-certificates/ca-certificates_20250419~deb12u2_all.deb" ], - "version": "20230311+deb12u1" + "version": "20250419~deb12u2" }, { "arch": "amd64", @@ -1729,13 +1729,13 @@ "version": "12.2.0-14+deb12u1" } ], - "key": "ca-certificates_20230311-p-deb12u1_arm64", + "key": "ca-certificates_20250419_deb12u2_arm64", "name": "ca-certificates", - "sha256": "0d5f444f594e48c1e16a41d8fc628a09b24c658916a1274025c2330f2a802bed", + "sha256": "b9f76b5271a7ac373fd5e7e1b5b826a71ddd702b42a0d104955ecb1acfffc94b", "urls": [ - "https://snapshot.debian.org/archive/debian/20260716T082409Z/pool/main/c/ca-certificates/ca-certificates_20230311+deb12u1_all.deb" + "https://snapshot.debian.org/archive/debian-security/20261020T213255Z/pool/updates/main/c/ca-certificates/ca-certificates_20250419~deb12u2_all.deb" ], - "version": "20230311+deb12u1" + "version": "20250419~deb12u2" }, { "arch": "arm64", diff --git a/php/common.yaml b/php/common.yaml index c459e15..884ff1b 100644 --- a/php/common.yaml +++ b/php/common.yaml @@ -4,7 +4,7 @@ sources: - channel: bookworm main contrib url: https://snapshot.debian.org/archive/debian/20260716T082409Z - channel: bookworm-security main - url: https://snapshot.debian.org/archive/debian-security/20260716T114414Z + url: https://snapshot.debian.org/archive/debian-security/20261020T213255Z - channel: bookworm-updates main url: https://snapshot.debian.org/archive/debian/20260716T082409Z @@ -16,7 +16,8 @@ packages: - media-types - tzdata - coreutils - - ca-certificates + # DLA-4845-1: keep the generated bundle and installed roots on the same fixed package. + - "ca-certificates (= 20250419~deb12u2)" - dash # Command-line dependencies diff --git a/php/image.bzl b/php/image.bzl index 830173f..5b551d4 100644 --- a/php/image.bzl +++ b/php/image.bzl @@ -126,7 +126,7 @@ def php_fpm_image(name, version): cacerts( name = "{}_cacerts".format(name), - package = "@ca-certificates//:data.tar.xz", + package = "@php-common//ca-certificates:data", ) oci_image( diff --git a/tests/check_ca_trust.py b/tests/check_ca_trust.py new file mode 100644 index 0000000..ef4d465 --- /dev/null +++ b/tests/check_ca_trust.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Check the generated bundle and the raw certificates shipped in PHP images.""" + +import hashlib +from pathlib import Path +import re +import ssl +import subprocess +import sys +import tarfile +import tempfile + + +PEM = re.compile(rb"-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----", re.S) +# Certificate DER SHA-256, not subject names or SPKI hashes. See fixtures/README.md. +DISTRUSTED = { + "86A1ECBA089C4A8D3BBE2734C612BA341D813E043CF9E8A862CD5C57A36BBE6B", + "D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4", + "7DD78D5F4F13459A83DFF9ABBBA62EDBAF6F2D102BF257FD712F4D9F2746ED8D", + "F2EDAAFF3D9B701FB4D14C9F285F8C0BAD90FC3BCC1FA07D47F4718EDABA34A5", +} +RETAINED = { + # Unaffected emSign Root CA - G1 and ISRG Root X1. + "40F6AF0346A99AA1CD1D555A4E9CCE62C7F9634603EE406615833DC8C8D00367", + "96BCEC06264976F37460779ACF28C5A7CFE8A3C0AAE11A8FFCEE05C0BDDF08C6", +} + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def fingerprints(data): + certs = PEM.findall(data) + require(bool(certs), "No PEM certificates found") + return { + hashlib.sha256(ssl.PEM_cert_to_DER_cert(cert.decode("ascii"))).hexdigest().upper() + for cert in certs + } + + +def read_archive(path, prefix): + with tarfile.open(path) as archive: + files = [ + member for member in archive.getmembers() + if member.isfile() and member.name.removeprefix("./").startswith(prefix) + and member.name.endswith(".crt") + ] + require(bool(files), f"No certificate files under {prefix} in {path}") + return b"\n".join(archive.extractfile(member).read() for member in files) + + +def main(): + require(len(sys.argv) == 3, "Usage: check_ca_trust.py BUNDLE_LAYER_TAR PACKAGE_DATA_TAR") + bundle = read_archive(sys.argv[1], "etc/ssl/certs/") + source = read_archive(sys.argv[2], "usr/share/ca-certificates/") + bundle_fps, source_fps = fingerprints(bundle), fingerprints(source) + require(bundle_fps == source_fps, "Generated bundle and installed raw roots differ") + require(not bundle_fps & DISTRUSTED, f"Distrusted roots remain: {bundle_fps & DISTRUSTED}") + require(RETAINED <= bundle_fps, "Unaffected emSign G1 or ISRG Root X1 was removed") + require(len(bundle_fps) > 100, "Unexpectedly small CA bundle") + + # These offline chains worked with the old bundle. Fix time to the incident + # so expiry cannot make an unsafe bundle appear to pass in future runs. + with tempfile.TemporaryDirectory() as directory: + ca_file = Path(directory) / "ca.pem" + ca_file.write_bytes(bundle) + fixtures = sorted((Path(__file__).parent / "fixtures").glob("*.pem")) + require(len(fixtures) == 2, "Both eMudhra and AAA cross-sign fixtures are required") + for fixture in fixtures: + result = subprocess.run( + ["openssl", "verify", "-CAfile", str(ca_file), "-no-CApath", "-no-CAstore", + "-attime", "1792756800", "-untrusted", str(fixture), str(fixture)], + capture_output=True, text=True, check=False, + ) + require(result.returncode != 0, f"Compromised chain still trusted: {fixture.name}") + require("error 20 at" in result.stderr, + f"Expected an untrusted issuer, not another failure: {result.stderr}") + print(f"PASS: {len(bundle_fps)} retained roots; affected roots and both attack chains rejected") + + +if __name__ == "__main__": + main() diff --git a/tests/fixtures/README.md b/tests/fixtures/README.md new file mode 100644 index 0000000..426098d --- /dev/null +++ b/tests/fixtures/README.md @@ -0,0 +1,23 @@ +# eMudhra distrust regression fixtures + +Public certificate chains copied on 23 October 2026 from the incident researcher's +[offline chain archive](https://emudhra.we-have-a-problem.com/chains.zip), linked by +[Mozilla's operator guidance](https://groups.google.com/a/mozilla.org/g/dev-security-policy/c/0R3XLJL6FuE). +These files contain certificates only, not private keys. + +- `emudhra-g3-chain.pem`: `chains/dv-g3b-emudhra.we-have-a-problem.com.pem`, + file SHA-256 `ab6483de0cb01d53d59275baf74d2766f3599e57a48d3319e4a5536c268ac696`. +- `aaa-cross-signed-chain.pem`: `chains/dv-g3b-aaa-emudhra.we-have-a-problem.com.pem`, + file SHA-256 `3641ff8e872e4c90d5691edb09894914121b267e6a50455347c5f28708fa1af2`. + +Both chains were accepted by the previous `20250419` bundle. The check fixes the +verification time to 23 October 2026, disables other OpenSSL CA stores and requires +an issuer-trust failure, not an expiry, DNS, or connection failure. It checks both +the generated bundle and raw roots, and retains unaffected emSign G1 and ISRG X1. + +The four defensive root fingerprint assertions come from the researcher's +[`roots.json`](https://emudhra.we-have-a-problem.com/roots.json). +Only emSign ECC G3 and AAA occur in this Debian bundle. Debian's +[DLA-4845-1](https://lists.debian.org/debian-lts-announce/2026/10/msg00039.html) +removes those two roots to cover the cross-sign path. This is not a blanket +distrust of all eMudhra certificates. diff --git a/tests/fixtures/aaa-cross-signed-chain.pem b/tests/fixtures/aaa-cross-signed-chain.pem new file mode 100644 index 0000000..10f6cbd --- /dev/null +++ b/tests/fixtures/aaa-cross-signed-chain.pem @@ -0,0 +1,38 @@ +-----BEGIN CERTIFICATE----- +MIICQDCCAcagAwIBAgIUU3mgjls/8ZJ8upmukdlSQR1IF/UwCgYIKoZIzj0EAwIw +PzELMAkGA1UEBhMCTkwxEzARBgNVBAoMCmVNdWRocmEgQlYxGzAZBgNVBAMMEkVN +IERWIFRMUyBDQSAtIEczQjAeFw0yNjEwMjAwMjIyNDFaFw0yNzA1MDMwMjI3NDFa +MDMxMTAvBgNVBAMMKGR2LWczYi1hYWEtZW11ZGhyYS53ZS1oYXZlLWEtcHJvYmxl +bS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATK3sfcOxxtM2Vdq9Qbw/GR +NsHlJcnqINEInXO3fkWhw/FYT80hkqGk0jSN/EKib3YZJsr5GyfkYcpEiA2rwMgm +o4GrMIGoMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG +CCsGAQUFBwMBMDMGA1UdEQQsMCqCKGR2LWczYi1hYWEtZW11ZGhyYS53ZS1oYXZl +LWEtcHJvYmxlbS5jb20wHQYDVR0OBBYEFDggfJFz1eeToKmzFBSYkMCvpAu0MB8G +A1UdIwQYMBaAFOIeL+ccGTkOVUtiwSAkVzUkiiUUMAoGCCqGSM49BAMCA2gAMGUC +MDqDDOt7K313QIH0rhn/ZKnzFu8+/9W8OlTuFtDfVCTRDfRmqdyfsCfLsEk7xqHq +uQIxAJqyLERABmU98U46OCuT5bp5h0ytuSEIGM7orTpKci5S1u1B/AOmwv162U7R +TcVPHA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDzjCCAragAwIBAgIRAKAk/fS6Zlx4XOSgIEg4WLcwDQYJKoZIhvcNAQELBQAw +ezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0yNTA1MTQwMDAwMDBaFw0y +ODEyMzEyMzU5NTlaMD8xCzAJBgNVBAYTAk5MMRMwEQYDVQQKDAplTXVkaHJhIEJW +MRswGQYDVQQDDBJFTSBEViBUTFMgQ0EgLSBHM0IwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAATnntnASpdzxHNeUREdqFrCvV5kqzdLgOEsvCA47B5PDjuBL8mFnh5nr7BO +L4vJf3SFumWqkR7opORbYtXMA9Vr5nizw4y03JN8okYOI4RTyJKTXSnUT5HhVga2 +PM7atGijggE1MIIBMTAfBgNVHSMEGDAWgBSgEQojPpbxB+zirynvgqV/0DCktDAd +BgNVHQ4EFgQU4h4v5xwZOQ5VS2LBICRXNSSKJRQwDgYDVR0PAQH/BAQDAgEGMBIG +A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC +MDEGA1UdIAQqMCgwCAYGZ4EMAQIBMA0GCysGAQQBg44hAQABMA0GCysGAQQBg44h +AQJkMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0FB +QUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEF +BQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBCwUAA4IB +AQBzQ1IoqpdotM6gFrR4Q3YrKifOLeaj5XXunldpVE/vZn2TxC2y0s8oYiLR5ICE +wqVXSB7N6BM1Mp+Nif7Jbhb2IswAfSR4Iik8+B0iRmi7lYoNlycCgHjmsjOmZaxM +QkPmjXAJbG5f4V41OsvJZmS7lI3r0IuvEDVX3GAZ13on6IImSs9ybNpHQ7NCqkMQ +7wH4uAO1dtpFycgJSdHaCOhHjrox2BTYGLdpUrYwY3EOAjlZ8UGgsxs7mG+xquMl +bN1LFURwfnkVMP3T/DBIZ/ys2+lNFyxK3FlArrV4/000uTnVB1lO8oGORYdXoT5V +GUyRCEIDhF5TBUuKF4E3kf1h +-----END CERTIFICATE----- diff --git a/tests/fixtures/emudhra-g3-chain.pem b/tests/fixtures/emudhra-g3-chain.pem new file mode 100644 index 0000000..ad8f25d --- /dev/null +++ b/tests/fixtures/emudhra-g3-chain.pem @@ -0,0 +1,56 @@ +-----BEGIN CERTIFICATE----- +MIICOTCCAb6gAwIBAgIUY1R/PHrtXShV0uhLJ5EyjsHvMi0wCgYIKoZIzj0EAwIw +PzELMAkGA1UEBhMCTkwxEzARBgNVBAoMCmVNdWRocmEgQlYxGzAZBgNVBAMMEkVN +IERWIFRMUyBDQSAtIEczQjAeFw0yNjEwMjAwMDU5MzZaFw0yNzA1MDMwMTA0MzZa +MC8xLTArBgNVBAMMJGR2LWczYi1lbXVkaHJhLndlLWhhdmUtYS1wcm9ibGVtLmNv +bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFpE24ACBFHQLzpg+7D767thJ3+Q +NIoJJugUMT/OftEz6G6uDdxlS+9VfXYBDglHjJirjEPFNglOGJoQNQuiz7Gjgacw +gaQwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYB +BQUHAwEwLwYDVR0RBCgwJoIkZHYtZzNiLWVtdWRocmEud2UtaGF2ZS1hLXByb2Js +ZW0uY29tMB0GA1UdDgQWBBT4r5v4etYNuG21BqBqs273OkcHiDAfBgNVHSMEGDAW +gBTiHi/nHBk5DlVLYsEgJFc1JIolFDAKBggqhkjOPQQDAgNpADBmAjEAlxNF+/8l +APpgibawACy15yn5bcvTksz2Zw0R9z9nUK9e3MSSk+hXagg7LVb7V4NtAjEA4qyR +laFPkaokrnTjqQieq8CgDQ6tIz3FjBvj3D7vkhKXHaml6zD2zT5ih2Y+lD2h +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDaDCCAu6gAwIBAgIQAKSu5njyM2K0wORgt3LyFDAKBggqhkjOPQQDAzBWMQsw +CQYDVQQGEwJJTjElMCMGA1UECgwcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl +ZDEgMB4GA1UEAwwXZW1TaWduIFJvb3QgVExTIENBIC0gRzMwHhcNMjUwNDMwMTU1 +NDA4WhcNNDAwNDI4MTgzMDAwWjA/MQswCQYDVQQGEwJOTDETMBEGA1UECgwKZU11 +ZGhyYSBCVjEbMBkGA1UEAwwSRU0gRFYgVExTIENBIC0gRzNCMHYwEAYHKoZIzj0C +AQYFK4EEACIDYgAE557ZwEqXc8RzXlERHahawr1eZKs3S4DhLLwgOOweTw47gS/J +hZ4eZ6+wTi+LyX90hbplqpEe6KTkW2LVzAPVa+Z4s8OMtNyTfKJGDiOEU8iSk10p +1E+R4VYGtjzO2rRoo4IBljCCAZIwHwYDVR0jBBgwFoAU4TqrIXzx401UrtRyt/2L +WUIgkFQwHQYDVR0OBBYEFOIeL+ccGTkOVUtiwSAkVzUkiiUUMB0GA1UdJQQWMBQG +CCsGAQUFBwMBBggrBgEFBQcDAjBdBgNVHSAEVjBUMDkGCysGAQQBg44hAQABMCow +KAYIKwYBBQUHAgEWHGh0dHA6Ly9yZXBvc2l0b3J5LmVtc2lnbi5jb20wDQYLKwYB +BAGDjiEBAmQwCAYGZ4EMAQIBMHUGCCsGAQUFBwEBBGkwZzAkBggrBgEFBQcwAYYY +aHR0cDovL29jc3AtYi5lbXNpZ24uY29tMD8GCCsGAQUFBzAChjNodHRwOi8vcmVw +b3NpdG9yeS5lbXNpZ24uY29tL2NlcnRzL0VNRFZUTFNDQUczQi5wN2MwNwYDVR0f +BDAwLjAsoCqgKIYmaHR0cDovL2NybC5lbXNpZ24uY29tLz9yb290dGxzY2FnMy5j +cmwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwCgYIKoZIzj0E +AwMDaAAwZQIwLmsGXi6oFMJ2klkcEMXMug6gvxQWZWkewiDWVzQyl2L6z6DuQfPO +Ibh1grvdULDCAjEAxZvLlxUavG69J6wnSjC8XBbqNIQsJ6CE2QdNOe84Ptxb6VG8 +gt2TlfJbHii+KNvK +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDdDCCAvmgAwIBAgIQAJYaPvsTWVdu0EAFtGhKWzAKBggqhkjOPQQDAzBrMQsw +CQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhy +YSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290 +IENBIC0gRzMwHhcNMjQwNzExMTU0MzM2WhcNMzkwNzA5MTgzMDAwWjBWMQswCQYD +VQQGEwJJTjElMCMGA1UECgwcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg +MB4GA1UEAwwXZW1TaWduIFJvb3QgVExTIENBIC0gRzMwdjAQBgcqhkjOPQIBBgUr +gQQAIgNiAARfD9w/q1cWxL6D9bMGH6CQ4u+gAV6GN9s+PwQx9Bl4hC+0iU8QOk8m +WO/RwXQy10DCSxT8vSIJClHKp+Ao4qJKdYeV0SwZ7LMQziyLfxIUOY6Grja/sQFw +LKYf8EdDXAyjggF1MIIBcTAfBgNVHSMEGDAWgBR8XQKEE9TMipuBzhccLikenEhj +QjAdBgNVHQ4EFgQU4TqrIXzx401UrtRyt/2LWUIgkFQwHQYDVR0lBBYwFAYIKwYB +BQUHAwEGCCsGAQUFBwMCMD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIB +FhxodHRwOi8vcmVwb3NpdG9yeS5lbXNpZ24uY29tMHgGCCsGAQUFBwEBBGwwajAi +BggrBgEFBQcwAYYWaHR0cDovL29jc3AuZW1zaWduLmNvbTBEBggrBgEFBQcwAoY4 +aHR0cDovL3JlcG9zaXRvcnkuZW1zaWduLmNvbS9jZXJ0cy9lbVNpZ25FQ0NSb290 +Q0FHMy5jcnQwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbXNpZ24uY29t +P1Jvb3RDQUczLmNybDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIB +ATAKBggqhkjOPQQDAwNpADBmAjEAt9CIpRGp46QHQYDUBnLKw+vvK0/h9vmilEAg +TroUl/anH4x2rXHqiCtBTBfgKDegAjEA8WpG1LTZdAIL0FSYqxXeREaeTSxEofM0 +1jJH3jGvCXC79LU9UPJ2o3TU+UIj2gMV +-----END CERTIFICATE-----