diff --git a/duo-client/src/main/java/com/duosecurity/client/CertificateUtils.java b/duo-client/src/main/java/com/duosecurity/client/CertificateUtils.java new file mode 100644 index 0000000..f05785c --- /dev/null +++ b/duo-client/src/main/java/com/duosecurity/client/CertificateUtils.java @@ -0,0 +1,139 @@ +package com.duosecurity.client; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Collection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +public class CertificateUtils { + + private static final String DEFAULT_BUNDLE_PATH = "duo-ca-certs/ca_certs.pem"; + + /** + * Create a TrustManagerFactory loaded with the default Duo CA bundle. + * + * @return TrustManagerFactory initialized with bundled Duo root CAs + */ + public static TrustManagerFactory createDefaultTrustManagerFactory() { + InputStream pemStream = CertificateUtils.class.getClassLoader() + .getResourceAsStream(DEFAULT_BUNDLE_PATH); + if (pemStream == null) { + throw new IllegalStateException( + "Cannot find bundled CA certificates at " + DEFAULT_BUNDLE_PATH); + } + try { + return createTrustManagerFactory(pemStream); + } finally { + try { + pemStream.close(); + } catch (IOException e) { + // ignore close error + } + } + } + + /** + * Create a TrustManagerFactory from PEM certificate content. + * + * @param pemContent PEM-encoded certificates as a String + * @return TrustManagerFactory initialized with the provided certificates + */ + public static TrustManagerFactory createTrustManagerFactory(String pemContent) { + InputStream stream = new ByteArrayInputStream(pemContent.getBytes(StandardCharsets.UTF_8)); + return createTrustManagerFactory(stream); + } + + /** + * Create a TrustManagerFactory from a PEM certificate InputStream. + * + * @param pemStream InputStream containing PEM-encoded certificates + * @return TrustManagerFactory initialized with the provided certificates + */ + public static TrustManagerFactory createTrustManagerFactory(InputStream pemStream) { + try { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Collection certs = cf.generateCertificates(pemStream); + + if (certs.isEmpty()) { + throw new IllegalArgumentException("No certificates found in PEM input"); + } + + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, null); + + int index = 0; + for (Certificate cert : certs) { + keyStore.setCertificateEntry("duo-ca-" + index, cert); + index++; + } + + TrustManagerFactory tmf = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(keyStore); + return tmf; + } catch (CertificateException | KeyStoreException | NoSuchAlgorithmException + | IOException e) { + throw new IllegalStateException("Failed to initialize trust store", e); + } + } + + /** + * Create an SSLSocketFactory from a TrustManagerFactory. + * + * @param tmf the TrustManagerFactory to use + * @return SSLSocketFactory configured with the trust manager + */ + public static SSLSocketFactory createSslSocketFactory(TrustManagerFactory tmf) { + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, tmf.getTrustManagers(), null); + return sslContext.getSocketFactory(); + } catch (Exception e) { + throw new IllegalStateException("Failed to create SSLSocketFactory", e); + } + } + + /** + * Extract the X509TrustManager from a TrustManagerFactory. + * + * @param tmf the TrustManagerFactory + * @return the X509TrustManager + */ + public static X509TrustManager getX509TrustManager(TrustManagerFactory tmf) { + for (TrustManager tm : tmf.getTrustManagers()) { + if (tm instanceof X509TrustManager) { + return (X509TrustManager) tm; + } + } + throw new IllegalStateException("No X509TrustManager found in TrustManagerFactory"); + } + + /** + * Get a TrustManagerFactory initialized with the system default trust store. + * + * @return TrustManagerFactory using system cacerts + */ + public static TrustManagerFactory getSystemTrustManagerFactory() { + try { + TrustManagerFactory tmf = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm()); + tmf.init((KeyStore) null); + return tmf; + } catch (NoSuchAlgorithmException | KeyStoreException e) { + throw new IllegalStateException("Failed to initialize system trust store", e); + } + } +} diff --git a/duo-client/src/main/java/com/duosecurity/client/Http.java b/duo-client/src/main/java/com/duosecurity/client/Http.java index f1728dc..87a5636 100644 --- a/duo-client/src/main/java/com/duosecurity/client/Http.java +++ b/duo-client/src/main/java/com/duosecurity/client/Http.java @@ -16,7 +16,9 @@ import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.TimeUnit; -import okhttp3.CertificatePinner; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.OkHttpClient; @@ -54,147 +56,6 @@ public class Http { public static MediaType FORM_ENCODED = MediaType.parse("application/x-www-form-urlencoded"); public static MediaType JSON_ENCODED = MediaType.parse("application/json"); - private static final String[] DEFAULT_CA_CERTS = { - //Source URL: https://www.amazontrust.com/repository/AmazonRootCA1.cer - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=Amazon Root CA 1,O=Amazon,C=US - //Issuer: CN=Amazon Root CA 1,O=Amazon,C=US - //Expiration Date: 2038-01-17 00:00:00 - //Serial Number: 66C9FCF99BF8C0A39E2F0788A43E696365BCA - //SHA256 Fingerprint: 8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e - "sha256/++MBgDH5WGvL9Bcn5Be30cRcL0f5O+NyoXuWtQdX1aI=", - //Source URL: https://www.amazontrust.com/repository/AmazonRootCA2.cer - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=Amazon Root CA 2,O=Amazon,C=US - //Issuer: CN=Amazon Root CA 2,O=Amazon,C=US - //Expiration Date: 2040-05-26 00:00:00 - //Serial Number: 66C9FD29635869F0A0FE58678F85B26BB8A37 - //SHA256 Fingerprint: 1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4 - "sha256/f0KW/FtqTjs108NpYj42SrGvOB2PpxIVM8nWxjPqJGE=", - //Source URL: https://www.amazontrust.com/repository/AmazonRootCA3.cer - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=Amazon Root CA 3,O=Amazon,C=US - //Issuer: CN=Amazon Root CA 3,O=Amazon,C=US - //Expiration Date: 2040-05-26 00:00:00 - //Serial Number: 66C9FD5749736663F3B0B9AD9E89E7603F24A - //SHA256 Fingerprint: 18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4 - "sha256/NqvDJlas/GRcYbcWE8S/IceH9cq77kg0jVhZeAPXq8k=", - //Source URL: https://www.amazontrust.com/repository/AmazonRootCA4.cer - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=Amazon Root CA 4,O=Amazon,C=US - //Issuer: CN=Amazon Root CA 4,O=Amazon,C=US - //Expiration Date: 2040-05-26 00:00:00 - //Serial Number: 66C9FD7C1BB104C2943E5717B7B2CC81AC10E - //SHA256 Fingerprint: e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092 - "sha256/9+ze1cZgR9KO1kZrVDxA4HQ6voHRCSVNz4RdTCx4U8U=", - //Source URL: https://www.amazontrust.com/repository/SFSRootCAG2.cer - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=Starfield Services Root Certificate Authority - G2, - // O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - //Issuer: CN=Starfield Services Root Certificate Authority - G2, - // O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - //Expiration Date: 2037-12-31 23:59:59 - //Serial Number: 0 - //SHA256 Fingerprint: 568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5 - "sha256/KwccWaCgrnaw6tsrrSO61FgLacNgG2MMLq8GE6+oP5I=", - //Source URL: https://cacerts.digicert.com/DigiCertHighAssuranceEVRootCA.crt - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US - //Issuer: CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US - //Expiration Date: 2031-11-10 00:00:00 - //Serial Number: 2AC5C266A0B409B8F0B79F2AE462577 - //SHA256 Fingerprint: 7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf - "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=", - //Source URL: https://cacerts.digicert.com/DigiCertTLSECCP384RootG5.crt - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=DigiCert TLS ECC P384 Root G5,O=DigiCert\, Inc.,C=US - //Issuer: CN=DigiCert TLS ECC P384 Root G5,O=DigiCert\, Inc.,C=US - //Expiration Date: 2046-01-14 23:59:59 - //Serial Number: 9E09365ACF7D9C8B93E1C0B042A2EF3 - //SHA256 Fingerprint: 018e13f0772532cf809bd1b17281867283fc48c6e13be9c69812854a490c1b05 - "sha256/oC+voZLIy4HLE0FVT5wFtxzKKokLDRKY1oNkfJYe+98=", - //Source URL: https://cacerts.digicert.com/DigiCertTLSRSA4096RootG5.crt - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=DigiCert TLS RSA4096 Root G5,O=DigiCert\, Inc.,C=US - //Issuer: CN=DigiCert TLS RSA4096 Root G5,O=DigiCert\, Inc.,C=US - //Expiration Date: 2046-01-14 23:59:59 - //Serial Number: 8F9B478A8FA7EDA6A333789DE7CCF8A - //SHA256 Fingerprint: 371a00dc0533b3721a7eeb40e8419e70799d2b0a0f2c1d80693165f7cec4ad75 - "sha256/ape1HIIZ6T5d7GS61YBs3rD4NVvkfnVwELcCRW4Bqv0=", - //Source URL: https://secure.globalsign.com/cacert/rootr46.crt - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=GlobalSign Root R46,O=GlobalSign nv-sa,C=BE - //Issuer: CN=GlobalSign Root R46,O=GlobalSign nv-sa,C=BE - //Expiration Date: 2046-03-20 00:00:00 - //Serial Number: 11D2BBB9D723189E405F0A9D2DD0DF2567D1 - //SHA256 Fingerprint: 4fa3126d8d3a11d1c4855a4f807cbad6cf919d3a5a88b03bea2c6372d93c40c9 - "sha256/rn+WLLnmp9v3uDP7GPqbcaiRdd+UnCMrap73yz3yu/w=", - //Source URL: https://secure.globalsign.com/cacert/roote46.crt - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=GlobalSign Root E46,O=GlobalSign nv-sa,C=BE - //Issuer: CN=GlobalSign Root E46,O=GlobalSign nv-sa,C=BE - //Expiration Date: 2046-03-20 00:00:00 - //Serial Number: 11D2BBBA336ED4BCE62468C50D841D98E843 - //SHA256 Fingerprint: cbb9c44d84b8043e1050ea31a69f514955d7bfd2e2c6b49301019ad61d9f5058 - "sha256/4EoCLOMvTM8sf2BGKHuCijKpCfXnUUR/g/0scfb9gXM=", - //Source URL: https://i.pki.goog/r2.crt - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=GTS Root R2,O=Google Trust Services LLC,C=US - //Issuer: CN=GTS Root R2,O=Google Trust Services LLC,C=US - //Expiration Date: 2036-06-22 00:00:00 - //Serial Number: 203E5AEC58D04251AAB1125AA - //SHA256 Fingerprint: 8d25cd97229dbf70356bda4eb3cc734031e24cf00fafcfd32dc76eb5841c7ea8 - "sha256/Vfd95BwDeSQo+NUYxVEEIlvkOlWY2SalKK1lPhzOx78=", - //Source URL: https://i.pki.goog/r4.crt - //Certificate #1 Details: - //Original Format: DER - //Subject: CN=GTS Root R4,O=Google Trust Services LLC,C=US - //Issuer: CN=GTS Root R4,O=Google Trust Services LLC,C=US - //Expiration Date: 2036-06-22 00:00:00 - //Serial Number: 203E5C068EF631A9C72905052 - //SHA256 Fingerprint: 349dfa4058c5e263123b398ae795573c4e1313c83fe68f93556cd5e8031b3c7d - "sha256/mEflZT5enoR1FuXLgYYGqnVEoZvmf9c2bVBpiOjYQ0c=", - //Source URL: https://www.identrust.com/file-download/download/public/5718 - //Certificate #1 Details: - //Original Format: PKCS7-DER - //Subject: CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US - //Issuer: CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US - //Expiration Date: 2034-01-16 18:12:23 - //Serial Number: A0142800000014523C844B500000002 - //SHA256 Fingerprint: 5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae - "sha256/B+hU8mp8vTiZJ6oEG/7xts0h3RQ4GK2UfcZVqeWH/og=", - //Source URL: https://www.identrust.com/file-download/download/public/5842 - //Certificate #1 Details: - //Original Format: PKCS7-PEM - //Subject: CN=IdenTrust Commercial Root TLS ECC CA 2,O=IdenTrust,C=US - //Issuer: CN=IdenTrust Commercial Root TLS ECC CA 2,O=IdenTrust,C=US - //Expiration Date: 2039-04-11 21:11:10 - //Serial Number: 40018ECF000DE911D7447B73E4C1F82E - //SHA256 Fingerprint: 983d826ba9c87f653ff9e8384c5413e1d59acf19ddc9c98cecae5fdea2ac229c - "sha256/uu5PB+MS9L3/ffB/PuTG6A+WjsTtTaF52qqjrcHFXRU=", - //Source URL: https://ssl-ccp.secureserver.net/repository/sfroot-g2.crt - //Certificate #1 Details: - //Original Format: PEM - //Subject: CN=Starfield Root Certificate Authority - G2, - // O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - //Issuer: CN=Starfield Root Certificate Authority - G2, - // O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - //Expiration Date: 2037-12-31 23:59:59 - //Serial Number: 0 - //SHA256 Fingerprint: 2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5 - "sha256/gI1os/q0iEpflxrOfRBVDXqVoWN3Tz7Dav/7IT++THQ=", - }; /** * Http constructor. @@ -227,13 +88,15 @@ protected Http(String inMethod, String inHost, String inUri, int timeout) { headers.add("user-agent", String.format("%s ca_bundle/%s (ca_pinning=%s)", UserAgentString, CA_BUNDLE_VERSION, "enabled")); - CertificatePinner pinner = Util.createPinner(host, DEFAULT_CA_CERTS); + TrustManagerFactory tmf = CertificateUtils.createDefaultTrustManagerFactory(); + SSLSocketFactory sslFactory = CertificateUtils.createSslSocketFactory(tmf); + X509TrustManager trustManager = CertificateUtils.getX509TrustManager(tmf); httpClient = new OkHttpClient.Builder() .connectTimeout(timeout, TimeUnit.SECONDS) .writeTimeout(timeout, TimeUnit.SECONDS) .readTimeout(timeout, TimeUnit.SECONDS) - .certificatePinner(pinner) + .sslSocketFactory(sslFactory, trustManager) .build(); } @@ -435,13 +298,17 @@ public void setProxy(String host, int port) { } /** - * Use custom CA certificates for certificate pinning. + * Use custom CA certificates for the trust store. * - * @param customCaCerts The CA certificates to pin + * @param pemContent PEM-encoded CA certificates as a String */ - public void useCustomCertificates(String[] customCaCerts) { - CertificatePinner pinner = Util.createPinner(host, customCaCerts); - httpClient = httpClient.newBuilder().certificatePinner(pinner).build(); + public void useCustomCertificates(String pemContent) { + TrustManagerFactory tmf = CertificateUtils.createTrustManagerFactory(pemContent); + SSLSocketFactory sslFactory = CertificateUtils.createSslSocketFactory(tmf); + X509TrustManager trustManager = CertificateUtils.getX509TrustManager(tmf); + httpClient = httpClient.newBuilder() + .sslSocketFactory(sslFactory, trustManager) + .build(); } /** @@ -449,8 +316,11 @@ public void useCustomCertificates(String[] customCaCerts) { * via the OS trust store. */ public void disableCaPinning() { + TrustManagerFactory tmf = CertificateUtils.getSystemTrustManagerFactory(); + SSLSocketFactory sslFactory = CertificateUtils.createSslSocketFactory(tmf); + X509TrustManager trustManager = CertificateUtils.getX509TrustManager(tmf); httpClient = httpClient.newBuilder() - .certificatePinner(CertificatePinner.DEFAULT) + .sslSocketFactory(sslFactory, trustManager) .build(); } @@ -558,7 +428,7 @@ protected abstract static class ClientBuilder { private int timeout = DEFAULT_TIMEOUT_SECS; private long maxBackoffMs = MAX_BACKOFF_MS; - private String[] caCerts = null; + private String customCertsContent = null; private boolean disableCaPinning = false; private SortedMap additionalDuoHeaders = new TreeMap(); private Map headers = new HashMap(); @@ -615,13 +485,13 @@ public ClientBuilder useMaxBackoffMs(long maxBackoffMs) { } /** - * Provide custom CA certificates for certificate pinning. + * Provide custom CA certificates for the trust store. * - * @param customCaCerts The CA certificates to pin to + * @param pemContent PEM-encoded CA certificates as a String * @return the Builder */ - public ClientBuilder useCustomCertificates(String[] customCaCerts) { - this.caCerts = customCaCerts; + public ClientBuilder useCustomCertificates(String pemContent) { + this.customCertsContent = pemContent; return this; } @@ -672,14 +542,14 @@ public ClientBuilder addHeader(String name, String value) { * @return the specified Http client object */ public T build() { - if (disableCaPinning && caCerts != null) { + if (disableCaPinning && customCertsContent != null) { throw new IllegalStateException( "Cannot both disable CA pinning and provide custom certificates"); } T duoClient = createClient(method, host, uri, timeout); duoClient.setMaxBackoffMs(maxBackoffMs); - if (caCerts != null) { - duoClient.useCustomCertificates(caCerts); + if (customCertsContent != null) { + duoClient.useCustomCertificates(customCertsContent); } if (disableCaPinning) { duoClient.disableCaPinning(); diff --git a/duo-client/src/main/java/com/duosecurity/client/Util.java b/duo-client/src/main/java/com/duosecurity/client/Util.java index 76d18e0..6f14444 100644 --- a/duo-client/src/main/java/com/duosecurity/client/Util.java +++ b/duo-client/src/main/java/com/duosecurity/client/Util.java @@ -6,7 +6,6 @@ import java.security.NoSuchAlgorithmException; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import okhttp3.CertificatePinner; public class Util { /** @@ -72,20 +71,6 @@ public static String join(Object[] s, String joiner) { return out.toString(); } - /** - * Create a certificate pinner for the specified CA certificates. - * - * @param apiHost the host for pinning - * @param caCerts the certificates to pin to - * @return a CertificatePinner - */ - public static CertificatePinner createPinner(String apiHost, String[] caCerts) { - CertificatePinner pinner = new CertificatePinner.Builder() - .add(apiHost, caCerts) - .build(); - - return pinner; - } /** * Create hash byte array of message. diff --git a/duo-client/src/main/resources/duo-ca-certs/ca_certs.pem b/duo-client/src/main/resources/duo-ca-certs/ca_certs.pem new file mode 100644 index 0000000..564146a --- /dev/null +++ b/duo-client/src/main/resources/duo-ca-certs/ca_certs.pem @@ -0,0 +1,489 @@ +# Source URL: https://www.amazontrust.com/repository/AmazonRootCA1.cer +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=Amazon Root CA 1,O=Amazon,C=US +# Issuer: CN=Amazon Root CA 1,O=Amazon,C=US +# Expiration Date: 2038-01-17 00:00:00 +# Serial Number: 66C9FCF99BF8C0A39E2F0788A43E696365BCA +# SHA256 Fingerprint: 8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e + +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + + +# Source URL: https://www.amazontrust.com/repository/AmazonRootCA2.cer +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=Amazon Root CA 2,O=Amazon,C=US +# Issuer: CN=Amazon Root CA 2,O=Amazon,C=US +# Expiration Date: 2040-05-26 00:00:00 +# Serial Number: 66C9FD29635869F0A0FE58678F85B26BB8A37 +# SHA256 Fingerprint: 1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4 + +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK +gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ +W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg +1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K +8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r +2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me +z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR +8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj +mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz +7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 ++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI +0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm +UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 +LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS +k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl +7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm +btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl +urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ +fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 +n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE +76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H +9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT +4PsJYGw= +-----END CERTIFICATE----- + + +# Source URL: https://www.amazontrust.com/repository/AmazonRootCA3.cer +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=Amazon Root CA 3,O=Amazon,C=US +# Issuer: CN=Amazon Root CA 3,O=Amazon,C=US +# Expiration Date: 2040-05-26 00:00:00 +# Serial Number: 66C9FD5749736663F3B0B9AD9E89E7603F24A +# SHA256 Fingerprint: 18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4 + +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl +ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr +ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr +BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM +YyRIHN8wfdVoOw== +-----END CERTIFICATE----- + + +# Source URL: https://www.amazontrust.com/repository/AmazonRootCA4.cer +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=Amazon Root CA 4,O=Amazon,C=US +# Issuer: CN=Amazon Root CA 4,O=Amazon,C=US +# Expiration Date: 2040-05-26 00:00:00 +# Serial Number: 66C9FD7C1BB104C2943E5717B7B2CC81AC10E +# SHA256 Fingerprint: e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092 + +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi +9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk +M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB +MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw +CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW +1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + + +# Source URL: https://www.amazontrust.com/repository/SFSRootCAG2.cer +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US +# Issuer: CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US +# Expiration Date: 2037-12-31 23:59:59 +# Serial Number: 0 +# SHA256 Fingerprint: 568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5 + +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- + + +# Source URL: https://cacerts.digicert.com/DigiCertHighAssuranceEVRootCA.crt +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# Issuer: CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US +# Expiration Date: 2031-11-10 00:00:00 +# Serial Number: 2AC5C266A0B409B8F0B79F2AE462577 +# SHA256 Fingerprint: 7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf + +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- + + +# Source URL: https://cacerts.digicert.com/DigiCertTLSECCP384RootG5.crt +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=DigiCert TLS ECC P384 Root G5,O=DigiCert\, Inc.,C=US +# Issuer: CN=DigiCert TLS ECC P384 Root G5,O=DigiCert\, Inc.,C=US +# Expiration Date: 2046-01-14 23:59:59 +# Serial Number: 9E09365ACF7D9C8B93E1C0B042A2EF3 +# SHA256 Fingerprint: 018e13f0772532cf809bd1b17281867283fc48c6e13be9c69812854a490c1b05 + +-----BEGIN CERTIFICATE----- +MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp +Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2 +MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ +bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS +7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp +0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS +B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49 +BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ +LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4 +DXZDjC5Ty3zfDBeWUA== +-----END CERTIFICATE----- + + +# Source URL: https://cacerts.digicert.com/DigiCertTLSRSA4096RootG5.crt +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=DigiCert TLS RSA4096 Root G5,O=DigiCert\, Inc.,C=US +# Issuer: CN=DigiCert TLS RSA4096 Root G5,O=DigiCert\, Inc.,C=US +# Expiration Date: 2046-01-14 23:59:59 +# Serial Number: 8F9B478A8FA7EDA6A333789DE7CCF8A +# SHA256 Fingerprint: 371a00dc0533b3721a7eeb40e8419e70799d2b0a0f2c1d80693165f7cec4ad75 + +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN +MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT +HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN +NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs +IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+ +ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0 +2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp +wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM +pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD +nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po +sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx +Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd +Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX +KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe +XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL +tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv +TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN +AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw +GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H +PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF +O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ +REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik +AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv +/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+ +p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw +MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF +qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK +ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+ +-----END CERTIFICATE----- + + +# Source URL: https://secure.globalsign.com/cacert/rootr46.crt +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=GlobalSign Root R46,O=GlobalSign nv-sa,C=BE +# Issuer: CN=GlobalSign Root R46,O=GlobalSign nv-sa,C=BE +# Expiration Date: 2046-03-20 00:00:00 +# Serial Number: 11D2BBB9D723189E405F0A9D2DD0DF2567D1 +# SHA256 Fingerprint: 4fa3126d8d3a11d1c4855a4f807cbad6cf919d3a5a88b03bea2c6372d93c40c9 + +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA +MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD +VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy +MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt +c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ +OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG +vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud +316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo +0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE +y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF +zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE ++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN +I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs +x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa +ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC +4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 +7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti +2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk +pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF +FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt +rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk +ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 +u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP +4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 +N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 +vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 +-----END CERTIFICATE----- + + +# Source URL: https://secure.globalsign.com/cacert/roote46.crt +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=GlobalSign Root E46,O=GlobalSign nv-sa,C=BE +# Issuer: CN=GlobalSign Root E46,O=GlobalSign nv-sa,C=BE +# Expiration Date: 2046-03-20 00:00:00 +# Serial Number: 11D2BBBA336ED4BCE62468C50D841D98E843 +# SHA256 Fingerprint: cbb9c44d84b8043e1050ea31a69f514955d7bfd2e2c6b49301019ad61d9f5058 + +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx +CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD +ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw +MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex +HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq +R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd +yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ +7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 ++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- + + +# Source URL: https://i.pki.goog/r2.crt +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=GTS Root R2,O=Google Trust Services LLC,C=US +# Issuer: CN=GTS Root R2,O=Google Trust Services LLC,C=US +# Expiration Date: 2036-06-22 00:00:00 +# Serial Number: 203E5AEC58D04251AAB1125AA +# SHA256 Fingerprint: 8d25cd97229dbf70356bda4eb3cc734031e24cf00fafcfd32dc76eb5841c7ea8 + +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt +nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY +6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu +MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k +RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg +f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV ++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo +dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW +Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa +G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq +gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H +vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 +0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC +B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u +NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg +yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev +HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6 +xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR +TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg +JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV +7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl +6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL +-----END CERTIFICATE----- + + +# Source URL: https://i.pki.goog/r4.crt +# Certificate #1 Details: +# Original Format: DER +# Subject: CN=GTS Root R4,O=Google Trust Services LLC,C=US +# Issuer: CN=GTS Root R4,O=Google Trust Services LLC,C=US +# Expiration Date: 2036-06-22 00:00:00 +# Serial Number: 203E5C068EF631A9C72905052 +# SHA256 Fingerprint: 349dfa4058c5e263123b398ae795573c4e1313c83fe68f93556cd5e8031b3c7d + +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi +QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR +HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D +9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 +p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD +-----END CERTIFICATE----- + + +# Source URL: https://www.identrust.com/file-download/download/public/5718 +# Certificate #1 Details: +# Original Format: PKCS7-DER +# Subject: CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US +# Issuer: CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US +# Expiration Date: 2034-01-16 18:12:23 +# Serial Number: A0142800000014523C844B500000002 +# SHA256 Fingerprint: 5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae + +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu +VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw +MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw +JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT +3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU ++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp +S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 +bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi +T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL +vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK +Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK +dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT +c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv +l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N +iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD +ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt +LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 +nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 ++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK +W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT +AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq +l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG +4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ +mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A +7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + + +# Source URL: https://www.identrust.com/file-download/download/public/5842 +# Certificate #1 Details: +# Original Format: PKCS7-PEM +# Subject: CN=IdenTrust Commercial Root TLS ECC CA 2,O=IdenTrust,C=US +# Issuer: CN=IdenTrust Commercial Root TLS ECC CA 2,O=IdenTrust,C=US +# Expiration Date: 2039-04-11 21:11:10 +# Serial Number: 40018ECF000DE911D7447B73E4C1F82E +# SHA256 Fingerprint: 983d826ba9c87f653ff9e8384c5413e1d59acf19ddc9c98cecae5fdea2ac229c + +-----BEGIN CERTIFICATE----- +MIICbDCCAc2gAwIBAgIQQAGOzwAN6RHXRHtz5MH4LjAKBggqhkjOPQQDBDBSMQsw +CQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MS8wLQYDVQQDEyZJZGVuVHJ1 +c3QgQ29tbWVyY2lhbCBSb290IFRMUyBFQ0MgQ0EgMjAeFw0yNDA0MTEyMTExMTFa +Fw0zOTA0MTEyMTExMTBaMFIxCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlJZGVuVHJ1 +c3QxLzAtBgNVBAMTJklkZW5UcnVzdCBDb21tZXJjaWFsIFJvb3QgVExTIEVDQyBD +QSAyMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBwomiZTgLg8KqEImMmnO5rNPb +Oo9sv5w4nJh45CXs9Gcu8YET9ulxsyVBCVSfSYeppdtXFEWYyBi0QRCAlp5YZHQB +H675v5rWVKRXvhzsuUNi9Xw0Zy1bAXaikmsrY/J0L52j2RulW4q4WvE7f23VFwZu +d82J8k0YG+M4MpmdOho1rsKjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdDgQWBBQhNGgGrnXhVx/FuQqjXpuH+IlbwzAKBggqhkjOPQQD +BAOBjAAwgYgCQgDc9F4WOxAgci2uQWfsX9cjeIvDXaaeVjDz31Ycc+ZdPrK1JKrB +f6CuTwWy8VojtGxdM3PJMkJC4LGPuhcvkHLo4gJCAV5h+PXe4bDJ3QxE8hkGFoUW +Ak6KtMCIpbLyt5pHrROi+YW9MpScoNGJkg96G1ETvJTWz6dv0uQYjKXt3jlOfQ7g +-----END CERTIFICATE----- + + +# Source URL: https://ssl-ccp.secureserver.net/repository/sfroot-g2.crt +# Certificate #1 Details: +# Original Format: PEM +# Subject: CN=Starfield Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US +# Issuer: CN=Starfield Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US +# Expiration Date: 2037-12-31 23:59:59 +# Serial Number: 0 +# SHA256 Fingerprint: 2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5 + +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + diff --git a/duo-client/src/test/java/com/duosecurity/client/CertificateUtilsTest.java b/duo-client/src/test/java/com/duosecurity/client/CertificateUtilsTest.java new file mode 100644 index 0000000..4efd7be --- /dev/null +++ b/duo-client/src/test/java/com/duosecurity/client/CertificateUtilsTest.java @@ -0,0 +1,66 @@ +package com.duosecurity.client; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import org.junit.Test; + +public class CertificateUtilsTest { + + @Test + public void testCreateDefaultTrustManagerFactory() { + TrustManagerFactory tmf = CertificateUtils.createDefaultTrustManagerFactory(); + assertNotNull("TrustManagerFactory should not be null", tmf); + } + + @Test + public void testDefaultBundleContainsCertificates() { + TrustManagerFactory tmf = CertificateUtils.createDefaultTrustManagerFactory(); + X509TrustManager trustManager = CertificateUtils.getX509TrustManager(tmf); + X509Certificate[] acceptedIssuers = trustManager.getAcceptedIssuers(); + assertTrue("Bundle should contain certificates", acceptedIssuers.length > 0); + } + + @Test + public void testCreateSslSocketFactory() { + TrustManagerFactory tmf = CertificateUtils.createDefaultTrustManagerFactory(); + SSLSocketFactory factory = CertificateUtils.createSslSocketFactory(tmf); + assertNotNull("SSLSocketFactory should not be null", factory); + } + + @Test + public void testGetX509TrustManager() { + TrustManagerFactory tmf = CertificateUtils.createDefaultTrustManagerFactory(); + X509TrustManager trustManager = CertificateUtils.getX509TrustManager(tmf); + assertNotNull("X509TrustManager should not be null", trustManager); + } + + @Test + public void testGetSystemTrustManagerFactory() { + TrustManagerFactory tmf = CertificateUtils.getSystemTrustManagerFactory(); + assertNotNull("System TrustManagerFactory should not be null", tmf); + X509TrustManager trustManager = CertificateUtils.getX509TrustManager(tmf); + assertNotNull("System X509TrustManager should not be null", trustManager); + } + + @Test(expected = IllegalArgumentException.class) + public void testEmptyPemThrowsException() { + InputStream emptyStream = new ByteArrayInputStream( + "".getBytes(StandardCharsets.UTF_8)); + CertificateUtils.createTrustManagerFactory(emptyStream); + } + + @Test(expected = IllegalStateException.class) + public void testInvalidPemThrowsException() { + InputStream invalidStream = new ByteArrayInputStream( + "not a certificate".getBytes(StandardCharsets.UTF_8)); + CertificateUtils.createTrustManagerFactory(invalidStream); + } +} diff --git a/duo-client/src/test/java/com/duosecurity/client/HttpDisableCaPinningTest.java b/duo-client/src/test/java/com/duosecurity/client/HttpDisableCaPinningTest.java index 5f13085..c8fc2b9 100644 --- a/duo-client/src/test/java/com/duosecurity/client/HttpDisableCaPinningTest.java +++ b/duo-client/src/test/java/com/duosecurity/client/HttpDisableCaPinningTest.java @@ -1,11 +1,10 @@ package com.duosecurity.client; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; import java.lang.reflect.Field; -import java.util.Set; -import okhttp3.CertificatePinner; +import javax.net.ssl.SSLSocketFactory; import okhttp3.OkHttpClient; import org.junit.Test; @@ -17,46 +16,46 @@ private OkHttpClient getHttpClient(Http http) throws Exception { return (OkHttpClient) httpClientField.get(http); } - @SuppressWarnings("unchecked") - private Set getPins(CertificatePinner pinner) throws Exception { - Field pinsField = CertificatePinner.class.getDeclaredField("pins"); - pinsField.setAccessible(true); - return (Set) pinsField.get(pinner); - } - @Test - public void testDisableCaPinning_removesPin() throws Exception { + public void testDefaultBuilder_hasCustomSslFactory() throws Exception { Http http = new Http.HttpBuilder("GET", "api-host.duosecurity.com", "/auth/v2/check") - .disableCaPinning() .build(); OkHttpClient client = getHttpClient(http); - Set pins = getPins(client.certificatePinner()); - assertTrue("Pins should be empty when CA pinning is disabled", pins.isEmpty()); + SSLSocketFactory factory = client.sslSocketFactory(); + assertNotNull("SSLSocketFactory should not be null", factory); + + // Verify it's not the same instance as a default OkHttpClient would use + OkHttpClient defaultClient = new OkHttpClient(); + assertNotSame("Should use custom SSL factory instance, not OkHttp default", + defaultClient.sslSocketFactory(), factory); } @Test - public void testDefaultBuilder_hasPinning() throws Exception { + public void testDisableCaPinning_usesSystemTrustStore() throws Exception { Http http = new Http.HttpBuilder("GET", "api-host.duosecurity.com", "/auth/v2/check") + .disableCaPinning() .build(); OkHttpClient client = getHttpClient(http); - Set pins = getPins(client.certificatePinner()); - assertFalse("Pins should not be empty by default", pins.isEmpty()); + SSLSocketFactory factory = client.sslSocketFactory(); + assertNotNull("SSLSocketFactory should not be null", factory); } @Test(expected = IllegalStateException.class) public void testDisableAndCustomCerts_throws() { + String pemContent = "-----BEGIN CERTIFICATE-----\ntest\n-----END CERTIFICATE-----"; new Http.HttpBuilder("GET", "api-host.duosecurity.com", "/auth/v2/check") .disableCaPinning() - .useCustomCertificates(new String[]{"sha256/test"}) + .useCustomCertificates(pemContent) .build(); } @Test(expected = IllegalStateException.class) public void testCustomCertsAndDisable_throws() { + String pemContent = "-----BEGIN CERTIFICATE-----\ntest\n-----END CERTIFICATE-----"; new Http.HttpBuilder("GET", "api-host.duosecurity.com", "/auth/v2/check") - .useCustomCertificates(new String[]{"sha256/test"}) + .useCustomCertificates(pemContent) .disableCaPinning() .build(); }