From 1f3a180f14783393f4f60d53f6e6c8374929f29f Mon Sep 17 00:00:00 2001 From: Kris Date: Fri, 16 Feb 2018 21:07:31 +0000 Subject: [PATCH] (tests) Test for client authentication on server side --- .travis.yml | 7 +++--- _dev/boring/Dockerfile | 1 + _dev/boring/client_ca.crt | 31 ++++++++++++++++++++++++ _dev/boring/client_rsa.crt | 24 +++++++++++++++++++ _dev/boring/client_rsa.key | 27 +++++++++++++++++++++ _dev/interop.sh | 9 +++++-- _dev/tris-localserver/runner.sh | 1 + _dev/tris-localserver/server.go | 42 ++++++++++++++++++++++++++++++++- 8 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 _dev/boring/client_ca.crt create mode 100644 _dev/boring/client_rsa.crt create mode 100644 _dev/boring/client_rsa.key diff --git a/.travis.yml b/.travis.yml index 8afb3b6..1c54a1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,9 @@ env: # - "C" - tris client will be tested against $SERVER # - "S" - tris server will be tested against $CLIENT # - none of them, client authentication is not tested - - MODE=interop CLIENT=boring SERVER=boring CLIAUTH=C # ClientAuth. CLIENT: tris, SERVER: boringssl - - MODE=interop CLIENT=tstclnt SERVER=tstclnt CLIAUTH=NONE + - MODE=interop CLIENT=boring SERVER=boring CLIAUTH=NONE # Without client authentication + - MODE=interop CLIENT=boring SERVER=boring CLIAUTH=SC # Client authentication + - MODE=interop CLIENT=tstclnt SERVER=tstclnt - MODE=interop CLIENT=picotls ZRTT=1 # - MODE=interop CLIENT=mint # does not support draft 22 - MODE=bogo @@ -35,7 +36,7 @@ install: - if [ -n "$SERVER" ]; then ./_dev/interop.sh INSTALL-CLIENT; fi script: - - if [ "$MODE" = "interop" ]; then ./_dev/interop.sh RUN $CLIENT; fi + - if [ "$MODE" = "interop" ]; then ./_dev/interop.sh RUN $CLIENT $CLIAUTH; fi - if [ "$MODE" = "interop" ] && [ "$ZRTT" = "1" ]; then ./_dev/interop.sh 0-RTT $CLIENT; fi - if [ -n "$SERVER" ]; then ./_dev/interop.sh RUN-CLIENT $SERVER $CLIAUTH; fi - if [ "$MODE" = "gotest" ]; then ./_dev/go.sh test -race crypto/tls; fi diff --git a/_dev/boring/Dockerfile b/_dev/boring/Dockerfile index 24bdc9b..72a7cd7 100644 --- a/_dev/boring/Dockerfile +++ b/_dev/boring/Dockerfile @@ -52,4 +52,5 @@ RUN cd boringssl && ninja -C build ADD httpreq.txt /httpreq.txt ADD run.sh /run.sh ADD server.sh rsa.pem ecdsa.pem / +ADD client_rsa.key client_rsa.crt client_ca.crt / ENTRYPOINT ["/run.sh"] diff --git a/_dev/boring/client_ca.crt b/_dev/boring/client_ca.crt new file mode 100644 index 0000000..ef85005 --- /dev/null +++ b/_dev/boring/client_ca.crt @@ -0,0 +1,31 @@ +-----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----- diff --git a/_dev/boring/client_rsa.crt b/_dev/boring/client_rsa.crt new file mode 100644 index 0000000..6f256b1 --- /dev/null +++ b/_dev/boring/client_rsa.crt @@ -0,0 +1,24 @@ +-----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----- diff --git a/_dev/boring/client_rsa.key b/_dev/boring/client_rsa.key new file mode 100644 index 0000000..1d8e330 --- /dev/null +++ b/_dev/boring/client_rsa.key @@ -0,0 +1,27 @@ +-----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/interop.sh b/_dev/interop.sh index 251eaf3..1453154 100755 --- a/_dev/interop.sh +++ b/_dev/interop.sh @@ -22,7 +22,12 @@ elif [ "$1" = "RUN" ]; then grep "Hello TLS 1.3" output.txt | grep -v "resumed" | grep -v "0-RTT" grep "Hello TLS 1.3" output.txt | grep "resumed" | grep -v "0-RTT" - + if [[ $3 =~ .*S.* ]]; then + # Client auth - tris is a server + docker run --rm tls-tris:$2 $IP:6443 -key client_rsa.key -cert client_rsa.crt -debug 2>&1 | tee output.txt + grep "send_client_certificate_verify" output.txt # Checks if client cert was requested and sent + grep "Hello TLS 1.3" output.txt | grep "resumed" | grep -v "0-RTT" + fi elif [ "$1" = "0-RTT" ]; then # 0-RTT @@ -59,7 +64,7 @@ elif [ "$1" = "RUN-CLIENT" ]; then # ECDSA docker run --rm tris-testclient -rsa=false $IP:2443 - # Test client authentication if requested + # Test client authentication if requested (tris is a client) [[ $3 =~ .*C.* ]] && docker run --rm tris-testclient -rsa=false -cliauth $IP:6443; true # TODO maybe check server logs for expected output? diff --git a/_dev/tris-localserver/runner.sh b/_dev/tris-localserver/runner.sh index 733dadf..d0fcc4a 100755 --- a/_dev/tris-localserver/runner.sh +++ b/_dev/tris-localserver/runner.sh @@ -5,5 +5,6 @@ ./tris-localserver -b 0.0.0.0:3443 -palg=ecdsa -rtt0=o 2>&1 & # third port: offer and reject 0-RTT ./tris-localserver -b 0.0.0.0:4443 -palg=ecdsa -rtt0=oa 2>&1 & # fourth port: offer and accept 0-RTT ./tris-localserver -b 0.0.0.0:5443 -palg=ecdsa -rtt0=oa -rtt0ack 2>&1 & # fifth port: offer and accept 0-RTT but confirm +./tris-localserver -b 0.0.0.0:6443 -palg=rsa -cliauth 2>&1 & # sixth port: RSA with required client authentication wait diff --git a/_dev/tris-localserver/server.go b/_dev/tris-localserver/server.go index c0c5105..165405b 100644 --- a/_dev/tris-localserver/server.go +++ b/_dev/tris-localserver/server.go @@ -10,6 +10,7 @@ import ( "net/http" "os" "time" + "crypto/x509" ) type ZeroRTT_t int @@ -73,6 +74,9 @@ func (s *server) start() { log.Println("Enabled keylog") } + clientCAs := x509.NewCertPool() + clientCAs.AppendCertsFromPEM([]byte(rsaCa_client)) + httpServer := &http.Server{ Addr: s.Address, TLSConfig: &tls.Config{ @@ -87,6 +91,7 @@ func (s *server) start() { }, MaxVersion: tls.VersionTLS13, ClientAuth: s.ClientAuthMethod, + ClientCAs: clientCAs, }, } log.Fatal(httpServer.ListenAndServeTLS("", "")) @@ -100,7 +105,7 @@ func main() { 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.String("cliauth", "", "") + arg_clientauth := flag.Bool("cliauth", false, "Performs client authentication (RequireAndVerifyClientCert used)") flag.Parse() s.Address=*arg_addr @@ -117,6 +122,10 @@ func main() { s.ZeroRTT = ZeroRTT_Offer | ZeroRTT_Accept } + if *arg_clientauth { + s.ClientAuthMethod = tls.RequireAndVerifyClientCert + } + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { tlsConn := r.Context().Value(http.TLSConnContextKey).(*tls.Conn) @@ -202,6 +211,37 @@ 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