Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Last active April 4, 2025 23:08
Show Gist options
  • Save salrashid123/c165c6c267fa1d121385bf2eaf60d34b to your computer and use it in GitHub Desktop.
Save salrashid123/c165c6c267fa1d121385bf2eaf60d34b to your computer and use it in GitHub Desktop.
Envoy EKM : extract the EKM value for a TLS connection with envoy

The following diff extracts the EKM value for a given TLS connection and then surfaces that to LUA (which emits the EKM as a header to the backend)

the LUA config will log the EKM in trace logs

# envoy -c envoy_server.yaml -l trace
[2025-04-04 08:36:29.396][3334775][info][lua] [source/extensions/filters/common/lua/lua.cc:26] script log: >>>>>>>>>>>> EKM: XGurfnlqXyjXphhJrrCmHRoKXAwC7CjrD7vixHdqOIo=

which has the same derived EKM value as a sample client app (eg, golang)

$ go run main.go 
EKM EXPORTER-my_ekm: XGurfnlqXyjXphhJrrCmHRoKXAwC7CjrD7vixHdqOIo=
200 OK
{
  "args": {}, 
  "headers": {
    "Accept-Encoding": "gzip", 
    "Ekm": "XGurfnlqXyjXphhJrrCmHRoKXAwC7CjrD7vixHdqOIo=", 
    "Host": "httpbin.org", 
    "User-Agent": "Go-http-client/1.1", 
    "X-Amzn-Trace-Id": "Root=1-67efd24d-09847a992febb3400b88e963", 
    "X-Envoy-Expected-Rq-Timeout-Ms": "15000"
  }, 
  "url": "https://httpbin.org/get"
}

Also see


  • ekm.diff (from envoy commit 9faa0a3c19018bd23985d1e0aaa94cd5546c9c35)
diff --git a/envoy/ssl/connection.h b/envoy/ssl/connection.h
index b9e968a524..1398c9f69c 100644
--- a/envoy/ssl/connection.h
+++ b/envoy/ssl/connection.h
@@ -225,6 +225,8 @@ public:
    * @return std::string the SNI used to establish the connection.
    **/
   virtual const std::string& sni() const PURE;
+
+  virtual const std::string& ekm() const PURE;
 };
 
 using ConnectionInfoConstSharedPtr = std::shared_ptr<const ConnectionInfo>;
diff --git a/source/common/tls/connection_info_impl_base.cc b/source/common/tls/connection_info_impl_base.cc
index 24019df89b..251dcabb87 100644
--- a/source/common/tls/connection_info_impl_base.cc
+++ b/source/common/tls/connection_info_impl_base.cc
@@ -7,6 +7,8 @@
 
 #include "absl/strings/str_replace.h"
 #include "openssl/err.h"
+
+#include "openssl/ssl.h"
 #include "openssl/safestack.h"
 #include "openssl/x509v3.h"
 #include "utility.h"
@@ -110,6 +112,31 @@ const std::string& ConnectionInfoImplBase::sha256PeerCertificateDigest() const {
       });
 }
 
