From 4386d89c02165bcdbb2c5171391c8a7dcad651b9 Mon Sep 17 00:00:00 2001 From: "Henry D. Case" Date: Thu, 2 Aug 2018 19:33:11 +0100 Subject: [PATCH] Introduces crypto_catalog --- _dev/crypto_catalog/Makefile | 4 + _dev/crypto_catalog/client.go | 233 +++++++++++++++++++++++++++++ _dev/crypto_catalog/server.go | 273 ++++++++++++++++++++++++++++++++++ 3 files changed, 510 insertions(+) create mode 100644 _dev/crypto_catalog/Makefile create mode 100644 _dev/crypto_catalog/client.go create mode 100644 _dev/crypto_catalog/server.go diff --git a/_dev/crypto_catalog/Makefile b/_dev/crypto_catalog/Makefile new file mode 100644 index 0000000..d54f7c3 --- /dev/null +++ b/_dev/crypto_catalog/Makefile @@ -0,0 +1,4 @@ +all: + make -f ~/repos/tls-tris/_dev/Makefile swap_tls + GOROOT=../GOROOT/linux_amd64 go build client.go + GOROOT=../GOROOT/linux_amd64 go build server.go diff --git a/_dev/crypto_catalog/client.go b/_dev/crypto_catalog/client.go new file mode 100644 index 0000000..1a7d184 --- /dev/null +++ b/_dev/crypto_catalog/client.go @@ -0,0 +1,233 @@ +package main + +import ( + "crypto/tls" + "crypto/x509" + "flag" + "fmt" + "io" + "log" + "os" + "strings" +) + +var tlsVersionToName = map[uint16]string{ + tls.VersionTLS10: "1.0", + tls.VersionTLS11: "1.1", + tls.VersionTLS12: "1.2", + tls.VersionTLS13: "1.3", + tls.VersionTLS13Draft18: "1.3 (draft 18)", + tls.VersionTLS13Draft23: "1.3 (draft 23)", +} + +var cipherSuiteIdToName = map[uint16]string{ + tls.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA", + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + tls.TLS_AES_128_GCM_SHA256: "TLS_AES_128_GCM_SHA256", + tls.TLS_AES_256_GCM_SHA384: "TLS_AES_256_GCM_SHA384", + tls.TLS_CHACHA20_POLY1305_SHA256: "TLS_CHACHA20_POLY1305_SHA256", + tls.TLS_ECDHE_SIDH_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_SIDH_ECDSA_WITH_AES_128_GCM_SHA256", +} + +type Client struct { + KeyLogWriter io.Writer + failed uint + client_cert tls.Certificate + client_certpool *x509.CertPool + preferedCurves []tls.CurveID +} + +func (c *Client) run(addr string, version, cipherSuite uint16) { + tls_config := &tls.Config{ + InsecureSkipVerify: true, + MinVersion: version, + MaxVersion: version, + CipherSuites: []uint16{cipherSuite}, + KeyLogWriter: c.KeyLogWriter, + Certificates: []tls.Certificate{c.client_cert}, + RootCAs: c.client_certpool, + CurvePreferences: c.preferedCurves, + } + con, err := tls.Dial("tcp", addr, tls_config) + if err != nil { + fmt.Printf("handshake failed: %v\n\n", err) + c.failed++ + return + } + defer con.Close() + + fmt.Printf("Established: TLS ver %X CipherSuite: %X\n", + con.ConnectionState().Version, + con.ConnectionState().CipherSuite) + + _, err = con.Write([]byte("GET / HTTP/1.1\r\nHost: localhost\r\n\r\n")) + if err != nil { + fmt.Printf("Write failed: %v\n\n", err) + c.failed++ + return + } + + buf := make([]byte, 1024) + n, err := con.Read(buf) + // A non-zero read with EOF is acceptable and occurs when a close_notify + // is received right after reading data (observed with NSS selfserv). + if !(n > 0 && err == io.EOF) && err != nil { + fmt.Printf("Read failed: %v\n\n", err) + c.failed++ + return + } + fmt.Printf("Read %d bytes\n", n) + + fmt.Println("OK\n") +} + +func main() { + var keylog_file string + var enable_rsa, enable_ecdsa, enable_sidh, client_auth bool + + flag.StringVar(&keylog_file, "keylogfile", "", "Secrets will be logged here") + flag.BoolVar(&enable_rsa, "rsa", false, "Whether to enable RSA cipher suites") + flag.BoolVar(&enable_ecdsa, "ecdsa", false, "Whether to enable ECDSA cipher suites") + flag.BoolVar(&client_auth, "cliauth", false, "Whether to enable client authentication") + flag.BoolVar(&enable_sidh, "sidh", false, "Whether to use SIDH") + flag.Parse() + if flag.NArg() != 1 { + flag.Usage() + os.Exit(1) + } + addr := flag.Arg(0) + if !strings.Contains(addr, ":") { + addr += ":443" + } + + client := Client{} + if keylog_file == "" { + keylog_file = os.Getenv("SSLKEYLOGFILE") + } + if keylog_file != "" { + keylog_writer, err := os.OpenFile(keylog_file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + log.Fatalf("Cannot open keylog file: %v", err) + } + client.KeyLogWriter = keylog_writer + log.Println("Enabled keylog") + } + + if client_auth { + var err error + client.client_cert, err = tls.X509KeyPair([]byte(client_crt), []byte(client_key)) + if err != nil { + panic("Can't load client certificate") + } + + client.client_certpool = x509.NewCertPool() + if !client.client_certpool.AppendCertsFromPEM([]byte(client_ca)) { + panic("Can't load client CA cert") + } + } + + if enable_rsa { + // Sanity check: TLS 1.2 with the mandatory cipher suite from RFC 5246 + client.run(addr, tls.VersionTLS12, tls.TLS_RSA_WITH_AES_128_CBC_SHA) + } + if enable_ecdsa { + // Sane cipher suite for TLS 1.2 with an ECDSA cert (as used by boringssl) + client.run(addr, tls.VersionTLS12, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + } + + if enable_sidh { + client.preferedCurves = []tls.CurveID{tls.SidhP751Curve25519} + client.run(addr, tls.VersionTLS13, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + } + + if client.failed > 0 { + log.Fatalf("Failed handshakes: %d\n", client.failed) + } else { + fmt.Println("All handshakes passed") + } +} + +const ( + client_ca = `-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIJAPpBgIvtQb1EMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTgwMjEzMjAxNjA3WhcNMTkwMjEzMjAxNjA3WjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAr4xgdmB4DaEh8zRFmg/1ZxYhQZMUP0iQX/Y8nDWxNlcd42p3TgpY1biz +jrq58ln9Om4U/GAn2RmtBAynSBXIlR5oVa44JeMM8Ka8R/dMKyHpF0Nj2EJB9unb +TC33PfzOlnKQxATwevnnhI6tGluWmwvxXUi7WnX0di+nQg9HrIVom3KrmRr2/41y +g497ccYUuNnKE6sewGdGzw045oWZpMDA2Us+MFo1IywOurjaM9bueRhPTcIiQ8RE +h7qb+FRwfxaj9ynZA2PCM7WMSSWCiZJV0uj/pshYF2lvtJcJef4dhwnsYBpc+mgx +2q9qcUBeo3ZHbi1/PRqjwSmcW3yY5cQRbpYp6xFmgmX3oHQkVXS0UlpNVZ+morcS +HEpaK8b76fCFcL5yFsAJkPPfny1IKU+CfaVq60dM/mxbEW6J4mZT/uAiqrCilMC+ +FyiATCZur8Ks7p47eZy700DllLod7gWTiuZTgHeQFVoX+jxbCZKlFn5Xspu8ALoK +Mla/q83mICRVy3+eMUsD7DNvoWYpCAYy/oMk0VWfrQ48JkCGbBW2PW/dU2nmqVhY +/11rurkr+1TUvYodnajANtXvUjW1DPOLb4dES4Qc4b7Fw8eFXrARhl5mXiL5HFKR +/VnRshiJ+QwTVkxl+KkZHEm/WS8QD+Zd8leAxh9MCoaU/XrBUBkCAwEAAaNTMFEw +HQYDVR0OBBYEFKUinuD1xRvcNd2Wti/PnBJp7On1MB8GA1UdIwQYMBaAFKUinuD1 +xRvcNd2Wti/PnBJp7On1MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggIBAJdJrNBftqkTs2HyuJ3x5RIsTxYh85hJYwNOdFLyzVG6HER9jRCnvmNTjG0O +I5wz5hQvDpwXs4BCCXHQZrTLAi3BEjq3AjrmR/XeGHulbWh3eh8LVu7MiLRgt+Ys +GnL2IaERrbkje24nCCMNPbI3fGDQEhTIYmmX8RJp+5BOJgCycKk6pFgfrjJv2C+d +78pcjlYII6M4vPnr/a08M49Bq6b5ADvIfe5G2KrUvD/+vwoAwv6d/daymHCQ2rY5 +kmdVk9VUp3Q4uKoeej4ENJSAUNTV7oTu346oc7q9sJffB5OltqbrE7ichak7lL+v +EjArZHElAhKNFXRZViCMvGDs+7JztqbsfT8Xb6Z27e+WyudB2bOUGm3hKuTIl06D +bA7yUskwEhmkd1CJqO5RLEJjKitOqe6Ye0/GsmPQNDK8GvyXTyGQK5OqBuzEexF0 +mlPoIhpSVH3K9SkRTTHvvcbdYlaQLi6gKq2uhbk4PnS2nfBtXqYIy9mxcgBJzLiB +/ydfLcf3GClwgvO1JHp6qAl4CO7oe8jqHpoGuznwi1aqkTyNkQWh0OXq3MS+dyqB +2yXFCFIeKCx18TE1OtuTD3ppBDjpyd0o/a6kYR3FDmdks/J33bGwLsLH3lbN6VjF +PNfNkaE1tfkpSGYsuT1DPxX8aAT4JLUfZ1Si6iO+E0Sj9LXA +-----END CERTIFICATE-----` + client_crt = `-----BEGIN CERTIFICATE----- +MIID/jCCAeYCAQEwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDAeFw0xODAyMTMyMDU0MjZaFw0xOTAyMTMyMDU0MjZaMEUxCzAJBgNVBAYTAkFV +MRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRz +IFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD1li7/35Q +C/T6FACSbsd0WlImu42i6w96wfngAfEgbz5Ip+IA2rJ8G5LNHTYYCpr9LlmhY6zm +soHgAkff6XwUnZaetX01UmGP4CD4D3UumkR1uKY4bCSNImm53SZgelOznpsqAWKE +zosMrDcOAJKJSN411KwVzWysfRCPyxvmLETzU9KHFCJ1oY3t1HzYIAqpHv9sMSst +dNHW3X7bWEAVKCQMKO+rWe/wAhE4iTVdlRi02oRoRWSVj41+nk6jI8KJNq70stHc +QSST0A7SUacPYKJWqJRhP1pZ6k4G3ZVE8332az7jvcN1uGGjERZoUbZxGB+mbMCC +GJwnwnNiI6/hAgMBAAEwDQYJKoZIhvcNAQELBQADggIBADNr6QMl57CdHEzNwc2M +CSZsuOLakp8YiovVDOXJ/p/lykUIIcR1rI1iNfb8oOFTZmrndGZVAh76EExdMHYG +m+4Vr2+z/73AZwvhhnLhftOKFFwkdjCfXouPlkc/zmhOORakIFGlLZFkuZRY6k2D +Q8uIt7E5uXSVl11A1LxN5X8lhK2G4lxJZuj1AqEFj9QD44Qy+MdgX38lzGCEXd8c +Y5K8zLJGbgXgYaFxqd0bImfjgjj82+Mui0OTV5PcRlczJX08ygKjcoAMVyvPHu72 +3zzxvoNcqUrvbptVvg9c7FSOpK95YZOe1LiyqZCwNJQl4fPRE++XQ4zDNdyiAp76 +a6BQg/M8gOpV/VBMTsNDr/yP/7eBqkfvU7jLfz7wKMDdcjeZnKom42f+/XOLEo6E +hyDuHGdQh10bZD/Ukcs69+pA3ioic1A8pQzAElH3IuDBsMJg30x8tACLKNcUY8BE +2eJgrCxWcvq88DeAT03W9AVpFZA8ZQUR3SHCquMBFogsmUDDMN+CoC0u5dBwHP+O +9rmWOXn8gp/zBCKGwemgVV5vSNzJs7z3aoqIiAABl56LBaXxjKzRmXoB/SyUW5zl +1zy4SQTE6SJYqqU6h2yRdT8n0oWN3AMy0VxbJTRq32kdYJVQK9cLKVqpxtCCtPnN +3lV+HDsj7k+AJjHiu1F4O+sp +-----END CERTIFICATE-----` + client_key = `-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAw9ZYu/9+UAv0+hQAkm7HdFpSJruNousPesH54AHxIG8+SKfi +ANqyfBuSzR02GAqa/S5ZoWOs5rKB4AJH3+l8FJ2WnrV9NVJhj+Ag+A91LppEdbim +OGwkjSJpud0mYHpTs56bKgFihM6LDKw3DgCSiUjeNdSsFc1srH0Qj8sb5ixE81PS +hxQidaGN7dR82CAKqR7/bDErLXTR1t1+21hAFSgkDCjvq1nv8AIROIk1XZUYtNqE +aEVklY+Nfp5OoyPCiTau9LLR3EEkk9AO0lGnD2CiVqiUYT9aWepOBt2VRPN99ms+ +473DdbhhoxEWaFG2cRgfpmzAghicJ8JzYiOv4QIDAQABAoIBADKcbZhAYjt7q5cJ +nlA5svA9+2cpJ2SITRrTkKk0t0VDmpwaTw0bd+8dDSZXO0ihTQbLeLx9zwxb67ah +wEN8yuVlCK0BiFdEcBRHvx18mTMvCSxHSSXhxNx4nUw8fBOI6aLNBZqoevaJjmP7 +CctjmHtESrEswkBsM36sX6BZxF8Kc4Q5Znuxqksnl6HNoxnjhmygJmYCFTToiTHa +f2HWKBiZfgfxX7WEuHer3h6nmBbBCOX1/hcipBMBBVIqFl1ZSIF/B3lR8UV4/X+a +SNMqggOqkEIuHKkSCKo1lNxEPP2p54EHrKkjepoqMzIFuYnn4qWesMznpmy+zBGB +6PCjfzUCgYEA92etvRVQjBx8dHTSiyCNbS1ELgiCkzar8PGH+ytTIaj/TTF1LfAi +UYRp5MtOKmQXxE3IRLDF8P8rEKC06aV12hVwhd2xfHjje+KZkwWZ2PIj+GbK7f1r +MvKN5eE0NhGiSvu5SiFuks/SV8Qc4StFPmiWf33XKvJuAWNkCu+bUZsCgYEAyqQL +nVNKTlgHNKDJKMHi/buZt8wtwGGXCxcv+w88PmEC0OCbH/V2niCPLvFmK1xDXpru +k7z9FTc+QeasEMtxY/Gcs3IgUzxOHxAL7cn6KBM44uDhpIcv3BFWtR053acVU6S4 +IKuijWIJNJEk2qksgQTX7Mv/xq2uXvfZqajdKjMCgYEA3x+5F9s+Pm5+a4TkUSc1 +hS4a3C0+ncfjv7QEwCftnGDOhu7A0IJOYRg7bGVShHaq3JaNtC19BwEJ9MALCOD5 +bYqCZahvpmNcPeE6Qdb+TiLq/96sy4AOiu8nvBejv9Ode2SUUd/e2jbla9Ppe8VL +eKJYgHicchYb0dKyag54FFsCgYEAuToEB9W3aS9bvsZtuZyooSfXFcND2sMZrqCO +Uh2WAqroSQfVo/vaZiX623z62A2o4xQZmd+5MqhhdxmkFGHyDtouU3SxiYPpIMmp +Lb1etT0E1ZWbi6mqnK0YpcrGNw5gFynMyMg6eKOxKGS33EuhC3ni6Wd7MB9X8ST6 +x/M73jMCgYBBge3/ugnZPE78TDL3DdefrjeYFaKhVc622eimS/MEPbkbdxh8azTM +LAoibwDU1NC8/3MfOBYMe6Qklu3kjexOJrfdo0Z7Khgd9F8A4tKwslUndSSlAfKF +2rjfqabVMZMLZ2XEbA4W5JTfaZS4YYGcrjY7+i7OsnSxoYG2sb+xlQ== +-----END RSA PRIVATE KEY-----` +) diff --git a/_dev/crypto_catalog/server.go b/_dev/crypto_catalog/server.go new file mode 100644 index 0000000..335ed45 --- /dev/null +++ b/_dev/crypto_catalog/server.go @@ -0,0 +1,273 @@ +package main + +import ( + "crypto/tls" + "crypto/x509" + "encoding/hex" + "flag" + "fmt" + "io" + "log" + "net/http" + "os" + "time" +) + +type ZeroRTT_t int +type Algo_t int + +// Bitset +const ( + ZeroRTT_None ZeroRTT_t = 0 + ZeroRTT_Offer = 1 << 0 + ZeroRTT_Accept = 1 << 1 +) + +const ( + PubKeyRSA Algo_t = iota + PubKeyECDSA + KeyShareSIDH +) + +type server struct { + Address string + ZeroRTT ZeroRTT_t + PubKey Algo_t + ClientAuthMethod tls.ClientAuthType + use_sidh bool + curves []tls.CurveID +} + +var tlsVersionToName = map[uint16]string{ + tls.VersionTLS10: "1.0", + tls.VersionTLS11: "1.1", + tls.VersionTLS12: "1.2", + tls.VersionTLS13: "1.3", + tls.VersionTLS13Draft23: "1.3 (draft 23)", +} + +func NewServer() *server { + s := new(server) + s.ClientAuthMethod = tls.NoClientCert + s.ZeroRTT = ZeroRTT_None + s.Address = "0.0.0.1:443" + s.curves = []tls.CurveID{tls.X25519, tls.CurveP256, tls.CurveP384, tls.CurveP521} + return s +} + +func (s *server) start() { + cert, err := tls.X509KeyPair([]byte(ecdsaCert), []byte(ecdsaKey)) + if s.PubKey == PubKeyRSA { + cert, err = tls.X509KeyPair([]byte(rsaCert), []byte(rsaKey)) + } + if err != nil { + log.Fatal(err) + } + var Max0RTTDataSize uint32 + if (s.ZeroRTT & ZeroRTT_Offer) == ZeroRTT_Offer { + Max0RTTDataSize = 100 * 1024 + } + var keyLogWriter io.Writer + if keyLogFile := os.Getenv("SSLKEYLOGFILE"); keyLogFile != "" { + keyLogWriter, err = os.OpenFile(keyLogFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + log.Fatalf("Cannot open keylog file: %v", err) + } + log.Println("Enabled keylog") + } + + clientCAs := x509.NewCertPool() + clientCAs.AppendCertsFromPEM([]byte(rsaCa_client)) + + httpServer := &http.Server{ + Addr: s.Address, + TLSConfig: &tls.Config{ + Certificates: []tls.Certificate{cert}, + Max0RTTDataSize: Max0RTTDataSize, + Accept0RTTData: (s.ZeroRTT & ZeroRTT_Accept) == ZeroRTT_Accept, + KeyLogWriter: keyLogWriter, + GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) { + // If we send the first flight too fast, NSS sends empty early data. + time.Sleep(500 * time.Millisecond) + return nil, nil + }, + MaxVersion: tls.VersionTLS13, + ClientAuth: s.ClientAuthMethod, + ClientCAs: clientCAs, + CurvePreferences: s.curves, + }, + } + log.Fatal(httpServer.ListenAndServeTLS("", "")) +} + +func main() { + + s := NewServer() + + arg_addr := flag.String("b", "0.0.0.0:443", "Address:port used for binding") + arg_palg := flag.String("palg", "rsa", "Public algorithm to use: rsa or ecdsa") + arg_zerortt := flag.String("rtt0", "n", `0-RTT, accepts following values [n: None, a: Accept, o: Offer, oa: Offer and Accept]`) + arg_confirm := flag.Bool("rtt0ack", false, "0-RTT confirm") + arg_clientauth := flag.Bool("cliauth", false, "Performs client authentication (RequireAndVerifyClientCert used)") + arg_sidhon := flag.Bool("enable_sidh", false, "Use SIDH for key exchange") + flag.Parse() + + s.Address = *arg_addr + + if *arg_palg == "ecdsa" { + s.PubKey = PubKeyECDSA + } + + if *arg_zerortt == "a" { + s.ZeroRTT = ZeroRTT_Accept + } else if *arg_zerortt == "o" { + s.ZeroRTT = ZeroRTT_Offer + } else if *arg_zerortt == "oa" { + s.ZeroRTT = ZeroRTT_Offer | ZeroRTT_Accept + } + + if *arg_clientauth { + s.ClientAuthMethod = tls.RequireAndVerifyClientCert + } + + if *arg_sidhon { + s.curves = []tls.CurveID{tls.SidhP751Curve25519} + } + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + tlsConn := r.Context().Value(http.TLSConnContextKey).(*tls.Conn) + + with0RTT := "" + if !tlsConn.ConnectionState().HandshakeConfirmed { + with0RTT = " [0-RTT]" + } + if *arg_confirm || r.URL.Path == "/confirm" { + if err := tlsConn.ConfirmHandshake(); err != nil { + log.Fatal(err) + } + if with0RTT != "" { + with0RTT = " [0-RTT confirmed]" + } + if !tlsConn.ConnectionState().HandshakeConfirmed { + panic("HandshakeConfirmed false after ConfirmHandshake") + } + } + + resumed := "" + if r.TLS.DidResume { + resumed = " [resumed]" + } + + http2 := "" + if r.ProtoMajor == 2 { + http2 = " [HTTP/2]" + } + + fmt.Printf("Established: TLS ver %X CipherSuite: %X\n", + r.TLS.Version, + r.TLS.CipherSuite) + + fmt.Fprintf(w, "

Hello TLS %s%s%s%s _o/\n", tlsVersionToName[r.TLS.Version], resumed, with0RTT, http2) + }) + + http.HandleFunc("/ch", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/plain") + fmt.Fprintf(w, "Client Hello packet (%d bytes):\n%s", len(r.TLS.ClientHello), hex.Dump(r.TLS.ClientHello)) + }) + + s.start() +} + +const ( + rsaKey = `-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA1DHcIM3SThFqy8nAkPQFX0E7ph8jqh8EATXryjKHGuVjR3Xh +OQ0BSPoJxyfdg/VEwevFrtmZAfz0WCbxvP2SVCmf7oobg4V2KPSo3nNt9vlBFUne +RtIyHRQ8YRnGSWaRHzJbX6ffltnG2aD+8qUfk161rdZgxBA9G0Ga47IkwQhT2Hqu +H3dW2Uu4W2WMyt6gX/tdyEAV57MOPcoceknr7Nb2kfiuDPR7h6wFrW3I6eoj8oX2 +SkIOuVNt1Z31BAUcPJDUjqopI0o9tolM/7X13M8dEY0OJQVr7FQYDF9JeSYeEMyb +wizjBaHDm48mSghP1o5UssQBbNNC83btXCjiLQIDAQABAoIBACzvGgRAUYaCnbDl +2kdXxUN0luMIuQ6vXrO67WF17bI+XRWm2riwDlObzzJDON9Wsua1vLjYD1SickOw +i4RP1grIfbuPt1/UhT8LAC+LFgA0rBmL+OvaWw5ZWKffQ2QLujN3AG5zKB/Tog43 +z4UmfldAuQxE11zta2M4M0qAUNQnQj1oiuI8RUdG0VvvLw8Htdi1ogH0CI5R669z +NjHt+JV+2gzKx6EX0s8mQL3yXGkC2xXItRbFclyCMJEhPS7QbBu+tru35N6WpzAq +BCl2Q7LQogvSA6MXuMOx6CyuExVfgmhbfeoheLE8gmXwl0Y37n/g6ZBZFAtpCjcs +UckPv0ECgYEA1orl7RwgIsZljMap6vWtMGoRIHKmT91DGpMmkh4suZe+yAk85maU +49Vd+8ZfIN41AH37yrsGOcPHgz5o5QufELpoub6DCsQ7u9F1vQp55cp+qyBWzAgz +b/xUuVnIyv3kLan3fpk7ZGCBXFBpLG0QXMFOHtda3Mlk5SmuoEYaYRkCgYEA/TLR +u4neKqyqwsqMuRJGC1iKFVmfCjZeNMtPNbTWpdqez/vvT8APnEpIumUGt8YROLGZ +8biUr5/ViOkmaP3wmQbO9m2/cE01lMTYv75w1cw2KVQe6kAHJkOx+JEx9xg53RJ/ +QlFtG5MQUy2599Gxp8BMGaXLH5yo4qwvNvY6CDUCgYEArxr7AwX7rKZlZ/sV4HHY +gzVu+R7aY0DibiRATO5X7rrNuhLgI+UCDNqvNLn6FqeGdvpcsmDneeozQwmDL77G +ey7KHyBBcF4tquQQxtRwHX+i1yUz8p+W7AX1WLrRSezjeenJ2QhUE1849hGjZeE2 +g546lq2Kub2enfPhVWsiSLECgYEA72T5QCPeVuLioUH5Q5Kvf1K7W+xcnr9A2xHP +Vqwgtre5qFQ/tFuXZuIlWXbjnyY6aiwhrZYjntm0f7pRgrt2nHj/fafOdVPK8Voc +xU4+SSbHntPWVw0qtVcUEjzVzRauvwMaJ43tZ0DpEnwNdO5i1oTObwF+x+jLFWZP +TdwIinECgYBzjZeCxxOMk5SlPpTsLUtgC+q3m1AavXhUVNEPP2gKMOIPTETPbhbG +LBxB2vVbJiS3J7itQy8gceT89O0vSEZnaTPXiM/Ws1QbkBJ8yW7KI7X4WuzN4Imq +/cLBRXLb8R328U27YyQFNGMjr2tX/+vx5FulJjSloWMRNuFWUngv7w== +-----END RSA PRIVATE KEY-----` + rsaCert = `-----BEGIN CERTIFICATE----- +MIIC+jCCAeKgAwIBAgIRANBDimJ/ww2tz77qcYIhuZowDQYJKoZIhvcNAQELBQAw +EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA5MjQxNzI5MTlaFw0yNjA5MjIxNzI5 +MTlaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDUMdwgzdJOEWrLycCQ9AVfQTumHyOqHwQBNevKMoca5WNHdeE5DQFI ++gnHJ92D9UTB68Wu2ZkB/PRYJvG8/ZJUKZ/uihuDhXYo9Kjec232+UEVSd5G0jId +FDxhGcZJZpEfMltfp9+W2cbZoP7ypR+TXrWt1mDEED0bQZrjsiTBCFPYeq4fd1bZ +S7hbZYzK3qBf+13IQBXnsw49yhx6Sevs1vaR+K4M9HuHrAWtbcjp6iPyhfZKQg65 +U23VnfUEBRw8kNSOqikjSj22iUz/tfXczx0RjQ4lBWvsVBgMX0l5Jh4QzJvCLOMF +ocObjyZKCE/WjlSyxAFs00Lzdu1cKOItAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF +oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC +CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAygPV4enmvwSuMd1JarxOXpOK +Z4Nsk7EKlfCPgzxQUOkFdLIr5ZG1kUkQt/omzTmoIWjLAsoYzT0ZCPOrioczKsWj +MceFUIkT0w+eIl+8DzauPy34o8rjcApglF165UG3iphlpI+jdPzv5TBarUAbwsFb +ClMLEiNJQ0OMxAIaRtb2RehD4q3OWlpWf6joJ36PRBqL8T5+f2x6Tg3c64UR+QPX +98UcCQHHdEhm7y2z5Z2Wt0B48tZ+UAxDEoEwMghNyw7wUD79IRlXGYypBnXaMuLX +46aGxbsSQ7Rfg62Co3JG7vo+eJd0AoZHrtFUnfM8V70IFzMBZnSwRslHRJe56Q== +-----END CERTIFICATE-----` + rsaCa_client = `-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIJAPpBgIvtQb1EMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTgwMjEzMjAxNjA3WhcNMTkwMjEzMjAxNjA3WjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAr4xgdmB4DaEh8zRFmg/1ZxYhQZMUP0iQX/Y8nDWxNlcd42p3TgpY1biz +jrq58ln9Om4U/GAn2RmtBAynSBXIlR5oVa44JeMM8Ka8R/dMKyHpF0Nj2EJB9unb +TC33PfzOlnKQxATwevnnhI6tGluWmwvxXUi7WnX0di+nQg9HrIVom3KrmRr2/41y +g497ccYUuNnKE6sewGdGzw045oWZpMDA2Us+MFo1IywOurjaM9bueRhPTcIiQ8RE +h7qb+FRwfxaj9ynZA2PCM7WMSSWCiZJV0uj/pshYF2lvtJcJef4dhwnsYBpc+mgx +2q9qcUBeo3ZHbi1/PRqjwSmcW3yY5cQRbpYp6xFmgmX3oHQkVXS0UlpNVZ+morcS +HEpaK8b76fCFcL5yFsAJkPPfny1IKU+CfaVq60dM/mxbEW6J4mZT/uAiqrCilMC+ +FyiATCZur8Ks7p47eZy700DllLod7gWTiuZTgHeQFVoX+jxbCZKlFn5Xspu8ALoK +Mla/q83mICRVy3+eMUsD7DNvoWYpCAYy/oMk0VWfrQ48JkCGbBW2PW/dU2nmqVhY +/11rurkr+1TUvYodnajANtXvUjW1DPOLb4dES4Qc4b7Fw8eFXrARhl5mXiL5HFKR +/VnRshiJ+QwTVkxl+KkZHEm/WS8QD+Zd8leAxh9MCoaU/XrBUBkCAwEAAaNTMFEw +HQYDVR0OBBYEFKUinuD1xRvcNd2Wti/PnBJp7On1MB8GA1UdIwQYMBaAFKUinuD1 +xRvcNd2Wti/PnBJp7On1MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggIBAJdJrNBftqkTs2HyuJ3x5RIsTxYh85hJYwNOdFLyzVG6HER9jRCnvmNTjG0O +I5wz5hQvDpwXs4BCCXHQZrTLAi3BEjq3AjrmR/XeGHulbWh3eh8LVu7MiLRgt+Ys +GnL2IaERrbkje24nCCMNPbI3fGDQEhTIYmmX8RJp+5BOJgCycKk6pFgfrjJv2C+d +78pcjlYII6M4vPnr/a08M49Bq6b5ADvIfe5G2KrUvD/+vwoAwv6d/daymHCQ2rY5 +kmdVk9VUp3Q4uKoeej4ENJSAUNTV7oTu346oc7q9sJffB5OltqbrE7ichak7lL+v +EjArZHElAhKNFXRZViCMvGDs+7JztqbsfT8Xb6Z27e+WyudB2bOUGm3hKuTIl06D +bA7yUskwEhmkd1CJqO5RLEJjKitOqe6Ye0/GsmPQNDK8GvyXTyGQK5OqBuzEexF0 +mlPoIhpSVH3K9SkRTTHvvcbdYlaQLi6gKq2uhbk4PnS2nfBtXqYIy9mxcgBJzLiB +/ydfLcf3GClwgvO1JHp6qAl4CO7oe8jqHpoGuznwi1aqkTyNkQWh0OXq3MS+dyqB +2yXFCFIeKCx18TE1OtuTD3ppBDjpyd0o/a6kYR3FDmdks/J33bGwLsLH3lbN6VjF +PNfNkaE1tfkpSGYsuT1DPxX8aAT4JLUfZ1Si6iO+E0Sj9LXA +-----END CERTIFICATE-----` + ecdsaCert = `-----BEGIN CERTIFICATE----- +MIIBbTCCAROgAwIBAgIQZCsHZcs5ZkzV+zC2E6j5RzAKBggqhkjOPQQDAjASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTE2MDkyNDE3NTE1OFoXDTI2MDkyMjE3NTE1OFow +EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDTO +B3IyzjYfKCp2HWy+P3QHxhdBT4AUGYgwTiSEj5phumPIahFNcOSWptN0UzlZvJdN +MMjVmrFYK/FjF4abkNKjSzBJMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr +BgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggq +hkjOPQQDAgNIADBFAiEAp9W157PM1IadPBc33Cbj7vaFvp+rXs/hSuMCzP8pgV8C +IHCswo1qiC0ZjQmWsBlmz5Zbp9rOorIzBYmGRhRdNs3j +-----END CERTIFICATE-----` + ecdsaKey = `-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIFdhO7IW5UIwpB1e2Vunm9QyKvUHWcVwGfLjhpOajuR7oAoGCCqGSM49 +AwEHoUQDQgAENM4HcjLONh8oKnYdbL4/dAfGF0FPgBQZiDBOJISPmmG6Y8hqEU1w +5Jam03RTOVm8l00wyNWasVgr8WMXhpuQ0g== +-----END EC PRIVATE KEY-----` +)