diff --git a/.travis.yml b/.travis.yml index e50de2cdbb..19d6d59e63 100644 --- a/.travis.yml +++ b/.travis.yml @@ -88,7 +88,7 @@ install: - git clone https://github.com/openresty/lua-resty-lrucache.git ../lua-resty-lrucache - git clone https://github.com/openresty/lua-resty-mysql.git ../lua-resty-mysql - git clone https://github.com/openresty/stream-lua-nginx-module.git ../stream-lua-nginx-module - - git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git luajit2 + - git clone -b feat/check_cdata https://github.com/dndx/luajit2.git luajit2 before_script: - mysql -uroot -e 'create database ngx_test; grant all on ngx_test.* to "ngx_test"@"%" identified by "ngx_test"; flush privileges;' diff --git a/README.markdown b/README.markdown index 0d4e0dd8eb..caf8a35dc4 100644 --- a/README.markdown +++ b/README.markdown @@ -927,7 +927,6 @@ TODO * add `ignore_resp_headers`, `ignore_resp_body`, and `ignore_resp` options to [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi) methods, to allow micro performance tuning on the user side. * add automatic Lua code time slicing support by yielding and resuming the Lua VM actively via Lua's debug hooks. * add `stat` mode similar to [mod_lua](https://httpd.apache.org/docs/trunk/mod/mod_lua.html). -* cosocket: add client SSL certificate support. [Back to TOC](#table-of-contents) @@ -7346,7 +7345,7 @@ This method was first introduced in the `v0.5.0rc1` release. tcpsock:sslhandshake -------------------- -**syntax:** *session, err = tcpsock:sslhandshake(reused_session?, server_name?, ssl_verify?, send_status_req?)* +**syntax:** *session, err = tcpsock:sslhandshake(reused_session?, server_name?, ssl_verify?, send_status_req?, options_table?)* **context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** @@ -7382,6 +7381,18 @@ to validate the server name in the server certificate. The optional `send_status_req` argument takes a boolean that controls whether to send the OCSP status request in the SSL handshake request (which is for requesting OCSP stapling). +An optional Lua table can be specified as the last argument to this method to specify various handshake options: + +* `client_cert` specify a client certificate chain cdata object that will be used while handshaking with +remote server. These objects can be created using [ngx.ssl.parse\_pem\_cert](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_cert) +function provided by lua-resty-core. Note that specifying the `client_cert` option requires +corresponding `client_priv_key` be provided too. See below. +* `client_priv_key` specify a private key corresponds to the `client_cert` option above. +These objects can be created using [ngx.ssl.parse\_pem\_priv\_key](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_priv_key) +function provided by lua-resty-core. + +The support for the options table argument was first introduced in the v0.10.16 release. + For connections that have already done SSL/TLS handshake, this method returns immediately. diff --git a/src/ngx_http_lua_socket_tcp.c b/src/ngx_http_lua_socket_tcp.c index d3453d456e..9ac1d0cd0f 100644 --- a/src/ngx_http_lua_socket_tcp.c +++ b/src/ngx_http_lua_socket_tcp.c @@ -1534,7 +1534,7 @@ ngx_http_lua_socket_conn_error_retval_handler(ngx_http_request_t *r, static int ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) { - int n, top; + int n, top, i; ngx_int_t rc; ngx_str_t name = ngx_null_string; ngx_connection_t *c; @@ -1542,15 +1542,19 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; ngx_http_lua_co_ctx_t *coctx; + STACK_OF(X509) *chain = NULL; + X509 *x509; + EVP_PKEY *pkey; + ngx_ssl_conn_t *ssl_conn; ngx_http_lua_socket_tcp_upstream_t *u; /* Lua function arguments: self [,session] [,host] [,verify] - [,send_status_req] */ + [,send_status_req] [, opts] */ n = lua_gettop(L); - if (n < 1 || n > 5) { - return luaL_error(L, "ngx.socket sslhandshake: expecting 1 ~ 5 " + if (n < 1 || n > 6) { + return luaL_error(L, "ngx.socket sslhandshake: expecting 1 ~ 6 " "arguments (including the object), but seen %d", n); } @@ -1626,6 +1630,8 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) return 2; } + ssl_conn = c->ssl->connection; + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { return luaL_error(L, "no ctx found"); @@ -1695,6 +1701,100 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) #endif } } + + if (n >= 6) { + if (lua_type(L, 6) == LUA_TTABLE) { + lua_getfield(L, 6, "client_cert"); + + if (!lua_isnil(L, -1)) { +#ifdef OPENRESTY_LUAJIT + chain = luaL_checkcdataptr(L, -1); + if (chain == NULL) { + return luaL_error(L, "\"client_cert\" can " + "not be NULL"); + } + + /* chain != NULL */ + + lua_pop(L, 1); + + lua_getfield(L, 6, "client_priv_key"); + + pkey = luaL_checkcdataptr(L, -1); + if (pkey == NULL) { + return luaL_error(L, "\"client_priv_key\" can " + "not be NULL"); + } + + if (sk_X509_num(chain) < 1) { + ERR_clear_error(); + return luaL_error(L, "invalid client " + "certificate chain"); + } + + x509 = sk_X509_value(chain, 0); + if (x509 == NULL) { + ERR_clear_error(); + lua_pushnil(L); + lua_pushliteral(L, "lua ssl fetch client " + "certificate from chain " + "failed"); + return 2; + } + + if (SSL_use_certificate(ssl_conn, x509) == 0) { + ERR_clear_error(); + lua_pushnil(L); + lua_pushliteral(L, "lua ssl set client " + "certificate failed"); + return 2; + } + + /* read rest of the chain */ + + for (i = 1; i < sk_X509_num(chain); i++) { + x509 = sk_X509_value(chain, i); + if (x509 == NULL) { + ERR_clear_error(); + lua_pushnil(L); + lua_pushliteral(L, "lua ssl fetch client " + "intermediate certificate " + "from chain failed"); + return 2; + } + + if (SSL_add1_chain_cert(ssl_conn, x509) == 0) { + ERR_clear_error(); + lua_pushnil(L); + lua_pushliteral(L, "lua ssl set client " + "intermediate certificate " + "failed"); + return 2; + } + } + + if (SSL_use_PrivateKey(ssl_conn, pkey) == 0) { + ERR_clear_error(); + lua_pushnil(L); + lua_pushliteral(L, "lua ssl set client " + "private key failed"); + return 2; + } +#else + return luaL_error(L, "client certificate support requires the " + "OpenResty LuaJIT fork"); +#endif /* OPENRESTY_LUAJIT */ + } + + lua_pop(L, 1); + + } else if (!lua_isnil(L, 6)) { + return luaL_error(L, "ngx.socket sslhandshake: bad " + "options table type, expecting a " + "table but seen %s", + lua_typename(L, lua_type(L, 6))); + } + } } } } diff --git a/t/129-ssl-socket.t b/t/129-ssl-socket.t index 454852d7da..8e3b2b8f8a 100644 --- a/t/129-ssl-socket.t +++ b/t/129-ssl-socket.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * 211; +plan tests => repeat_each() * 251; $ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); @@ -32,6 +32,43 @@ our $EquifaxRootCertificate = read_file("t/cert/equifax.crt"); our $TestCertificate = read_file("t/cert/test.crt"); our $TestCertificateKey = read_file("t/cert/test.key"); our $TestCRL = read_file("t/cert/test.crl"); +our $MTLSCA = read_file("t/cert/mtls_ca.crt"); +our $MTLSClient = read_file("t/cert/mtls_client.crt"); +our $MTLSClientKey = read_file("t/cert/mtls_client.key"); +our $MTLSServer = read_file("t/cert/mtls_server.crt"); +our $MTLSServerKey = read_file("t/cert/mtls_server.key"); + +our $HtmlDir = html_dir; + +our $mtls_http_config = <<"_EOC_"; +server { + listen unix:$::HtmlDir/mtls.sock ssl; + + ssl_certificate $::HtmlDir/mtls_server.crt; + ssl_certificate_key $::HtmlDir/mtls_server.key; + + ssl_client_certificate $::HtmlDir/mtls_ca.crt; + ssl_verify_client on; + server_tokens off; + + location / { + return 200 "hello, \$ssl_client_s_dn"; + } +} +_EOC_ + +our $mtls_user_files = <<"_EOC_"; +>>> mtls_server.key +$::MTLSServerKey +>>> mtls_server.crt +$::MTLSServer +>>> mtls_ca.crt +$::MTLSCA +>>> mtls_client.key +$::MTLSClientKey +>>> mtls_client.crt +$::MTLSClient +_EOC_ run_tests(); @@ -2508,6 +2545,41 @@ SSL reused session #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; + content_by_lua_block { + local sock = ngx.socket.tcp() + sock:settimeout(7000) + + local ok, err = sock:connect("openresty.org", 443) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local session, err = sock:sslhandshake(1, 2, 3, 4, 5, 6) + } + } + +--- request +GET /t +--- ignore_response +--- error_log eval +qr/\[error\] .* ngx.socket sslhandshake: expecting 1 ~ 6 arguments \(including the object\), but seen 7/ +--- no_error_log +[alert] +--- timeout: 10 + + + +=== TEST 32: handshake, no arguments +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER ipv6=off; + location /t { + #set $port 5000; + set $port $TEST_NGINX_MEMCACHED_PORT; + content_by_lua_block { local sock = ngx.socket.tcp() sock:settimeout(7000) @@ -2528,7 +2600,318 @@ SSL reused session GET /t --- ignore_response --- error_log eval -qr/\[error\] .* ngx.socket sslhandshake: expecting 1 ~ 5 arguments \(including the object\), but seen 0/ +qr/\[error\] .* ngx.socket sslhandshake: expecting 1 ~ 6 arguments \(including the object\), but seen 0/ --- no_error_log [alert] --- timeout: 10 + + + +=== TEST 33: mutual TLS handshake, upstream is not accessible without client certs +--- http_config eval: $::mtls_http_config +--- config eval +" + server_tokens off; + + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = sock:connect('unix:$::HtmlDir/mtls.sock') + if not ok then + ngx.say('failed to connect: ', err) + end + + assert(sock:sslhandshake()) + + ngx.say('connected: ', ok) + + local req = 'GET /\\r\\n' + + local bytes, err = sock:send(req) + if not bytes then + ngx.say('failed to send request: ', err) + return + end + + ngx.say('request sent: ', bytes) + + ngx.say(sock:receive('*a')) + + assert(sock:close()) + } + } +" + +--- user_files eval: $::mtls_user_files +--- request +GET /t +--- response_body_like: 400 No required SSL certificate was sent +--- no_error_log +[alert] +[error] +[crit] +[emerg] + + + +=== TEST 34: mutual TLS handshake, upstream is accessible when client certs are supplied +--- http_config eval: $::mtls_http_config +--- config eval +" + server_tokens off; + + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = sock:connect('unix:$::HtmlDir/mtls.sock') + if not ok then + ngx.say('failed to connect: ', err) + end + + local f = assert(io.open('$::HtmlDir/mtls_client.crt')) + local cert_data = f:read('*a') + f:close() + + f = assert(io.open('$::HtmlDir/mtls_client.key')) + local key_data = f:read('*a') + f:close() + + local ssl = require('ngx.ssl') + + local chain = assert(ssl.parse_pem_cert(cert_data)) + local priv = assert(ssl.parse_pem_priv_key(key_data)) + + assert(sock:sslhandshake(nil, nil, nil, nil, { client_cert = chain, client_priv_key = priv, })) + + ngx.say('connected: ', ok) + + local req = 'GET /\\r\\n' + + local bytes, err = sock:send(req) + if not bytes then + ngx.say('failed to send request: ', err) + return + end + + ngx.say('request sent: ', bytes) + + ngx.say(sock:receive('*a')) + + assert(sock:close()) + } + } +" + +--- user_files eval: $::mtls_user_files +--- request +GET /t +--- response_body +connected: 1 +request sent: 7 +hello, CN=foo@example.com,O=OpenResty,ST=California,C=US +--- no_error_log +[alert] +[error] +[crit] +[emerg] + + + +=== TEST 35: incorrect type of options table +--- config + server_tokens off; + + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = sock:connect('127.0.0.1', ngx.var.server_port) + if not ok then + ngx.say('failed to connect: ', err) + end + + ok, err = sock:sslhandshake(nil, nil, nil, nil, ngx.null) + if not ok then + ngx.say('failed to handshake: ', err) + end + + assert(sock:close()) + } + } + +--- request +GET /t +--- error_code: 500 +--- no_error_log +[alert] +[crit] +[emerg] +--- error_log +ngx.socket sslhandshake: bad options table type, expecting a table but seen userdata + + + +=== TEST 36: incorrect type of client cert +--- config + server_tokens off; + + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = sock:connect('127.0.0.1', ngx.var.server_port) + if not ok then + ngx.say('failed to connect: ', err) + end + + ok, err = sock:sslhandshake(nil, nil, nil, nil, { client_cert = "doesnt", client_priv_key = "work", }) + if not ok then + ngx.say('failed to handshake: ', err) + end + + assert(sock:close()) + } + } + +--- request +GET /t +--- error_code: 500 +--- no_error_log +[alert] +[crit] +[emerg] +--- error_log +bad argument #7 to 'sslhandshake' (cdata expected, got string) + + + +=== TEST 37: incorrect type of client key +--- config eval +" + server_tokens off; + + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = sock:connect('127.0.0.1', ngx.var.server_port) + if not ok then + ngx.say('failed to connect: ', err) + end + + local f = assert(io.open('$::HtmlDir/mtls_client.crt')) + local cert_data = f:read('*a') + f:close() + + local ssl = require('ngx.ssl') + + local chain = assert(ssl.parse_pem_cert(cert_data)) + + ok, err = sock:sslhandshake(nil, nil, nil, nil, { client_cert = chain, client_priv_key = 'work', }) + if not ok then + ngx.say('failed to handshake: ', err) + end + + assert(sock:close()) + } + } +" + +--- user_files eval: $::mtls_user_files +--- request +GET /t +--- error_code: 500 +--- no_error_log +[alert] +[crit] +[emerg] +--- error_log +bad argument #7 to 'sslhandshake' (cdata expected, got string) + + + +=== TEST 38: missing private key +--- config eval +" + server_tokens off; + + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = sock:connect('127.0.0.1', ngx.var.server_port) + if not ok then + ngx.say('failed to connect: ', err) + end + + local f = assert(io.open('$::HtmlDir/mtls_client.crt')) + local cert_data = f:read('*a') + f:close() + + local ssl = require('ngx.ssl') + + local chain = assert(ssl.parse_pem_cert(cert_data)) + + ok, err = sock:sslhandshake(nil, nil, nil, nil, { client_cert = chain, }) + if not ok then + ngx.say('failed to handshake: ', err) + end + + assert(sock:close()) + } + } +" + +--- user_files eval: $::mtls_user_files +--- request +GET /t +--- error_code: 500 +--- no_error_log +[alert] +[crit] +[emerg] +--- error_log +bad argument #7 to 'sslhandshake' (cdata expected, got nil) + + + +=== TEST 39: mutual TLS handshake, upstream is not accessible without empty options table +--- http_config eval: $::mtls_http_config +--- config eval +" + server_tokens off; + + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = sock:connect('unix:$::HtmlDir/mtls.sock') + if not ok then + ngx.say('failed to connect: ', err) + end + + assert(sock:sslhandshake(nil, nil, nil, nil, {})) + + ngx.say('connected: ', ok) + + local req = 'GET /\\r\\n' + + local bytes, err = sock:send(req) + if not bytes then + ngx.say('failed to send request: ', err) + return + end + + ngx.say('request sent: ', bytes) + + ngx.say(sock:receive('*a')) + + assert(sock:close()) + } + } +" + +--- user_files eval: $::mtls_user_files +--- request +GET /t +--- response_body_like: 400 No required SSL certificate was sent +--- no_error_log +[alert] +[error] +[crit] +[emerg] diff --git a/t/cert/mtls_ca.crt b/t/cert/mtls_ca.crt new file mode 100644 index 0000000000..99c8ec833d --- /dev/null +++ b/t/cert/mtls_ca.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFpTCCA42gAwIBAgIUfTh89NyxxmbVwNZ/YFddssWc+WkwDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAoM +CU9wZW5SZXN0eTEiMCAGA1UEAwwZT3BlblJlc3R5IFRlc3RpbmcgUm9vdCBDQTAe +Fw0xOTA5MTMyMjI4MTJaFw0zOTA5MDgyMjI4MTJaMFoxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQKDAlPcGVuUmVzdHkxIjAgBgNVBAMM +GU9wZW5SZXN0eSBUZXN0aW5nIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDcMg2DeV8z+0E2ZiXUax111lKzhAbMCK0RJlV9tAi+YdcsDR/t +zvvAZNGONUoewUuz/7E88oweh+Xi1GJtvd0DjB70y7tgpf5PUXovstWVwy7s5jZo +kgn62yi9ZOOZpjwnYTBviirtRTnZRwkzL6wF0xMyJjAbKBJuPMrMiyFdh82lt7wI +NS4mhyEdM0UiVVxfC2uzsddTOcOJURfGbW7UZm4Xohzq4QZ8geQj2OT5YTqw7dZ7 +Xxre5H7IcNcAh+vIk5SEBV1WE+S5MnFly7gaLYNc49OSfz5Hcpv59Vr+4bZ+olbW +nQ/uU8BQovtkW6pjuT8nC4OKs2e8osoAZuk0rFS1uC501C+yES48mzaU8ttAidu6 +nb/JgsdkrnJQeTc5rAoER4M2ne5kqtEXN8wzf3/sazo2PLywbfrUXUTV6kJilrGr +RkBN+fr6HTBkf+ooQMBOQPTojUdwbR86CLCyiJov2bzmBfGcOgSakv59S+uvUZFp +FLTiahuzLfcgYsG3UKQA47pYlNdUqP8vCCaf1nwmqjx2KS3Z/YFnO/gQgtY+f0Bh +UpnUDv+zBxpVFfVCyxByEsDPdwDkqLSwB6+YZINl36S48iXpoPhNXIYmO6GnhNWV +k2/RyCDTxEO+MbXHVg6iyIVHJWth7m18vl4uuSK/LbJHV9Q9Z7G99DQ0NwIDAQAB +o2MwYTAdBgNVHQ4EFgQUuoo+ehdlDFcQU+j5qONMKh0NtFQwHwYDVR0jBBgwFoAU +uoo+ehdlDFcQU+j5qONMKh0NtFQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAYYwDQYJKoZIhvcNAQELBQADggIBAM7c9q41K8306lfAVLqtbtaeETy+xxYG +XE2HfFW1IuukrXQ8d/JH4stL/HcHJzzhHPf5p3ja3Snu9zPmTk3pgUPDYPZf57tR +NCqwxjn6blwXWlzQqSavto9KAx3IWHuj0OTrZz/a1KPb9NGvatBhgthyRCRTbvhL +OA5tveuYSHb724cp3NZ1xaTQmDZsSgHCoCJ/7RnlbcJ7RsKCOzCWNFRomH410vdv +TajkUBlEC4OC1RIvxuVePHHb1ogbbe93SA/9mzw/E5SfoeF3mvByN4Ay8awXbNlH +26RfuIdGc4fZRc/87s4yPwhYScZBG+pHO0gn42E0FyiG6Jp3rhHMH5Sa2hNlPMpn +hYMaA6zQI4n/3AeFNM0VGxA+Yg/Al2WpXEJARrZqMW/qcrdMcPj5WeY6Tb6er04S +kfImwhMIajl3nNc9tHoad8r2VuMWMltH/dnWuEdo+pPdIY3fdJdyQeoLQDDLEQwL +AYrFy4uzKfQogfQBIHRdIMZTJh5v3mAFDpK59I5yzSt1GtUnFMC5MVOg+LbOo5UW +FCtwaW5EZiTszmakvvWMMZe9HwZMYNCeSGGtiPA/GA2zNci/n2TEcB11HgiY52y2 +E/40nS61oL81zMwhV7l5psgJxQ2ORsKRJPHjADwvwh3xyCEJgVyBRCDX7J3PpAUO +79DprjVU8t7p +-----END CERTIFICATE----- diff --git a/t/cert/mtls_ca.key b/t/cert/mtls_ca.key new file mode 100644 index 0000000000..d741b5b0e7 --- /dev/null +++ b/t/cert/mtls_ca.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/t/cert/mtls_client.crt b/t/cert/mtls_client.crt new file mode 100644 index 0000000000..c6ba07ccb6 --- /dev/null +++ b/t/cert/mtls_client.crt @@ -0,0 +1,111 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=California, O=OpenResty, CN=OpenResty Testing Root CA + Validity + Not Before: Sep 13 22:30:49 2019 GMT + Not After : Sep 10 22:30:49 2029 GMT + Subject: C=US, ST=California, O=OpenResty, CN=foo@example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d0:8c:1e:2c:25:7f:00:9d:8a:3d:8a:f3:b5:1d: + 6b:24:f5:ac:35:7d:cd:b7:d0:af:db:88:7c:ee:82: + 46:16:47:f3:43:08:a1:04:6e:0d:3e:ce:69:fa:d5: + 89:14:82:20:f1:47:f2:38:c8:ab:ea:2f:1e:f0:15: + 04:c0:f4:8b:3c:c3:d4:78:56:87:4c:f1:70:ac:11: + 86:2e:c4:6a:6d:10:84:27:81:ca:2a:8b:85:3e:62: + 13:5e:40:6c:19:e4:49:3d:f3:de:aa:e8:5e:11:a1: + f2:66:83:6a:40:d1:34:c5:bf:b8:cb:97:7c:6a:ea: + 46:bf:17:be:32:8d:a8:31:56:e5:8b:6d:08:03:d0: + 44:69:b9:af:1e:15:1d:a5:64:9e:12:84:83:db:d9: + c6:71:90:3b:c2:7b:41:21:57:af:70:15:0b:56:59: + 21:a6:4e:46:71:66:90:f1:ef:bc:b2:48:f9:8b:ea: + e5:72:4a:ba:4a:ae:2d:74:0b:33:03:f6:2e:47:0f: + 56:a4:00:e8:1e:62:cb:b8:af:9c:98:1a:89:7c:d0: + a3:7a:5a:e1:84:50:64:e4:5d:a5:70:a4:69:54:c4: + f4:76:44:a2:be:1b:ef:dc:a3:d8:1d:0d:30:a2:d4: + 79:fb:39:76:ab:b7:18:f2:f7:92:f8:81:83:94:b8: + 11:b1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Cert Type: + SSL Client, S/MIME + Netscape Comment: + OpenSSL Generated Client Certificate + X509v3 Subject Key Identifier: + D2:E4:F5:21:1C:17:A4:FF:13:F4:1A:28:A8:A7:DC:C6:DE:89:A0:31 + X509v3 Authority Key Identifier: + keyid:BA:8A:3E:7A:17:65:0C:57:10:53:E8:F9:A8:E3:4C:2A:1D:0D:B4:54 + + X509v3 Key Usage: critical + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Client Authentication, E-mail Protection + X509v3 Subject Alternative Name: + email:foo@example.com, email:bar@example.com + Signature Algorithm: sha256WithRSAEncryption + 47:77:51:37:00:f7:28:da:c4:d9:4e:38:c4:ec:ea:24:c9:83: + 36:4c:90:93:a7:b2:2b:10:bf:75:df:0b:72:d8:e7:4f:4f:68: + e5:32:2f:35:89:17:95:5c:bb:43:fc:70:89:46:08:43:61:ac: + 41:62:84:01:94:88:d1:dc:8a:bd:30:2c:18:eb:51:79:0b:b7: + 1b:b6:49:df:c9:85:55:f6:73:9f:b7:83:99:52:23:fe:e6:bd: + 09:da:90:b9:e2:9b:68:c4:df:bd:fe:23:94:55:34:be:0d:7d: + 84:0c:53:69:2a:0f:3c:47:68:34:3f:2a:3f:89:3f:3e:d3:26: + ce:b7:58:bc:d0:6f:ee:f8:bd:5d:c6:48:ae:a0:6c:1f:6d:e0: + 66:93:7d:db:3c:07:e6:15:ae:aa:e3:d0:3d:ef:04:b6:dd:53: + 16:93:61:70:e9:af:c0:e9:1d:ff:2b:e5:0a:03:56:48:3f:1c: + dc:fe:1b:a6:6d:f6:54:ab:41:e5:3b:5b:ab:f5:81:10:46:26: + bb:ea:d7:0e:33:b1:5e:30:4d:81:86:63:9a:4a:4f:1e:44:b9: + c2:c6:08:4e:da:fa:3a:55:da:96:7c:01:f6:d5:e8:3b:ba:e9: + 31:3b:1c:51:39:1a:59:f0:e0:c7:17:2e:f6:18:9d:ec:a7:48: + 30:b8:4c:6d:e5:4a:4f:43:41:cb:0e:6b:ac:ad:87:44:90:76: + 85:23:2b:eb:8f:97:4b:22:13:60:20:3a:37:a4:dc:74:7d:85: + 3d:a1:f5:1a:03:f6:d5:78:c7:bc:9b:09:f2:c8:05:27:43:2a: + ac:50:21:3a:ee:83:2d:db:02:6f:c7:91:de:63:d6:36:7d:7a: + 9f:1f:fb:48:62:f4:fb:8e:3a:ea:61:9b:3c:03:f9:f8:a5:df: + 1b:02:14:2c:de:e6:e3:47:d2:44:65:94:1a:c6:e1:fd:ba:8d: + b6:f8:93:a9:46:46:26:79:b0:bf:57:a8:a2:20:66:56:7e:c9: + f5:a4:0b:5e:76:70:0a:47:a4:db:45:2e:15:99:69:f9:6b:14: + 93:2a:0a:b6:ee:53:a6:b9:02:9b:a2:25:37:1e:37:70:a2:7c: + 7f:c3:ce:98:17:2f:9b:5b:fa:6f:ae:d8:0e:d4:6a:b2:03:5a: + fe:ba:4b:7f:f6:98:20:ea:cb:be:17:34:e0:43:74:d1:0c:e5: + d4:cc:5d:13:41:d3:5e:a4:f6:94:f7:15:b8:15:a9:65:f8:28: + 3f:da:ef:b2:30:34:6d:96:3a:7a:f4:20:ec:9e:62:13:36:f1: + a7:04:e1:7a:d2:33:20:f6:61:4a:68:44:cb:92:d7:62:f0:e4: + 70:f0:a5:e3:dd:2f:e2:a3 +-----BEGIN CERTIFICATE----- +MIIFGTCCAwGgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAoMCU9wZW5SZXN0eTEiMCAGA1UE +AwwZT3BlblJlc3R5IFRlc3RpbmcgUm9vdCBDQTAeFw0xOTA5MTMyMjMwNDlaFw0y +OTA5MTAyMjMwNDlaMFAxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh +MRIwEAYDVQQKDAlPcGVuUmVzdHkxGDAWBgNVBAMMD2Zvb0BleGFtcGxlLmNvbTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANCMHiwlfwCdij2K87UdayT1 +rDV9zbfQr9uIfO6CRhZH80MIoQRuDT7OafrViRSCIPFH8jjIq+ovHvAVBMD0izzD +1HhWh0zxcKwRhi7Eam0QhCeByiqLhT5iE15AbBnkST3z3qroXhGh8maDakDRNMW/ +uMuXfGrqRr8XvjKNqDFW5YttCAPQRGm5rx4VHaVknhKEg9vZxnGQO8J7QSFXr3AV +C1ZZIaZORnFmkPHvvLJI+Yvq5XJKukquLXQLMwP2LkcPVqQA6B5iy7ivnJgaiXzQ +o3pa4YRQZORdpXCkaVTE9HZEor4b79yj2B0NMKLUefs5dqu3GPL3kviBg5S4EbEC +AwEAAaOB8jCB7zAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAzBglghkgB +hvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENlcnRpZmljYXRlMB0G +A1UdDgQWBBTS5PUhHBek/xP0Giiop9zG3omgMTAfBgNVHSMEGDAWgBS6ij56F2UM +VxBT6Pmo40wqHQ20VDAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUH +AwIGCCsGAQUFBwMEMCsGA1UdEQQkMCKBD2Zvb0BleGFtcGxlLmNvbYEPYmFyQGV4 +YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQBHd1E3APco2sTZTjjE7OokyYM2 +TJCTp7IrEL913wty2OdPT2jlMi81iReVXLtD/HCJRghDYaxBYoQBlIjR3Iq9MCwY +61F5C7cbtknfyYVV9nOft4OZUiP+5r0J2pC54ptoxN+9/iOUVTS+DX2EDFNpKg88 +R2g0Pyo/iT8+0ybOt1i80G/u+L1dxkiuoGwfbeBmk33bPAfmFa6q49A97wS23VMW +k2Fw6a/A6R3/K+UKA1ZIPxzc/humbfZUq0HlO1ur9YEQRia76tcOM7FeME2BhmOa +Sk8eRLnCxghO2vo6VdqWfAH21eg7uukxOxxRORpZ8ODHFy72GJ3sp0gwuExt5UpP +Q0HLDmusrYdEkHaFIyvrj5dLIhNgIDo3pNx0fYU9ofUaA/bVeMe8mwnyyAUnQyqs +UCE67oMt2wJvx5HeY9Y2fXqfH/tIYvT7jjrqYZs8A/n4pd8bAhQs3ubjR9JEZZQa +xuH9uo22+JOpRkYmebC/V6iiIGZWfsn1pAtednAKR6TbRS4VmWn5axSTKgq27lOm +uQKboiU3Hjdwonx/w86YFy+bW/pvrtgO1GqyA1r+ukt/9pgg6su+FzTgQ3TRDOXU +zF0TQdNepPaU9xW4Fall+Cg/2u+yMDRtljp69CDsnmITNvGnBOF60jMg9mFKaETL +ktdi8ORw8KXj3S/iow== +-----END CERTIFICATE----- diff --git a/t/cert/mtls_client.key b/t/cert/mtls_client.key new file mode 100644 index 0000000000..34b301f0bb --- /dev/null +++ b/t/cert/mtls_client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA0IweLCV/AJ2KPYrztR1rJPWsNX3Nt9Cv24h87oJGFkfzQwih +BG4NPs5p+tWJFIIg8UfyOMir6i8e8BUEwPSLPMPUeFaHTPFwrBGGLsRqbRCEJ4HK +KouFPmITXkBsGeRJPfPequheEaHyZoNqQNE0xb+4y5d8aupGvxe+Mo2oMVbli20I +A9BEabmvHhUdpWSeEoSD29nGcZA7wntBIVevcBULVlkhpk5GcWaQ8e+8skj5i+rl +ckq6Sq4tdAszA/YuRw9WpADoHmLLuK+cmBqJfNCjelrhhFBk5F2lcKRpVMT0dkSi +vhvv3KPYHQ0wotR5+zl2q7cY8veS+IGDlLgRsQIDAQABAoIBAEpoY++OZVT74LH6 +nN+XIn5qZUokm7yk6cnjVefndUhH3aSiNIkXFwS8sxV7ENDPaR+NcwANoUEKFPjG +Fw8dcXx5xpo1DUtHrdLG4eBX1j0Zsn1CErbBVwYeChkL1UYbrII9O8ow5DdYV9t5 +sfR0cGbJ9A43+31OH3XY69SvtD39xItgxK0Wg4Ciz475kCvG51Q1iBWAkm4koXhz +VCha4wghs81wJ28HRMFZAFf2C+72rk6EypMUX2dYirvW/+7zONirk298NDMAOSBh +mRWyPV8qipYx42hBQ9vSVm0UVb0ZbqVomKKUZfj11LL6Ad/OzCyVAiNLXyZREV6r +d324Bu0CgYEA/YPsE6p6H3MTPIoVTnsyyQw0pNmXtIAuYTgSveeuPoTYn3ZBWoGN +iLpbnW4EH3xNKfrdMjbqqLls1iwm7/ZAP5klAuL4s10onrcjMt65fyfa3Lw1gavG +SUFFdsueH2k3FohqNsbQUSXZILVQnXsRoldi38b7NKrAqABcEMAIqXMCgYEA0pde +nt4aMmrGBRPLnjCs1UlC5PbXzCE8XxxQ7HZKx4Sy5ErQ0EW1wzF6c0fEYI7i+j1/ +ESKqekzc5ue0T8acoioB+VUybO1oxQZsZUPY7roqXOYwZH9LQOdPYUOh9k33CZHw +6KFfx8bKCpdXn7FkwR2UUtCSp/6CZcyYr89Qn0sCgYAQ0L5I86bUDTL6cgJFyWAt ++7RGNvScEWCCLFD57bMeDHu93/8nvK4hopLPF2wIlpsbrLsdSI06EcqJTjZq9j9+ +uG6/CUULyKMYG/emuSU+rOsUdxtpdXZah4zO+2SKmtT/lp7M8VUB/OuxArXNLEuY +JAm35B/nd2f9/MAekE5CxwKBgQCV660w7G0590mB09XhiEWCkeVNm22FpSOVklMK +BCy4XX/9hkWh//6mN1M1PqJPG2n7PEx5pnQ3HQEmYU28fWiFCeLd3glIArvTh/8j +GGoXifEescFByl2IlyOr2roy3s4/weX/tuK5Fow/ff6jcWaJFMXDLzk437d1QXJx +tuVugQKBgByfr2eakXFQvAVGJUfVXA3M2BoBODZEPYTgryVMoEEduFy0HZiw4xKi +Dngwewy6/UJMAGA+8ak9Ca367FxnegZU9knm6ujYVyhU5WzbKpR8v7OaUP8d5icq +rCZZtglG0c8XfVpJjR4FsKA/qrFvKZpu5NdEw3o5/LSrV4HjqZQ6 +-----END RSA PRIVATE KEY----- diff --git a/t/cert/mtls_server.crt b/t/cert/mtls_server.crt new file mode 100644 index 0000000000..c4d320f4be --- /dev/null +++ b/t/cert/mtls_server.crt @@ -0,0 +1,112 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=California, O=OpenResty, CN=OpenResty Testing Root CA + Validity + Not Before: Sep 13 22:32:03 2019 GMT + Not After : Sep 10 22:32:03 2029 GMT + Subject: C=US, ST=California, O=OpenResty, CN=example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:69:2b:30:43:b0:b4:cc:84:3f:22:39:65:65: + 6a:bd:75:a4:2b:7d:f7:ec:e4:12:e8:d1:c4:ce:7e: + 4e:54:5c:22:cc:d2:18:7f:3b:9e:cb:70:d9:7d:79: + 8f:05:93:b6:9f:2f:d5:33:d7:98:a2:ed:c5:00:93: + e4:ca:bc:cb:f0:e1:63:3e:07:6b:38:6f:4d:09:45: + f1:a1:3b:a3:ca:c0:47:c1:a1:0a:f8:c9:bb:c7:da: + 26:9d:d3:0b:35:24:01:3e:16:14:2e:44:38:8c:c9: + 09:02:41:9e:b6:fb:0c:aa:fc:d6:44:5e:27:ab:aa: + d5:c3:68:e1:dd:57:06:6c:4f:f6:24:33:a8:2b:49: + 60:82:0e:15:aa:55:9f:61:cc:74:39:7e:9f:a6:4f: + 71:4a:8b:eb:43:dd:c2:f7:90:38:df:a6:a6:a8:f6: + 77:bc:9e:54:69:30:83:4c:2a:eb:b8:62:7c:c7:14: + 84:9e:f3:e1:4a:15:33:51:65:a3:af:9d:09:c6:b8: + 89:30:a3:d2:18:e9:dc:5d:6b:ea:68:ca:8b:5c:e4: + 3b:fe:32:7f:48:c3:4c:f0:b5:06:f6:23:97:3e:f2: + 50:90:68:26:39:6d:b2:e2:53:89:71:6a:48:f0:f1: + fc:89:3c:6d:db:87:6c:79:23:ed:87:5d:c5:fa:8a: + 0d:b9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Cert Type: + SSL Server + Netscape Comment: + OpenSSL Generated Server Certificate + X509v3 Subject Key Identifier: + 8C:8E:18:2C:13:84:C9:2A:61:6B:73:3F:18:76:A4:85:55:5F:5C:5F + X509v3 Authority Key Identifier: + keyid:BA:8A:3E:7A:17:65:0C:57:10:53:E8:F9:A8:E3:4C:2A:1D:0D:B4:54 + DirName:/C=US/ST=California/O=OpenResty/CN=OpenResty Testing Root CA + serial:7D:38:7C:F4:DC:B1:C6:66:D5:C0:D6:7F:60:57:5D:B2:C5:9C:F9:69 + + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication + Signature Algorithm: sha256WithRSAEncryption + 80:9f:3e:f5:8b:50:ee:cb:e4:c2:f0:16:01:07:a1:af:76:bc: + da:c8:cd:24:e9:63:df:d3:47:28:8c:7f:58:14:5d:d4:fd:44: + 16:c3:06:15:be:90:ec:1c:8f:78:34:11:e7:cc:86:d8:2a:a2: + e5:99:70:83:76:4a:65:a4:e1:9a:68:20:29:c0:7a:c6:4a:08: + b3:74:c3:53:b5:7b:79:92:f1:99:b5:a1:a3:90:ce:9a:cb:26: + a5:a6:33:de:74:98:99:ec:18:d1:1e:41:be:f8:c3:d2:8d:aa: + 07:de:9a:97:28:0d:bf:70:ac:2b:cf:b7:ff:bc:ac:e4:16:0c: + 1c:03:a7:5a:2d:64:0d:90:16:bd:97:c3:1f:f5:bf:a9:fa:15: + d1:e0:d4:0d:f7:b3:51:23:ce:ad:16:4f:41:72:17:aa:01:d5: + 44:e2:9e:d5:ce:ea:54:98:04:43:14:2e:51:4b:c7:d9:21:4f: + e1:a4:fa:dd:e0:f0:82:ec:6f:9f:be:a2:3c:3b:85:f7:6d:96: + ee:0d:e6:08:2b:1b:be:06:a4:b7:5f:a3:f2:f2:b9:d0:5a:8f: + 90:86:1a:f4:7a:9f:c8:ae:09:1d:60:a2:8b:e0:0b:f6:00:21: + d9:df:33:4b:39:75:b6:64:9b:c7:df:e4:85:7a:ae:df:72:8c: + 8b:7e:98:8e:47:0a:27:1f:8e:2c:11:7f:7b:fc:a0:db:1b:6e: + f6:de:4e:85:ac:30:e6:e8:6a:7a:e6:f9:f4:18:0a:c6:ad:1c: + e1:0c:dd:e0:e0:8d:5a:d7:08:34:e7:22:b4:44:bd:99:39:b1: + 71:74:3f:7c:aa:65:f5:37:46:85:d3:79:f7:a8:35:8d:2b:30: + 99:d2:47:ce:a6:74:eb:f3:9f:d3:9a:4e:99:96:50:7b:ba:22: + c8:72:47:d4:da:6e:9a:73:01:3c:89:e9:3f:56:17:b7:ba:22: + 71:db:66:a2:d2:fb:33:51:36:f6:b6:f2:5b:32:70:9d:e7:e3: + 36:d6:ae:cb:9b:62:ef:69:c7:f7:ba:95:49:16:f5:7c:d9:29: + bb:0a:02:b1:6b:72:15:ab:2c:27:7b:c8:bc:f6:15:1f:fa:ae: + 08:fd:e0:11:36:b1:ab:9c:c8:11:d1:d3:0d:7d:49:4e:ca:e6: + 73:ee:0d:c3:8d:6f:f5:a4:fe:a1:af:6b:91:f7:53:fd:10:df: + 77:dd:ef:ec:7b:cf:32:75:df:04:8a:d1:a1:f7:36:68:ee:65: + e3:43:90:37:43:e8:d1:a8:e2:90:5c:1c:75:0a:29:94:4a:6a: + 9b:89:28:43:bd:85:56:0d:f1:2b:44:bd:e6:7a:4c:b7:85:10: + 77:b7:a8:0f:33:29:a7:26 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAoMCU9wZW5SZXN0eTEiMCAGA1UE +AwwZT3BlblJlc3R5IFRlc3RpbmcgUm9vdCBDQTAeFw0xOTA5MTMyMjMyMDNaFw0y +OTA5MTAyMjMyMDNaMEwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh +MRIwEAYDVQQKDAlPcGVuUmVzdHkxFDASBgNVBAMMC2V4YW1wbGUuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu2krMEOwtMyEPyI5ZWVqvXWkK333 +7OQS6NHEzn5OVFwizNIYfzuey3DZfXmPBZO2ny/VM9eYou3FAJPkyrzL8OFjPgdr +OG9NCUXxoTujysBHwaEK+Mm7x9omndMLNSQBPhYULkQ4jMkJAkGetvsMqvzWRF4n +q6rVw2jh3VcGbE/2JDOoK0lggg4VqlWfYcx0OX6fpk9xSovrQ93C95A436amqPZ3 +vJ5UaTCDTCrruGJ8xxSEnvPhShUzUWWjr50JxriJMKPSGOncXWvqaMqLXOQ7/jJ/ +SMNM8LUG9iOXPvJQkGgmOW2y4lOJcWpI8PH8iTxt24dseSPth13F+ooNuQIDAQAB +o4IBNTCCATEwCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4 +QgENBCYWJE9wZW5TU0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNV +HQ4EFgQUjI4YLBOEySpha3M/GHakhVVfXF8wgZcGA1UdIwSBjzCBjIAUuoo+ehdl +DFcQU+j5qONMKh0NtFShXqRcMFoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp +Zm9ybmlhMRIwEAYDVQQKDAlPcGVuUmVzdHkxIjAgBgNVBAMMGU9wZW5SZXN0eSBU +ZXN0aW5nIFJvb3QgQ0GCFH04fPTcscZm1cDWf2BXXbLFnPlpMA4GA1UdDwEB/wQE +AwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAgEAgJ8+ +9YtQ7svkwvAWAQehr3a82sjNJOlj39NHKIx/WBRd1P1EFsMGFb6Q7ByPeDQR58yG +2Cqi5Zlwg3ZKZaThmmggKcB6xkoIs3TDU7V7eZLxmbWho5DOmssmpaYz3nSYmewY +0R5BvvjD0o2qB96alygNv3CsK8+3/7ys5BYMHAOnWi1kDZAWvZfDH/W/qfoV0eDU +DfezUSPOrRZPQXIXqgHVROKe1c7qVJgEQxQuUUvH2SFP4aT63eDwguxvn76iPDuF +922W7g3mCCsbvgakt1+j8vK50FqPkIYa9HqfyK4JHWCii+AL9gAh2d8zSzl1tmSb +x9/khXqu33KMi36YjkcKJx+OLBF/e/yg2xtu9t5Ohaww5uhqeub59BgKxq0c4Qzd +4OCNWtcINOcitES9mTmxcXQ/fKpl9TdGhdN596g1jSswmdJHzqZ06/Of05pOmZZQ +e7oiyHJH1NpumnMBPInpP1YXt7oicdtmotL7M1E29rbyWzJwnefjNtauy5ti72nH +97qVSRb1fNkpuwoCsWtyFassJ3vIvPYVH/quCP3gETaxq5zIEdHTDX1JTsrmc+4N +w41v9aT+oa9rkfdT/RDfd93v7HvPMnXfBIrRofc2aO5l40OQN0Po0ajikFwcdQop +lEpqm4koQ72FVg3xK0S95npMt4UQd7eoDzMppyY= +-----END CERTIFICATE----- diff --git a/t/cert/mtls_server.key b/t/cert/mtls_server.key new file mode 100644 index 0000000000..3509beb661 --- /dev/null +++ b/t/cert/mtls_server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAu2krMEOwtMyEPyI5ZWVqvXWkK3337OQS6NHEzn5OVFwizNIY +fzuey3DZfXmPBZO2ny/VM9eYou3FAJPkyrzL8OFjPgdrOG9NCUXxoTujysBHwaEK ++Mm7x9omndMLNSQBPhYULkQ4jMkJAkGetvsMqvzWRF4nq6rVw2jh3VcGbE/2JDOo +K0lggg4VqlWfYcx0OX6fpk9xSovrQ93C95A436amqPZ3vJ5UaTCDTCrruGJ8xxSE +nvPhShUzUWWjr50JxriJMKPSGOncXWvqaMqLXOQ7/jJ/SMNM8LUG9iOXPvJQkGgm +OW2y4lOJcWpI8PH8iTxt24dseSPth13F+ooNuQIDAQABAoIBABnT/KfCLHA+X1t0 +FATtXTCPLfjwe2KibBi6EC2FKrZlnEYuDkI6rT/MZaztO9DA8sItjWx/ogGSUzwp +JbbrHhAsf8jkrNoyPKOyiAJ4fbJLnZgJ4cE3zDFW10uY8kp4k9NCp7VYoZKFgkBV +WtJM9wn5nm39q+n0uVEc+0PN4oy6m54Aqb1HqVCyXFp+/pVhL6PtgaClbqJd3oKV +0/HLWfWaI3nvV6ltAphUfPoCmYIUtSl90sRgSeEaJ61UZXh0OkhhtD7Iw/JUlHDk +a0J7owrh0Wf1kDsaSn+j1ba8MELsspFYYVm0gAMKAvRXbVrYgUMdb+HVdZ0odULl +ezFWeAECgYEA9nnoZs+PzKWNxTzYPtgvvrSLmpXLzNrs/p41JUhy6GjQIixTSBFy +WHkjwu0k2fvRgODfcaetAyK6sV4uTpRgqUhtFSeyNMelZ2yiIEqvhUrtHoVov1C+ +BqwwlUnmkQZNQODXOpKCvnqnOaPwMILKLtxDGmPtW0tCTR2dVVaht6ECgYEAwqb/ +h0Fh3YtykOnhV8wOZRrpVr8jS1RIgg/hklt2xh6+OYtL16sKFaLBF/BhzZRBapqd +fB2Cx3B6rxZ5PLTse8yjEvjt6Ly7TusYWpaKbYKFnnEbmdsm5sBepuLUv4AoMYbk +99ZejFcQI2gNbzX7eIrFitCQGxT+Wu7Gncv+vxkCgYBvAYCVrS2KcZVkG38Y7qyy +KwYk3QoofQD3u7Eb1YFLAsmaWnQ3pQPmrMhaZguO0UcN0DlSKr5VBzMl5tDcOx89 +noziVjqAYtovtlFeUcSzN4eLk3IVl/u9bZeD5QCemEP60Eie7JVNzFe8MgVfE8iT +Skg+fnrL/x0hNhFB+f5jgQKBgDgOEX4o5P8A3nA++gbnm6mgE1xI1OgnkG3sFuCn ++E9boRo/NAsalV/fq82yCuhB7oi9l+abNQMsMBhl12oVDBkmuDuJdjHUz/gNGclU +mu6obMRQ/ErVYqGG+nsCzZOMW4bPuvZoRHgTxnD70QqauB1hkTvFjgpOhGU5Z/cf +PPBZAoGBAJQK7NF6VoF9nm5CT8vufrQ2vvp2aiLdOLLx5JXt/6seEnPZWtEvjp8/ ++ExIsfOIaU5elhv8ze8iKmRP9f04XdWpbRm6k6AR5cOkkQQ1oO7N9abU7KbD/gqX +pJIWOlaUrbKO4Dprx7HyMYYPs9mu/UoF0Dvd/+bYXM5ZKiFrQ3Ly +-----END RSA PRIVATE KEY-----