+size_t string_length(const uint8_t* str) {
+  size_t length = 0;
+  while (str[length] != '\0') {
+      length++;
+  }
+  return length;
+}
+
+const std::string& ConnectionInfoImplBase::ekm() const {
+  return getCachedValueOrCreate<std::string>(CachedValueTag::EKM, [](SSL* ssl) {
+    const char *klabel = "EXPORTER-my_ekm";
+    const uint8_t* kcontext = reinterpret_cast<const uint8_t*>("my_context");
+
+    size_t size = 32;
+    uint8_t* buf = new uint8_t[size];
+    
+    //int rs = SSL_export_keying_material(ssl,buf,size , klabel, strlen(klabel),NULL, 0, 0);
+    int rs = SSL_export_keying_material(ssl,buf,size , klabel, strlen(klabel),kcontext, string_length(kcontext), 1);    
+    if (rs == 1) {
+      return std::string(reinterpret_cast<const char*>(buf),size);
+    }
+    return std::string{};
+  });
+}
+
 absl::Span<const std::string> ConnectionInfoImplBase::sha256PeerCertificateChainDigests() const {
   return getCachedValueOrCreate<std::vector<std::string>>(
       CachedValueTag::Sha256PeerCertificateChainDigests, [](SSL* ssl) {
diff --git a/source/common/tls/connection_info_impl_base.h b/source/common/tls/connection_info_impl_base.h
index b386e99b1d..6f08a38b4c 100644
--- a/source/common/tls/connection_info_impl_base.h
+++ b/source/common/tls/connection_info_impl_base.h
@@ -52,6 +52,7 @@ public:
   const std::string& tlsVersion() const override;
   const std::string& alpn() const override;
   const std::string& sni() const override;
+  const std::string& ekm() const override;
 
   virtual SSL* ssl() const PURE;
 
@@ -86,6 +87,7 @@ private:
     IpSansPeerCertificate,
     OidsPeerCertificate,
     OidsLocalCertificate,
+    EKM,
   };
 
   // Retrieve the given tag from the set of cached values, or create the value via the supplied
diff --git a/source/extensions/filters/common/expr/context.cc b/source/extensions/filters/common/expr/context.cc
index 00d6139a4d..3253934b9d 100644
--- a/source/extensions/filters/common/expr/context.cc
+++ b/source/extensions/filters/common/expr/context.cc
@@ -83,6 +83,13 @@ const SslExtractorsValues& SslExtractorsValues::get() {
                                 }
                                 return CelValue::CreateString(&info.dnsSansPeerCertificate()[0]);
                               }},
