Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand Down
9 changes: 0 additions & 9 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
16 changes: 8 additions & 8 deletions php/common.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
5 changes: 3 additions & 2 deletions php/common.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion php/image.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
84 changes: 84 additions & 0 deletions tests/check_ca_trust.py
Original file line number Diff line number Diff line change
@@ -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()
23 changes: 23 additions & 0 deletions tests/fixtures/README.md
Original file line number Diff line number Diff line change
@@ -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.
38 changes: 38 additions & 0 deletions tests/fixtures/aaa-cross-signed-chain.pem
Original file line number Diff line number Diff line change
@@ -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-----
56 changes: 56 additions & 0 deletions tests/fixtures/emudhra-g3-chain.pem
Original file line number Diff line number Diff line change
@@ -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-----
Loading