+                              {EKM,
+                                [](const Ssl::ConnectionInfo& info) -> absl::optional<CelValue> {
+                                  if (info.ekm().empty()) {
+                                    return {};
+                                  }
+                                  return CelValue::CreateString(&info.ekm());
+                              }},
                              {SHA256PeerCertificateDigest,
                               [](const Ssl::ConnectionInfo& info) -> absl::optional<CelValue> {
                                 if (info.sha256PeerCertificateDigest().empty()) {
diff --git a/source/extensions/filters/common/expr/context.h b/source/extensions/filters/common/expr/context.h
index 48ddf83dd1..af4bb0c03c 100644
--- a/source/extensions/filters/common/expr/context.h
+++ b/source/extensions/filters/common/expr/context.h
@@ -71,6 +71,7 @@ constexpr absl::string_view DNSSanLocalCertificate = "dns_san_local_certificate"
 constexpr absl::string_view DNSSanPeerCertificate = "dns_san_peer_certificate";
 constexpr absl::string_view SHA256PeerCertificateDigest = "sha256_peer_certificate_digest";
 constexpr absl::string_view DownstreamTransportFailureReason = "transport_failure_reason";
+constexpr absl::string_view EKM = "ekm";
 
 // Source properties
 constexpr absl::string_view Source = "source";
diff --git a/source/extensions/filters/common/lua/wrappers.cc b/source/extensions/filters/common/lua/wrappers.cc
index f440b88a71..7b6d5e1b1b 100644
--- a/source/extensions/filters/common/lua/wrappers.cc
+++ b/source/extensions/filters/common/lua/wrappers.cc
@@ -382,6 +382,12 @@ int SslConnectionWrapper::luaCiphersuiteString(lua_State* state) {
   return 1;
 }
 
+int SslConnectionWrapper::luaEKM(lua_State* state) {
+  const std::string& e = connection_info_.ekm();
+  lua_pushlstring(state, e.data(), e.size());
+  return 1;
+}
+
 int SslConnectionWrapper::luaUrlEncodedPemEncodedPeerCertificate(lua_State* state) {
   const std::string& peer_cert_pem = connection_info_.urlEncodedPemEncodedPeerCertificate();
   lua_pushlstring(state, peer_cert_pem.data(), peer_cert_pem.size());
diff --git a/source/extensions/filters/common/lua/wrappers.h b/source/extensions/filters/common/lua/wrappers.h
index d474555272..3e28322bc9 100644
--- a/source/extensions/filters/common/lua/wrappers.h
+++ b/source/extensions/filters/common/lua/wrappers.h
@@ -170,6 +170,7 @@ public:
             {"sessionId", static_luaSessionId},
             {"ciphersuiteId", static_luaCiphersuiteId},
             {"ciphersuiteString", static_luaCiphersuiteString},
+            {"ekm", static_luaEKM},
             {"urlEncodedPemEncodedPeerCertificate", static_luaUrlEncodedPemEncodedPeerCertificate},
             {"urlEncodedPemEncodedPeerCertificateChain",
              static_luaUrlEncodedPemEncodedPeerCertificateChain},
@@ -300,6 +301,9 @@ private:
    */
   DECLARE_LUA_FUNCTION(SslConnectionWrapper, luaCiphersuiteString);
 
+
+  DECLARE_LUA_FUNCTION(SslConnectionWrapper, luaEKM);
+
   /**
    * Returns the TLS version (e.g. TLSv1.2, TLSv1.3) used in the established TLS connection. Returns
    * string if secured and nil if not.
  • envoy_server.yaml
node:
  cluster: service_greeter
  id: test-id

admin:
  access_log_path: /dev/null
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9000


static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8081 }
    listener_filters:
    - name: envoy.filters.listener.tls_inspector
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
    - name: envoy.filters.listener.http_inspector
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.filters.listener.http_inspector.v3.HttpInspector    
    filter_chains:
    - filter_chain_match:
        server_names: ["httpbin.org"]
      transport_socket:
        name: envoy.transport_sockets.tls
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
          common_tls_context:
            tls_certificates:
            - certificate_chain:
                filename: certs/httpbin.crt
              private_key:
                filename: certs/httpbin.key    
      filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          route_config:
            virtual_hosts:
            - name: httpbin_service
              domains: ["httpbin.org"]
              routes:
              - match: 
                  path: "/get"          
                route:
                  cluster: dynamic_forward_proxy_cluster
                typed_per_filter_config:
                  envoy.filters.http.dynamic_forward_proxy:
                    '@type': type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.PerRouteConfig     
          http_filters:
          - name: envoy.filters.http.lua
            typed_config:   
              '@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
              inlineCode: |

                local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
                function enc(data)
                    return ((data:gsub('.', function(x) 
                        local r,b='',x:byte()
                        for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
                        return r;
                    end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
                        if (#x < 6) then return '' end
                        local c=0
                        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
                        return b:sub(c+1,c+1)
                    end)..({ '', '==', '=' })[#data%3+1])
                end

                function envoy_on_request(request_handle)
                  local stream = request_handle:streamInfo()

                  ekm_header = request_handle:headers():get("X-Custom-EKM")

                  if ekm_header == nil then
                    request_handle:respond({[":status"] = "403"},"ekm not found")                      
                  else
                    if stream:downstreamSslConnection():ekm() ~= nil then
                      local peerDigest = stream:downstreamSslConnection():ekm()
                      local peerSig =enc(peerDigest)
                      request_handle:logInfo(">>>>>>>>>>>> EKM: "..peerSig)

                      if ekm_header == peerSig then
                        request_handle:headers():add("EKM", peerSig)
                      else
                        request_handle:respond({[":status"] = "403"},"ekm header mismatch")
                      end
                    else                   
                      request_handle:respond({[":status"] = "403"},"error extracting EKM")
                    end  
                  end

                end                
          - name: envoy.filters.http.dynamic_forward_proxy
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig
              dns_cache_config:
                name: dynamic_forward_proxy_cache_config
                dns_lookup_family: V4_ONLY     
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router  
  clusters:
  - name: dynamic_forward_proxy_cluster
    lb_policy: CLUSTER_PROVIDED
    connect_timeout: 5s
    http2_protocol_options: {}    
    cluster_type:
      name: envoy.clusters.dynamic_forward_proxy
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
        dns_cache_config:
          name: dynamic_forward_proxy_cache_config
          dns_lookup_family: V4_ONLY
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        common_tls_context:
          validation_context:
            trusted_ca:
              filename: /etc/ssl/certs/ca-certificates.crt    
  • main.go
package main

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
)

var (
	ekm []byte
)

func main() {

	caCert, err := os.ReadFile("certs/root-ca.crt")
	if err != nil {
		fmt.Printf("Error reading cacert %v\n", err)
		return
	}

	serverCertPool := x509.NewCertPool()
	serverCertPool.AppendCertsFromPEM(caCert)

	tlsConfig := &tls.Config{
		ServerName: "httpbin.org",
		RootCAs:    serverCertPool,
	}

	conn, err := tls.Dial("tcp", "localhost:8081", tlsConfig)
	if err != nil {
		fmt.Printf("Error dialing %v\n", err)
		return
	}
	cs := conn.ConnectionState()

	ekm, err = cs.ExportKeyingMaterial("EXPORTER-my_ekm", []byte("my_context"), 32)
	//ekm, err = cs.ExportKeyingMaterial("EXPORTER-my_ekm", []byte(nil), 32)
	if err != nil {
		fmt.Printf("Error getting ekm %v\n", err)
		return
	}
	fmt.Printf("EKM EXPORTER-my_ekm: %s\n", base64.StdEncoding.EncodeToString(ekm))

	tr := &http.Transport{
		DialTLSContext: func(ctx context.Context, network string, addr string) (net.Conn, error) {
			return conn, nil
		},
	}
	client := http.Client{
		Transport: tr,
	}

	req, err := http.NewRequest(http.MethodGet, "https://httpbin.org/get", nil)
	if err != nil {
		fmt.Printf("Error creating request %v\n", err)
		return
	}

	req.Header.Add("X-Custom-EKM", base64.StdEncoding.EncodeToString(ekm))

	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("Error making request %v\n", err)
		return
	}

	htmlData, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("Error response %v\n", err)
		return
	}
	defer resp.Body.Close()
	fmt.Printf("%v\n", resp.Status)
	fmt.Printf("%s\n", string(htmlData))

}

  • httpbin.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 46 (0x2e)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Google, OU=Enterprise, CN=Single Root CA
        Validity
            Not Before: Nov 17 12:17:20 2024 GMT
            Not After : Nov 17 12:17:20 2034 GMT
        Subject: C=US, O=Google, OU=Enterprise, CN=httpbin.org
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:a6:95:81:de:6e:97:17:6e:fb:27:6b:7c:d2:06:
                    a6:1e:83:eb:e5:18:75:d7:b0:01:07:36:1d:b0:11:
                    d3:90:d7:f1:77:68:d8:f7:b5:34:d5:40:e4:70:21:
                    a5:9a:67:85:ac:b6:8c:05:7d:3c:3f:e9:1c:10:e4:
                    bd:94:29:1d:7d:27:c4:a0:92:5d:f7:bb:b4:e2:6d:
                    c0:7f:e0:46:b5:61:33:b3:f3:5d:3a:80:ae:8e:3a:
                    88:1e:09:bc:cc:b4:43:87:14:52:2e:2b:60:08:04:
                    12:23:06:1f:f0:c2:75:ff:d3:56:6c:e3:3d:c3:e7:
                    ee:8b:df:47:2d:e8:6c:a3:21:d8:04:05:a7:2a:ed:
                    a2:3a:36:b6:ce:24:d3:15:cf:ff:e1:25:40:6e:67:
                    c8:cc:2f:22:00:87:ce:7a:0b:18:c2:ac:f4:12:9f:
                    c8:10:ea:6c:86:23:dc:65:95:f6:18:7a:1a:b8:33:
                    b2:ee:71:4e:eb:8a:28:23:7b:e4:8f:4a:18:58:15:
                    46:b4:7a:b4:cc:dc:71:1b:2f:3d:d1:1d:7c:3b:b0:
                    7b:b4:b0:51:cb:a8:5c:c0:6b:80:65:2f:3f:01:93:
                    6d:5f:b0:0f:82:c8:ef:63:9f:ff:60:e8:d8:6d:51:
                    81:2d:bb:18:73:f8:7e:61:75:67:07:a7:43:f8:87:
                    12:31
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Subject Key Identifier: 
                DF:F9:3C:DC:25:48:11:1A:63:6B:39:D2:4D:E2:10:59:3A:BC:73:0B
            X509v3 Authority Key Identifier: 
                EC:F0:EA:53:53:3F:9F:23:DC:C1:0E:31:10:37:07:DE:DE:E7:6E:F3
            Authority Information Access: 
                CA Issuers - URI:http://pki.esodemoapp2.com/ca/root-ca.cer
            X509v3 CRL Distribution Points: 
                Full Name:
                  URI:http://pki.esodemoapp2.com/ca/root-ca.crl
            X509v3 Subject Alternative Name: 
                DNS:httpbin.org
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        1a:ba:c8:ad:44:8c:77:20:a4:ce:eb:14:07:52:86:31:df:1a:
        bf:e4:48:c2:c2:10:dc:4d:0d:d9:6b:85:2e:ad:b9:f3:bd:f3:
        f8:17:93:b9:47:2f:bf:43:72:6b:30:c5:63:2a:5c:d8:7a:7f:
        14:05:27:aa:26:ed:9b:7a:0e:63:00:e4:4f:9e:58:82:df:4e:
        a5:72:20:3c:df:a7:50:3f:cd:f9:54:7b:ed:b2:e4:0f:82:cd:
        c1:ff:25:9b:5b:b5:7f:6b:a4:77:8e:ac:6d:b7:86:63:07:c0:
        0e:e4:21:4a:f6:c1:30:3c:eb:0f:c5:95:08:2e:4e:2b:34:13:
        d2:d7:fc:b5:a2:b7:96:7f:6c:51:e7:24:04:63:c3:b9:e0:58:
        6a:ad:dc:e0:2f:a4:1a:45:ba:87:7e:be:67:b1:72:17:0d:ae:
        be:08:1c:b9:23:e3:4d:44:05:f3:48:fe:0c:8d:2b:5c:92:23:
        8d:2e:31:8f:af:eb:7c:70:53:36:f6:aa:e3:33:c3:cc:61:90:
        8b:f4:47:ff:fe:fb:c6:1b:ce:25:ca:61:e8:c9:a8:e3:94:ef:
        84:11:4f:b7:0e:bf:d3:87:7f:3f:bc:80:9d:ad:75:af:e9:95:
        06:22:c3:c3:81:4a:1f:46:b6:69:50:79:a6:3d:d7:85:d7:cd:
        03:94:69:4e
-----BEGIN CERTIFICATE-----
MIIEITCCAwmgAwIBAgIBLjANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEP
MA0GA1UECgwGR29vZ2xlMRMwEQYDVQQLDApFbnRlcnByaXNlMRcwFQYDVQQDDA5T
aW5nbGUgUm9vdCBDQTAeFw0yNDExMTcxMjE3MjBaFw0zNDExMTcxMjE3MjBaMEkx
CzAJBgNVBAYTAlVTMQ8wDQYDVQQKDAZHb29nbGUxEzARBgNVBAsMCkVudGVycHJp
c2UxFDASBgNVBAMMC2h0dHBiaW4ub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAppWB3m6XF277J2t80gamHoPr5Rh117ABBzYdsBHTkNfxd2jY97U0
1UDkcCGlmmeFrLaMBX08P+kcEOS9lCkdfSfEoJJd97u04m3Af+BGtWEzs/NdOoCu
jjqIHgm8zLRDhxRSLitgCAQSIwYf8MJ1/9NWbOM9w+fui99HLehsoyHYBAWnKu2i
Oja2ziTTFc//4SVAbmfIzC8iAIfOegsYwqz0Ep/IEOpshiPcZZX2GHoauDOy7nFO
64ooI3vkj0oYWBVGtHq0zNxxGy890R18O7B7tLBRy6hcwGuAZS8/AZNtX7APgsjv
Y5//YOjYbVGBLbsYc/h+YXVnB6dD+IcSMQIDAQABo4IBDzCCAQswDgYDVR0PAQH/
BAQDAgeAMAkGA1UdEwQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0OBBYE
FN/5PNwlSBEaY2s50k3iEFk6vHMLMB8GA1UdIwQYMBaAFOzw6lNTP58j3MEOMRA3
B97e527zMEUGCCsGAQUFBwEBBDkwNzA1BggrBgEFBQcwAoYpaHR0cDovL3BraS5l
c29kZW1vYXBwMi5jb20vY2Evcm9vdC1jYS5jZXIwOgYDVR0fBDMwMTAvoC2gK4Yp
aHR0cDovL3BraS5lc29kZW1vYXBwMi5jb20vY2Evcm9vdC1jYS5jcmwwFgYDVR0R
BA8wDYILaHR0cGJpbi5vcmcwDQYJKoZIhvcNAQELBQADggEBABq6yK1EjHcgpM7r
FAdShjHfGr/kSMLCENxNDdlrhS6tufO98/gXk7lHL79DcmswxWMqXNh6fxQFJ6om
7Zt6DmMA5E+eWILfTqVyIDzfp1A/zflUe+2y5A+CzcH/JZtbtX9rpHeOrG23hmMH
wA7kIUr2wTA86w/FlQguTis0E9LX/LWit5Z/bFHnJARjw7ngWGqt3OAvpBpFuod+
vmexchcNrr4IHLkj401EBfNI/gyNK1ySI40uMY+v63xwUzb2quMzw8xhkIv0R//+
+8YbziXKYejJqOOU74QRT7cOv9OHfz+8gJ2tda/plQYiw8OBSh9GtmlQeaY914XX
zQOUaU4=
-----END CERTIFICATE-----
  • httpbin.key
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCmlYHebpcXbvsn
a3zSBqYeg+vlGHXXsAEHNh2wEdOQ1/F3aNj3tTTVQORwIaWaZ4WstowFfTw/6RwQ
5L2UKR19J8Sgkl33u7TibcB/4Ea1YTOz8106gK6OOogeCbzMtEOHFFIuK2AIBBIj
Bh/wwnX/01Zs4z3D5+6L30ct6GyjIdgEBacq7aI6NrbOJNMVz//hJUBuZ8jMLyIA
h856CxjCrPQSn8gQ6myGI9xllfYYehq4M7LucU7riigje+SPShhYFUa0erTM3HEb
Lz3RHXw7sHu0sFHLqFzAa4BlLz8Bk21fsA+CyO9jn/9g6NhtUYEtuxhz+H5hdWcH
p0P4hxIxAgMBAAECggEADHMCZl7h7EanPuItzR1hl0i5HaEnF2QoI4OUEuc2Ji45
NbkQc+ynIuPLXqTpFSG07/wheTyLfuQ7LHkHwPWUpliNPYnKu3ub8EsO9o+KgT4f
KMzgdAGPagIuT35fTXYQUN1AKgKkVd0GBPeNdgb2XhTLce5GnKgt3+ajEWd8DPHY
wCsT7CSSTDGvGq0EZ1E2KK+hDM3Wj5kn65jX+AXVyDppuJZUqH8ycx9g+oBeE8Y0
n4Edno4ghM9xQDW/Vrj0nxI2pNas9GviyswwhRHCqV5uZ0HJBYeSsACiaBBd+094
slWC1YSpMFsjXj0A1LIyMKmLrVZNim95ongAHRRq5QKBgQDmOtR1kcX51EbdWFrk
aqF18GnuawHxtCblUXqdWuWV4JKfj7D2nu/AsMxUxyMlbcDDAFsQiW4oIcY16AhF
Dw72+49VrU+QA6wQyPCBCdIb2TsXUwmo1qAP8ldfZYgUaki4CHPabBk7aY2yvSbO
eMZtWI6wCl5vS91vXoQBB85OJQKBgQC5OuzY8EzxE8jDStfzBAG7iSwGocdGyGOg
1LKN3eLQMtx1n7DumBqVjNPpUNZUutw8zUA859QXsuMA+ieidKauhnbt2ZYfb7Mr
Aq4AVeiW2uhKgvZru9u+FLCt06rgBSaDBBc0jSQYVQ32YFZ6nEXTvtDyGExu1BmQ
gs30T4XYHQKBgEI9mvNYxcVjth/pU/10UJBGY7QdRantU2OXVdgAVx4QRx9xkFDk
2cZvF9sskIgsU9HHQGw5nmAdl5Ha+MYl1wBo0IyuGL4u0ErkBY6a7MDmd4H2ekkB
t3vfFhR0efqludZ5WBv4Dipx7DsJASlWxoCfgi5UTWdoRIXOg9xoCouhAoGAOHEu
LsS6jVNb/7ZUq2ZzKLQZyEOPt4/kW+O0LOqJ7Ksy5lysy2dp4lwxTo0lYlg2OAjL
JEP4KuiFp4ySezxUdiXfI4cD6bxduiNs5glHgIBf/CR/9kAeK4Oeerle/jhTjeS3
NXo0n317bbHZaC8qT+V7QeoJkFPtHk3deC6rODkCgYEA33AxdMfl0pgZpYxI/Dv4
7DMG1XUuomgzqymxmNyoyZPsx5QUm5NUAxzkv8ijwDUO9ymXvZWSh4GECQjwbtdI
YQgcsCVBsvsHtoq8ZI4tGK0uuNSAruWQ8ATABFbM2KQvBiwZ+J0IF1yNy2KLNX7m
4c9dGvwi/BTxQyMEWUxzZtg=
-----END PRIVATE KEY-----
  • root-ca.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Google, OU=Enterprise, CN=Single Root CA
        Validity
            Not Before: Dec 27 17:38:02 2023 GMT
            Not After : Dec 26 17:38:02 2033 GMT
        Subject: C=US, O=Google, OU=Enterprise, CN=Single Root CA
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:bd:4e:4b:a5:b0:44:c4:8a:e0:82:cf:f2:e2:30:
                    02:08:9b:c3:31:82:29:7c:49:91:24:a9:eb:f3:6e:
                    2e:f8:97:51:6d:b2:54:be:8e:e9:18:18:e4:24:6f:
                    4e:9e:7c:82:c3:d1:1b:0a:7c:f1:6f:90:37:3a:5c:
                    26:ff:4a:2b:72:53:dc:7a:22:8f:e5:ab:14:13:e9:
                    44:be:03:60:3a:d0:dd:e5:95:61:40:84:5b:e7:19:
                    01:5f:c6:87:5d:47:fa:e2:0a:6e:bd:9d:7b:b1:88:
                    ac:8f:a3:8f:97:b7:6d:57:03:a3:6c:bf:7b:25:1e:
                    f0:ba:09:c2:47:7e:0a:eb:b8:c3:9f:e7:87:c9:a1:
                    4b:0f:70:ca:75:0b:ee:b3:8e:a3:9a:92:f6:18:65:
                    5a:e0:37:8c:ef:48:bb:cd:45:35:85:11:19:dc:d8:
                    f1:6f:8d:a5:d7:ef:48:15:9f:1a:47:fa:16:dd:77:
                    29:69:06:6d:1e:d9:1d:4f:86:61:df:6b:b8:91:f1:
                    43:b6:80:e4:65:20:66:90:aa:d1:4d:a6:3d:39:7c:
                    a2:19:8e:16:a7:61:a2:f2:18:4b:13:25:ee:1b:72:
                    38:b9:8f:3c:50:ad:cd:88:fa:dc:08:a5:67:8e:0f:
                    8a:c8:66:8d:13:50:24:c3:1f:a8:c7:a9:56:7f:c3:
                    15:3f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Subject Key Identifier: 
                EC:F0:EA:53:53:3F:9F:23:DC:C1:0E:31:10:37:07:DE:DE:E7:6E:F3
            X509v3 Authority Key Identifier: 
                EC:F0:EA:53:53:3F:9F:23:DC:C1:0E:31:10:37:07:DE:DE:E7:6E:F3
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        77:aa:56:03:04:39:86:fc:c8:69:8b:c3:02:ae:87:43:e9:af:
        66:60:fd:f0:df:98:3e:f3:f1:ea:bb:8e:1a:40:ce:18:d2:b4:
        28:93:e4:4d:1c:15:14:89:23:85:10:7f:cf:f6:37:b4:64:c8:
        8e:57:67:41:2e:08:0f:19:87:e6:7a:8a:4a:e6:93:92:96:53:
        27:19:21:24:38:c7:2f:43:67:be:a4:85:3c:e4:b0:10:d7:14:
        76:48:e8:81:e0:ba:7a:26:c4:f3:1d:ba:61:bd:cd:96:4e:9d:
        f6:b6:e5:ad:6a:79:c0:89:01:a9:1e:9b:54:95:97:6e:fb:99:
        17:84:7f:b6:a0:05:a1:0b:41:a6:c8:d3:a4:08:f6:d6:ff:6f:
        1e:94:87:d0:c3:4b:da:8a:4a:aa:42:a8:60:2c:55:25:b1:62:
        bc:a3:54:0e:de:4a:36:07:78:ed:2a:ed:d0:e2:d8:45:45:f3:
        4e:4f:1c:3f:a5:5d:59:bf:5e:66:f4:f6:77:1b:87:90:c0:78:
        94:aa:a8:1b:83:6d:0f:f9:83:32:5b:18:78:1b:99:46:61:64:
        46:61:80:bd:d8:3d:6a:e5:6f:cf:37:c6:bf:32:c9:a0:6e:f4:
        95:4e:de:07:35:af:2e:d5:1f:9d:6c:fb:b4:59:db:90:bb:b9:
        44:43:40:92
-----BEGIN CERTIFICATE-----
MIIDdjCCAl6gAwIBAgIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJVUzEP
MA0GA1UECgwGR29vZ2xlMRMwEQYDVQQLDApFbnRlcnByaXNlMRcwFQYDVQQDDA5T
aW5nbGUgUm9vdCBDQTAeFw0yMzEyMjcxNzM4MDJaFw0zMzEyMjYxNzM4MDJaMEwx
CzAJBgNVBAYTAlVTMQ8wDQYDVQQKDAZHb29nbGUxEzARBgNVBAsMCkVudGVycHJp
c2UxFzAVBgNVBAMMDlNpbmdsZSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAvU5LpbBExIrggs/y4jACCJvDMYIpfEmRJKnr824u+JdRbbJU
vo7pGBjkJG9OnnyCw9EbCnzxb5A3Olwm/0orclPceiKP5asUE+lEvgNgOtDd5ZVh
QIRb5xkBX8aHXUf64gpuvZ17sYisj6OPl7dtVwOjbL97JR7wugnCR34K67jDn+eH
yaFLD3DKdQvus46jmpL2GGVa4DeM70i7zUU1hREZ3Njxb42l1+9IFZ8aR/oW3Xcp
aQZtHtkdT4Zh32u4kfFDtoDkZSBmkKrRTaY9OXyiGY4Wp2Gi8hhLEyXuG3I4uY88
UK3NiPrcCKVnjg+KyGaNE1Akwx+ox6lWf8MVPwIDAQABo2MwYTAOBgNVHQ8BAf8E
BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7PDqU1M/nyPcwQ4xEDcH
3t7nbvMwHwYDVR0jBBgwFoAU7PDqU1M/nyPcwQ4xEDcH3t7nbvMwDQYJKoZIhvcN
AQELBQADggEBAHeqVgMEOYb8yGmLwwKuh0Ppr2Zg/fDfmD7z8eq7jhpAzhjStCiT
5E0cFRSJI4UQf8/2N7RkyI5XZ0EuCA8Zh+Z6ikrmk5KWUycZISQ4xy9DZ76khTzk
sBDXFHZI6IHgunomxPMdumG9zZZOnfa25a1qecCJAakem1SVl277mReEf7agBaEL
QabI06QI9tb/bx6Uh9DDS9qKSqpCqGAsVSWxYryjVA7eSjYHeO0q7dDi2EVF805P
HD+lXVm/Xmb09ncbh5DAeJSqqBuDbQ/5gzJbGHgbmUZhZEZhgL3YPWrlb883xr8y
yaBu9JVO3gc1ry7VH51s+7RZ25C7uURDQJI=
-----END CERTIFICATE-----
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment