async-io 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3fbd77d42c8f025d30053dc7e421240f1f2c68fa
4
- data.tar.gz: 402ee863245252e8e3f19723876301650c9e6439
2
+ SHA256:
3
+ metadata.gz: bb235e6d1285f39304e2feaaff9a1d2b7d37d237600b205438509d3b96bb9f9e
4
+ data.tar.gz: a84f31c19838358f8cd486659acc2bb76d6ab4f87f1f6fcb16506e5e6649231f
5
5
  SHA512:
6
- metadata.gz: dae197ce5e7a47b42b3ec929777ab4baae97182f6e5c3fda6953223c983f1d9cc0f4034c495c12aa6a5e742b520aa138b17633ed667989fc8e714dad6e8a670e
7
- data.tar.gz: 3ccb61d3e991fd5d52beabca6e6da9ee834adc637803c42405bd101446ba3dbbc7927119391a14b09605557346715947c5234be66e61fd944332a3984cfbd762
6
+ metadata.gz: 2aac0ebf53a9a4535747dec63f2f1864d4c57f043cfb9b3c1498a0e7f647d8b42fbe2fb493810d8e13990d79b42576f227bf6131918e899b41b101bd1a5e6c30
7
+ data.tar.gz: df5224b997090982c11c3ed2c3b52386f2e86b6416bfb537d32140b189e101ac7e7f6504bc224fd4ef8e122f65429ef1c3bcb3c8d8a15983c1dfed661fabc65b
data/README.md CHANGED
@@ -82,6 +82,8 @@ end
82
82
  ## See Also
83
83
 
84
84
  - [async](https://github.com/socketry/async) — Asynchronous event-driven reactor.
85
+ - [async-process](https://github.com/socketry/async-process) — Asynchronous process spawning/waiting.
86
+ - [async-websocket](https://github.com/socketry/async-websocket) — Asynchronous client and server websockets.
85
87
  - [async-dns](https://github.com/socketry/async-dns) — Asynchronous DNS resolver and server.
86
88
  - [async-rspec](https://github.com/socketry/async-rspec) — Shared contexts for running async specs.
87
89
  - [rubydns](https://github.com/ioquatix/rubydns) — A easy to use Ruby DNS server.
@@ -26,7 +26,6 @@ module Async
26
26
  Address = Addrinfo
27
27
 
28
28
  class Endpoint < Struct.new(:specification, :options)
29
- include ::Socket::Constants
30
29
  include Comparable
31
30
 
32
31
  class << self
@@ -36,23 +35,32 @@ module Async
36
35
  end
37
36
 
38
37
  def tcp(*args, **options)
39
- self.new(Address.tcp(*args), **options)
38
+ AddressEndpoint.new(Address.tcp(*args), **options)
40
39
  end
41
40
 
42
41
  def udp(*args, **options)
43
- self.new(Address.udp(*args), **options)
42
+ AddressEndpoint.new(Address.udp(*args), **options)
44
43
  end
45
44
 
46
45
  def unix(*args, **options)
47
- self.new(Address.unix(*args), **options)
46
+ AddressEndpoint.new(Address.unix(*args), **options)
48
47
  end
49
48
 
49
+ def ssl(*args, **options)
50
+ SecureEndpoint.new(Endpoint.tcp(*args, **options), **options)
51
+ end
52
+
53
+ # Generate a list of endpoints from an array.
50
54
  def each(specifications, &block)
55
+ return to_enum(:each, specifications) unless block_given?
56
+
51
57
  specifications.each do |specification|
52
58
  if specification.is_a? self
53
59
  yield specification
54
60
  elsif specification.is_a? Array
55
61
  yield self.send(*specification)
62
+ elsif specification.is_a? String
63
+ yield self.parse(specification)
56
64
  else
57
65
  yield self.new(specification)
58
66
  end
@@ -71,17 +79,6 @@ module Async
71
79
  # This is how addresses are internally converted, e.g. within `Socket#sendto`.
72
80
  alias to_str to_sockaddr
73
81
 
74
- def address
75
- @address ||= case specification
76
- when Addrinfo
77
- specification
78
- when ::BasicSocket, BasicSocket
79
- specification.local_address
80
- else
81
- raise ArgumentError, "Not sure how to convert #{specification} into address!"
82
- end
83
- end
84
-
85
82
  # SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, etc.
86
83
  def socket_type
87
84
  address.socktype
@@ -97,38 +94,89 @@ module Async
97
94
  address.protocol
98
95
  end
99
96
 
100
- def bind(&block)
101
- case specification
102
- when Addrinfo
103
- Socket.bind(specification, **options, &block)
104
- when ::BasicSocket
105
- yield Socket.new(specification)
106
- when BasicSocket
107
- yield specification
108
- else
109
- raise ArgumentError, "Not sure how to bind to #{specification}!"
110
- end
97
+ def bind
98
+ yield specification
111
99
  end
112
100
 
113
101
  def accept(&block)
114
- backlog = self.options.fetch(:backlog, SOMAXCONN)
102
+ backlog = self.options.fetch(:backlog, Socket::SOMAXCONN)
115
103
 
116
- bind do |socket|
117
- socket.listen(backlog)
118
- socket.accept_each(&block)
104
+ bind do |server|
105
+ server.listen(backlog)
106
+ server.accept_each(&block)
119
107
  end
120
108
  end
121
109
 
110
+ def connect
111
+ yield specification
112
+ end
113
+ end
114
+
115
+ # This class will open and close the socket automatically.
116
+ class AddressEndpoint < Endpoint
117
+ def address
118
+ specification
119
+ end
120
+
121
+ def bind(&block)
122
+ Socket.bind(specification, **options, &block)
123
+ end
124
+
122
125
  def connect(&block)
123
- case specification
124
- when Addrinfo
125
- Socket.connect(specification, &block)
126
- when ::BasicSocket
127
- yield Async::IO.try_convert(specification)
128
- when BasicSocket
129
- yield specification
126
+ Socket.connect(specification, &block)
127
+ end
128
+ end
129
+
130
+ # This class doesn't exert ownership over the specified socket.
131
+ class SocketEndpoint < Endpoint
132
+ def address
133
+ specification.local_address
134
+ end
135
+
136
+ def bind(&block)
137
+ yield Socket.new(specification, **options)
138
+ end
139
+
140
+ def connect(&block)
141
+ yield Async::IO.try_convert(specification)
142
+ end
143
+ end
144
+
145
+ class SecureEndpoint < Endpoint
146
+ def params
147
+ options[:ssl_params]
148
+ end
149
+
150
+ def context
151
+ if context = options[:ssl_context]
152
+ if params = self.params
153
+ context = context.dup
154
+ context.set_params(params)
155
+ end
130
156
  else
131
- raise ArgumentError, "Not sure how to connect to #{specification}!"
157
+ context = ::OpenSSL::SSL::SSLContext.new
158
+
159
+ if params = self.params
160
+ context.set_params(params)
161
+ end
162
+ end
163
+
164
+ return context
165
+ end
166
+
167
+ def bind(&block)
168
+ specification.bind do |server|
169
+ yield SSLServer.new(server, context)
170
+ end
171
+ end
172
+
173
+ def connect(&block)
174
+ specification.connect do |socket|
175
+ ssl_socket = SSLSocket.connect_socket(socket, context)
176
+
177
+ ssl_socket.connect
178
+
179
+ yield ssl_socket
132
180
  end
133
181
  end
134
182
  end
@@ -33,7 +33,7 @@ module Async
33
33
  # @!macro [attach] wrap_blocking_method
34
34
  # @method $1
35
35
  # Invokes `$2` on the underlying {io}. If the operation would block, the current task is paused until the operation can succeed, at which point it's resumed and the operation is completed.
36
- def wrap_blocking_method(new_name, method_name, invert: true, &block)
36
+ def wrap_blocking_method(new_name, method_name, invert: true)
37
37
  define_method(new_name) do |*args|
38
38
  async_send(method_name, *args)
39
39
  end
@@ -94,17 +94,9 @@ module Async
94
94
  @io.__send__(*args, exception: false)
95
95
  end
96
96
  end
97
- else
98
- def async_send(*args)
99
- async do
100
- @io.__send__(*args)
101
- end
102
- end
103
- end
104
-
105
- def async
106
- while true
107
- begin
97
+
98
+ def async
99
+ while true
108
100
  result = yield
109
101
 
110
102
  case result
@@ -115,10 +107,42 @@ module Async
115
107
  else
116
108
  return result
117
109
  end
118
- rescue ::IO::WaitReadable
119
- wait_readable
120
- rescue ::IO::WaitWritable
121
- wait_writable
110
+ end
111
+ end
112
+ elsif RUBY_VERSION >= "2.1"
113
+ def async_send(*args)
114
+ async do
115
+ @io.__send__(*args)
116
+ end
117
+ end
118
+
119
+ def async
120
+ while true
121
+ begin
122
+ return yield
123
+ rescue ::IO::WaitReadable, ::IO::EAGAINWaitReadable
124
+ wait_readable
125
+ rescue ::IO::WaitWritable, ::IO::EAGAINWaitWritable
126
+ wait_writable
127
+ end
128
+ end
129
+ end
130
+ else
131
+ def async_send(*args)
132
+ async do
133
+ @io.__send__(*args)
134
+ end
135
+ end
136
+
137
+ def async
138
+ while true
139
+ begin
140
+ return yield
141
+ rescue ::IO::WaitReadable
142
+ wait_readable
143
+ rescue ::IO::WaitWritable
144
+ wait_writable
145
+ end
122
146
  end
123
147
  end
124
148
  end
@@ -36,19 +36,23 @@ module Async
36
36
  end
37
37
 
38
38
  module ServerSocket
39
- def accept
39
+ def accept(task: Task.current)
40
40
  peer, address = async_send(:accept_nonblock)
41
41
 
42
+ wrapper = Socket.new(peer, self.reactor)
43
+
42
44
  if block_given?
43
- wrapper = Socket.new(peer, self.reactor)
44
-
45
- begin
46
- yield wrapper, address
47
- ensure
48
- wrapper.close
45
+ task.async do
46
+ task.annotate "incoming connection #{address}"
47
+
48
+ begin
49
+ yield wrapper, address
50
+ ensure
51
+ wrapper.close
52
+ end
49
53
  end
50
54
  else
51
- return Socket.new(peer, self.reactor), address
55
+ return wrapper, address
52
56
  end
53
57
  end
54
58
 
@@ -56,14 +60,8 @@ module Async
56
60
  task.annotate "accepting connections #{self.local_address.inspect}"
57
61
 
58
62
  while true
59
- task.async(*self.accept) do |task, io, address|
60
- task.annotate "incoming connection #{address}"
61
-
62
- begin
63
- yield io, address
64
- ensure
65
- io.close
66
- end
63
+ self.accept(task: task) do |io, address|
64
+ yield io, address
67
65
  end
68
66
  end
69
67
  end
@@ -73,7 +71,6 @@ module Async
73
71
  wraps ::Socket, :bind, :ipv6only!, :listen
74
72
 
75
73
  include ::Socket::Constants
76
-
77
74
  include ServerSocket
78
75
 
79
76
  def connect(*args)
@@ -85,7 +82,7 @@ module Async
85
82
  end
86
83
 
87
84
  def self.build(*args, task: Task.current)
88
- socket = ::Socket.new(*args)
85
+ socket = wrapped_klass.new(*args)
89
86
 
90
87
  yield socket
91
88
 
@@ -102,10 +99,10 @@ module Async
102
99
  # @param remote_address [Addrinfo] The remote address to connect to.
103
100
  # @param local_address [Addrinfo] The local address to bind to before connecting.
104
101
  # @option protcol [Integer] The socket protocol to use.
105
- def self.connect(remote_address, local_address = nil, task: Task.current)
102
+ def self.connect(remote_address, local_address = nil, task: Task.current, **options)
106
103
  task.annotate "connecting to #{remote_address.inspect}"
107
104
 
108
- wrapper = build(remote_address.afamily, remote_address.socktype, remote_address.protocol) do |socket|
105
+ wrapper = build(remote_address.afamily, remote_address.socktype, remote_address.protocol, **options) do |socket|
109
106
  socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, true)
110
107
 
111
108
  if local_address
@@ -140,10 +137,10 @@ module Async
140
137
  # @param local_address [Address] The local address to bind to.
141
138
  # @option protocol [Integer] The socket protocol to use.
142
139
  # @option reuse_port [Boolean] Allow this port to be bound in multiple processes.
143
- def self.bind(local_address, protocol: 0, reuse_port: false, task: Task.current, &block)
140
+ def self.bind(local_address, protocol: 0, reuse_port: false, task: Task.current, **options, &block)
144
141
  task.annotate "binding to #{local_address.inspect}"
145
142
 
146
- wrapper = build(local_address.afamily, local_address.socktype, protocol) do |socket|
143
+ wrapper = build(local_address.afamily, local_address.socktype, protocol, **options) do |socket|
147
144
  socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, true)
148
145
  socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEPORT, true) if reuse_port
149
146
  socket.bind(local_address.to_sockaddr)
@@ -0,0 +1,98 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'socket'
22
+
23
+ require 'openssl'
24
+
25
+ module Async
26
+ module IO
27
+ SSLError = OpenSSL::SSL::SSLError
28
+
29
+ # Asynchronous TCP socket wrapper.
30
+ class SSLSocket < Generic
31
+ wraps ::OpenSSL::SSL::SSLSocket, :alpn_protocol, :cert, :cipher, :client_ca, :hostname=, :npn_protocol, :peer_cert, :peer_cert_chain, :pending, :post_connection_check, :session, :session=, :session_reused?, :ssl_version, :state
32
+
33
+ wrap_blocking_method :accept, :accept_nonblock
34
+ wrap_blocking_method :connect, :connect_nonblock
35
+
36
+ def local_address
37
+ @io.to_io.local_address
38
+ end
39
+
40
+ def remote_address
41
+ @io.to_io.remote_address
42
+ end
43
+
44
+ def self.connect_socket(socket, context)
45
+ io = wrapped_klass.new(socket.io, context)
46
+
47
+ # This ensures that when the internal IO is closed, it also closes the internal socket:
48
+ io.sync_close = true
49
+
50
+ return self.new(io, socket.reactor)
51
+ end
52
+ end
53
+
54
+ class SSLServer
55
+ extend Forwardable
56
+
57
+ def initialize(server, context)
58
+ @server = server
59
+ @context = context
60
+ end
61
+
62
+ def_delegators :@server, :local_address, :setsockopt, :getsockopt
63
+
64
+ attr :server
65
+ attr :context
66
+
67
+ include ServerSocket
68
+
69
+ def listen(*args)
70
+ @server.listen(*args)
71
+ end
72
+
73
+ def accept(task: Task.current)
74
+ peer, address = @server.accept
75
+
76
+ wrapper = SSLSocket.connect_socket(peer, @context)
77
+
78
+ if block_given?
79
+ task.async do
80
+ task.annotate "accepting secure connection #{address}"
81
+
82
+ begin
83
+ wrapper.accept
84
+
85
+ yield wrapper, address
86
+ rescue SSLError
87
+ Async.logger.error($!.class) {$!}
88
+ ensure
89
+ wrapper.close
90
+ end
91
+ end
92
+ else
93
+ return wrapper, address
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module IO
23
- VERSION = "1.0.0"
23
+ VERSION = "1.1.0"
24
24
  end
25
25
  end
@@ -33,7 +33,7 @@ RSpec.describe Async::IO::Endpoint do
33
33
  end
34
34
  end
35
35
 
36
- describe Async::IO::Endpoint.new(TCPServer.new('0.0.0.0', 1234)) do
36
+ describe Async::IO::SocketEndpoint.new(TCPServer.new('0.0.0.0', 1234)) do
37
37
  it "should be a tcp binding" do
38
38
  expect(subject.socket_type).to be == ::Socket::SOCK_STREAM
39
39
  end
@@ -0,0 +1,31 @@
1
+ #!/bin/sh
2
+
3
+ get_subject() {
4
+ if [ "$1" = "trusted" ]
5
+ then
6
+ echo "/C=US/ST=California/L=San Francisco/O=Celluloid/OU=Socketry/CN=localhost"
7
+ else
8
+ echo "/C=XX/ST=Untrusted/L=Evilville/O=Evil Hacker/OU=Attack Department/CN=localhost"
9
+ fi
10
+ }
11
+
12
+ # Generate two CAs: one to be considered trusted, and one that's untrusted
13
+ for type in trusted untrusted; do
14
+ rm -rf ./demoCA
15
+ mkdir -p ./demoCA
16
+ mkdir -p ./demoCA/certs
17
+ mkdir -p ./demoCA/crl
18
+ mkdir -p ./demoCA/newcerts
19
+ mkdir -p ./demoCA/private
20
+ touch ./demoCA/index.txt
21
+
22
+ openssl genrsa -out ${type}-ca.key 2048
23
+ openssl req -new -x509 -days 12500 -key ${type}-ca.key -out ${type}-ca.crt -subj "$(get_subject $type)"
24
+ openssl x509 -in ${type}-ca.crt -noout -next_serial -out ./demoCA/serial
25
+
26
+ openssl req -newkey rsa:2048 -keyout ${type}-cert.key -nodes -out ${type}-cert.req -subj "$(get_subject $type)"
27
+ openssl ca -days 12500 -cert ${type}-ca.crt -keyfile ${type}-ca.key -out ${type}-cert.crt -infiles ${type}-cert.req
28
+ rm ${type}-cert.req
29
+ done
30
+
31
+ rm -rf ./demoCA
@@ -0,0 +1,25 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIESjCCAzKgAwIBAgIJAPCsnL6/gRaRMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV
3
+ BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp
4
+ c2NvMRIwEAYDVQQKEwlDZWxsdWxvaWQxETAPBgNVBAsTCFNvY2tldHJ5MRIwEAYD
5
+ VQQDEwlsb2NhbGhvc3QwIBcNMTYwOTEwMTY0OTIwWhgPMjA1MDEyMDExNjQ5MjBa
6
+ MHUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
7
+ YW4gRnJhbmNpc2NvMRIwEAYDVQQKEwlDZWxsdWxvaWQxETAPBgNVBAsTCFNvY2tl
8
+ dHJ5MRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
9
+ ggEKAoIBAQDAXdhY1LlZrTBTxecJzNvYYKXgp2ya6Qqvb8e+knhw7674kM5EB5Qw
10
+ 3dxt1msdgzfqlwBQUIJSUtsi2jwcVXlHs9c6gePkiZJMCNag5fyi/o2kQmlOQFR8
11
+ N9uOhd4YThZRD7/Aoa04FMmIPeNYtVnkx8lbZO5MWN3RQ+ppovYhP/d/IWHUpXs1
12
+ J/H4fZxucsDMKo5zX36VuEdFAyIgxZ8lw1/dp3BwAl+82Pcs+GSwPFawAcvVKkOt
13
+ OwE9Edw8iNlKWjgcwGSfNHwJoyr10YK/f90CzdZbJGofEZbHxueAT1bftEqHf4zv
14
+ vs5mp9TkkQh0UuQpwalp050In7lrkI9TAgMBAAGjgdowgdcwHQYDVR0OBBYEFGh2
15
+ jJPd4xrU5D+QV4WiErIWUWbiMIGnBgNVHSMEgZ8wgZyAFGh2jJPd4xrU5D+QV4Wi
16
+ ErIWUWbioXmkdzB1MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW
17
+ MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzESMBAGA1UEChMJQ2VsbHVsb2lkMREwDwYD
18
+ VQQLEwhTb2NrZXRyeTESMBAGA1UEAxMJbG9jYWxob3N0ggkA8Kycvr+BFpEwDAYD
19
+ VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAERiepnBTfYOto5yNXP2um6MI
20
+ R8ly66ImTixYpn3PtToPrkQ4Smgp/B7E2P6uFkFyrx8d5yd+r42yZ07ZJXM/qXg1
21
+ xggtpls+LeqQi4b6FXoJpSRmyG2cbd0oznOnR3ebrBHd/gP13H3sc0FQjrQ6ERJh
22
+ kWffK2pka3Q9KGJc2ygCYTpG4wPNRqMohAT49CqwdrbOn43Nnt/tQKu6yluKCM0h
23
+ 1tOv9RFlAJhhbKyB9uFDPGD9TNbyk4wHCw9CviIg5Ao1MWUS9uBR+pMESpt9ewQz
24
+ H/Y5nPIDYF9i2zekavtbgibjMEQ1N2Qs2y/2Y5A5YiihfN8iWwBMW4QJx8QLBg==
25
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEAwF3YWNS5Wa0wU8XnCczb2GCl4KdsmukKr2/HvpJ4cO+u+JDO
3
+ RAeUMN3cbdZrHYM36pcAUFCCUlLbIto8HFV5R7PXOoHj5ImSTAjWoOX8ov6NpEJp
4
+ TkBUfDfbjoXeGE4WUQ+/wKGtOBTJiD3jWLVZ5MfJW2TuTFjd0UPqaaL2IT/3fyFh
5
+ 1KV7NSfx+H2cbnLAzCqOc19+lbhHRQMiIMWfJcNf3adwcAJfvNj3LPhksDxWsAHL
6
+ 1SpDrTsBPRHcPIjZSlo4HMBknzR8CaMq9dGCv3/dAs3WWyRqHxGWx8bngE9W37RK
7
+ h3+M777OZqfU5JEIdFLkKcGpadOdCJ+5a5CPUwIDAQABAoIBACmvrISDhK8UQtbE
8
+ mi6bgEDBoPCwF27ydWhTNtvrbcI7jpU6/Bft9IUqbuw2fPvmRaXGl0DQUY15exdw
9
+ Z3pUY3XQWSHKqBIMZfGoMKqpbDf+Jb+kzKEye5x3llKqW9i0g02JtioOXzU5+/pU
10
+ PwIoOpTDXrU5iBJvZ5JDv3ao4+GMVDKOlxsmMqW0rq4gDm48tZTyQpXlvAx+adXb
11
+ YF8n1KQ6Nx6lDinCVz9MjBdQ3vNrN/VMaVIIl0knG2oMmNRvf9xDasLYGkuLbj+E
12
+ 0O2WjzgopBsj7Qq59u7w262qvYqfMkVx1lGUHmITVAXso+b5l/RThbw3MoJYedLy
13
+ GPzC1eECgYEA+wcRjIPNkEd/+UoiaHx3EKi6faKtwq2DStkXjODYk/viVwhG+5bV
14
+ blXf0gjv79jleYn1LAu0FoolYVMur5aHzdJBvjWZl6Uq649xe6CwaGKZikWiMe6I
15
+ 4TRkSqxKjahJcEb4VUjAWL/pruBXOUkF1SQ9GRkIdXCwfzYhA0BTeCsCgYEAxC1Q
16
+ OhVxiSi4XiacKEJkmbiDN6O7inoGp3rcE6wBBQipDwTRLJZBXauwzRslpzMWMvo0
17
+ TjHnWn6A3e/fKCjUAu3jWq2GrS+UE7kMXSDdPW2Fl8fzAKGxY1XAwPng4EpdRd5Y
18
+ 5LVGin10wZ/mOURF0jEy2XRaMeP1E3MtRePJyXkCgYB4SonZSOu/wNONdT4JzeMM
19
+ g55iSAt2J8mrm15Srwh52ZE73YaOV1hNeC86Kfg4ejp0xGxNQAp7ZpXFDqRnlf3b
20
+ 3m6MpIjGh2qK2QErmfQPAXjMLtQrkz/ak02gDvHm8gbHG+syixtJLCXiHDUQCXMX
21
+ ETeKCFnqVSbuvtSRB0k4YwKBgGjq+x81XLVIS+I+sAFwELGN1s+pB6H1xR1JPe5f
22
+ bWQtz4yyvNQlv+vC6RmozShw0AyPd+3iDqN9SJppsWWfAFRYueFDMOXqrj0mGJCu
23
+ BOTXcD1OuI277Ez+DcqnWTdbTisR0WTv9jwXAJyVUeGKu/TATzuxWJOaIPY4ARyB
24
+ yOexAoGAL75WiMSKtvZUAqTchEJxmhOuhHSaLF+b2VNnI4NCHK1aVrvH5jErPNIO
25
+ NTSj4GBr8wjaC0Zhvu6EAIlK9xMM7R41ZEQG/3HuRMcjf8kUkGmfJ2KjS5alC5Yh
26
+ BSV4gGcDsQ0nZEgSHZ8hSwzBrwXtd1jMNs4cMVPgiwb/BWOecQw=
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,83 @@
1
+ Certificate:
2
+ Data:
3
+ Version: 3 (0x2)
4
+ Serial Number:
5
+ f0:ac:9c:be:bf:81:16:92
6
+ Signature Algorithm: sha1WithRSAEncryption
7
+ Issuer: C=US, ST=California, L=San Francisco, O=Celluloid, OU=Socketry, CN=localhost
8
+ Validity
9
+ Not Before: Sep 10 16:49:21 2016 GMT
10
+ Not After : Dec 1 16:49:21 2050 GMT
11
+ Subject: C=US, ST=California, O=Celluloid, OU=Socketry, CN=localhost
12
+ Subject Public Key Info:
13
+ Public Key Algorithm: rsaEncryption
14
+ RSA Public Key: (2048 bit)
15
+ Modulus (2048 bit):
16
+ 00:b9:1f:61:e1:42:d2:4c:12:be:51:f1:7c:52:c8:
17
+ 67:a4:48:38:29:df:44:20:a2:6e:13:90:e6:5a:7f:
18
+ 88:c8:1d:5e:c3:11:58:06:a2:0c:30:fc:d6:a0:dd:
19
+ 3a:0d:dd:05:1f:76:47:51:e7:49:28:f4:90:09:65:
20
+ 1e:93:bb:c5:f8:07:16:48:00:67:72:13:1a:a6:cc:
21
+ 11:74:40:e1:ba:0c:ba:ef:7e:82:37:2a:62:3d:69:
22
+ cd:2f:f0:9a:a1:61:b6:f6:a4:fc:90:51:d1:81:5e:
23
+ 11:2f:55:1d:8a:30:31:3a:d3:99:7e:a9:ad:4c:52:
24
+ 6d:be:3e:28:cf:92:a1:cc:42:1d:04:39:95:97:38:
25
+ 2a:57:91:06:e7:cd:80:23:5c:76:7b:dc:77:a1:52:
26
+ 2a:1b:85:c1:57:44:37:97:aa:17:45:e8:3f:d0:11:
27
+ 53:07:00:06:2d:60:d3:a9:84:4c:97:4b:33:c4:77:
28
+ 2e:a1:79:af:8a:30:1a:67:61:17:1f:f7:0e:40:4b:
29
+ 8d:84:92:cd:22:57:30:85:65:b7:b0:2e:ac:a1:55:
30
+ d5:96:7f:a9:7f:24:dd:ba:88:37:46:6a:91:42:37:
31
+ e1:7d:e6:5c:2e:2b:33:1b:7e:b2:15:70:78:fe:61:
32
+ 71:d2:bc:cd:84:49:8d:9d:98:c5:c3:95:68:b6:34:
33
+ d4:d3
34
+ Exponent: 65537 (0x10001)
35
+ X509v3 extensions:
36
+ X509v3 Basic Constraints:
37
+ CA:FALSE
38
+ Netscape Comment:
39
+ OpenSSL Generated Certificate
40
+ X509v3 Subject Key Identifier:
41
+ AA:1B:00:42:93:AA:8F:15:5D:D7:B4:18:45:10:1E:75:45:C8:26:96
42
+ X509v3 Authority Key Identifier:
43
+ keyid:68:76:8C:93:DD:E3:1A:D4:E4:3F:90:57:85:A2:12:B2:16:51:66:E2
44
+
45
+ Signature Algorithm: sha1WithRSAEncryption
46
+ ab:3a:40:58:9f:04:fd:17:2d:bd:6c:e2:58:36:27:aa:30:68:
47
+ 8b:17:9d:29:60:a1:a5:ac:36:a3:11:df:ee:c9:8f:c6:c3:ae:
48
+ 7d:a0:2f:9c:f0:38:d6:1a:25:a7:2e:7a:98:ed:0f:67:9b:cb:
49
+ 7b:b1:4c:58:eb:b3:c5:80:86:10:43:f2:43:57:39:92:de:82:
50
+ c3:4d:02:66:56:80:a1:98:bb:d1:a6:a4:25:54:0c:ab:45:1d:
51
+ eb:70:52:ac:07:a2:6c:13:68:3a:80:f4:2c:04:11:c7:40:85:
52
+ 5c:46:71:d0:71:db:1f:35:33:8b:82:c6:09:b1:c5:96:12:ac:
53
+ e8:9e:a5:38:98:ac:3b:a6:86:64:95:87:36:d9:f8:9d:0a:bb:
54
+ 70:d8:c2:39:70:f3:8b:d1:56:fc:c0:28:e1:22:82:0a:e9:7e:
55
+ c6:6f:52:37:98:6f:48:56:e7:0f:49:48:9c:03:0d:c0:34:93:
56
+ 3c:b4:66:b2:b5:88:96:c7:31:27:02:b0:78:f7:12:81:31:c2:
57
+ e3:c6:8c:cf:f5:f6:cb:23:16:ed:b0:df:d9:e9:cb:2d:8b:6f:
58
+ 9e:d4:78:c6:73:a0:c1:13:48:32:65:39:fe:a3:f9:53:ee:6e:
59
+ 4b:73:0a:12:58:64:e5:9f:a2:67:65:fd:7a:1a:30:3a:ed:28:
60
+ f2:b2:b8:31
61
+ -----BEGIN CERTIFICATE-----
62
+ MIID0jCCArqgAwIBAgIJAPCsnL6/gRaSMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV
63
+ BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp
64
+ c2NvMRIwEAYDVQQKEwlDZWxsdWxvaWQxETAPBgNVBAsTCFNvY2tldHJ5MRIwEAYD
65
+ VQQDEwlsb2NhbGhvc3QwIBcNMTYwOTEwMTY0OTIxWhgPMjA1MDEyMDExNjQ5MjFa
66
+ MF0xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQKEwlD
67
+ ZWxsdWxvaWQxETAPBgNVBAsTCFNvY2tldHJ5MRIwEAYDVQQDEwlsb2NhbGhvc3Qw
68
+ ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5H2HhQtJMEr5R8XxSyGek
69
+ SDgp30Qgom4TkOZaf4jIHV7DEVgGogww/Nag3ToN3QUfdkdR50ko9JAJZR6Tu8X4
70
+ BxZIAGdyExqmzBF0QOG6DLrvfoI3KmI9ac0v8JqhYbb2pPyQUdGBXhEvVR2KMDE6
71
+ 05l+qa1MUm2+PijPkqHMQh0EOZWXOCpXkQbnzYAjXHZ73HehUiobhcFXRDeXqhdF
72
+ 6D/QEVMHAAYtYNOphEyXSzPEdy6hea+KMBpnYRcf9w5AS42Eks0iVzCFZbewLqyh
73
+ VdWWf6l/JN26iDdGapFCN+F95lwuKzMbfrIVcHj+YXHSvM2ESY2dmMXDlWi2NNTT
74
+ AgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2Vu
75
+ ZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSqGwBCk6qPFV3XtBhFEB51Rcgm
76
+ ljAfBgNVHSMEGDAWgBRodoyT3eMa1OQ/kFeFohKyFlFm4jANBgkqhkiG9w0BAQUF
77
+ AAOCAQEAqzpAWJ8E/RctvWziWDYnqjBoixedKWChpaw2oxHf7smPxsOufaAvnPA4
78
+ 1holpy56mO0PZ5vLe7FMWOuzxYCGEEPyQ1c5kt6Cw00CZlaAoZi70aakJVQMq0Ud
79
+ 63BSrAeibBNoOoD0LAQRx0CFXEZx0HHbHzUzi4LGCbHFlhKs6J6lOJisO6aGZJWH
80
+ Ntn4nQq7cNjCOXDzi9FW/MAo4SKCCul+xm9SN5hvSFbnD0lInAMNwDSTPLRmsrWI
81
+ lscxJwKwePcSgTHC48aMz/X2yyMW7bDf2enLLYtvntR4xnOgwRNIMmU5/qP5U+5u
82
+ S3MKElhk5Z+iZ2X9ehowOu0o8rK4MQ==
83
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEAuR9h4ULSTBK+UfF8UshnpEg4Kd9EIKJuE5DmWn+IyB1ewxFY
3
+ BqIMMPzWoN06Dd0FH3ZHUedJKPSQCWUek7vF+AcWSABnchMapswRdEDhugy6736C
4
+ NypiPWnNL/CaoWG29qT8kFHRgV4RL1UdijAxOtOZfqmtTFJtvj4oz5KhzEIdBDmV
5
+ lzgqV5EG582AI1x2e9x3oVIqG4XBV0Q3l6oXReg/0BFTBwAGLWDTqYRMl0szxHcu
6
+ oXmvijAaZ2EXH/cOQEuNhJLNIlcwhWW3sC6soVXVln+pfyTduog3RmqRQjfhfeZc
7
+ LiszG36yFXB4/mFx0rzNhEmNnZjFw5VotjTU0wIDAQABAoIBACqtrn4lTqBVLeVs
8
+ W/Il26cHM1OL8oPnjqMaI9E3V8xy4Pbt17Jnx5G/qKebeRfbHaQ8O4MJZFd50n8n
9
+ /d2nS6O71oow9ahZ+Sn9IAUCNEgVST+Pleur7MwlyTVFLhEImwrPzJ5lDnzZt/KG
10
+ l/HU3HSoddm6uoY+9qgGYphAQOb67kYEJv+e5b8lTn0dXC7ZoG0MhqVlDh+wyHnD
11
+ KcvtycVfGCOFVnUXbeuahLwPAvximNs/TIrHmDSIyuns31/I9OyWUMWwzgWIRw4q
12
+ AaVA3j4OOaw8sfuWj0eQ1w/R1x5gAn+gMvqKRWKvCR/Ulmg5YRRqamc8aJsrvORl
13
+ TGI4J1kCgYEA7JWjN7Tj0v2Qd1tkCJm+o0mz2MqNl4/QaJ3VgEM0VuaJ1qdsd7jI
14
+ 0/JhXbNKxr0mnmE+UqI5t/zQ0xWpsPqY1i+Y0B+SkGTpQpQBBGYZg064fufJOnYe
15
+ RPp2WADvmS5ZZZzujbILlwztctPzt4dPmGY8JlSKtdOQR4qeXI39n0cCgYEAyFCX
16
+ D6jb1R9tbd/g4UdWKoLyQPkZvSVnpAMgRmZO/V3YnaxfOBTDEKF/t7oUVL41xvM4
17
+ /5xuzJkhi7DxV0ImRr7+DDuUxO0r1vXDhQdzsq9wuxlZW+9hiPCYFpkMLR/Lj2MQ
18
+ zhUnQJ0FhFY/gDOnrQkEw9O2Gky61vh1LdCtHBUCgYBbmiijJg/cHr9z51fZGKY+
19
+ lQfklbCzEUTxbMNAsUSvrP2LtjGCPXLM1ZkrbYMzZgNw6Vf3KMbOXT4BrO6SDsVk
20
+ kPNLCh52eAv08ldee6W/OJio0lgQobFgpdVyh5I9rjuA431eMaTZLHE3t6cy1VpV
21
+ OKhrcupuMmc3vA1K6tNbewKBgCnkgNMrk14NBou2CIfUrXaSkCt6bSGbkwNADB3t
22
+ A5QFbmn7RKar4Oe3fshjyCC47vI+p6r9gkaTt+pJBRAkq3CcPPE9/Kz6lPKNz2gg
23
+ 2NeDzWWztXZ+p71F4+jF9T/yqFXCeB9BWUYwEJlOmFUteGG9wxtZSXpSlbijmY4N
24
+ WEbJAoGAZnARe+/aW767Yej2shBwF8gwEvoKZMjl+VdsHCR9E2MsyRh/KsFSLp8a
25
+ O4axayeRI1ROSFd/6AX3ch1zHxHNomab1z1zBPuAnVrdoxnsiSWvMIg5RfAAPiBP
26
+ +N5kBedH6VmkGymOR03Tr3VYcyY9sHrCZfsD44880inh4Z/T3lA=
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,26 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEXDCCA0SgAwIBAgIJAJ0IEx1+1dDLMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNV
3
+ BAYTAlhYMRIwEAYDVQQIEwlVbnRydXN0ZWQxEjAQBgNVBAcTCUV2aWx2aWxsZTEU
4
+ MBIGA1UEChMLRXZpbCBIYWNrZXIxGjAYBgNVBAsTEUF0dGFjayBEZXBhcnRtZW50
5
+ MRIwEAYDVQQDEwlsb2NhbGhvc3QwIBcNMTYwOTEwMTY0OTMzWhgPMjA1MDEyMDEx
6
+ NjQ5MzNaMHsxCzAJBgNVBAYTAlhYMRIwEAYDVQQIEwlVbnRydXN0ZWQxEjAQBgNV
7
+ BAcTCUV2aWx2aWxsZTEUMBIGA1UEChMLRXZpbCBIYWNrZXIxGjAYBgNVBAsTEUF0
8
+ dGFjayBEZXBhcnRtZW50MRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3
9
+ DQEBAQUAA4IBDwAwggEKAoIBAQCyKMLmY2mCc1A/18g+EsKNmiHysMianeGx2Zs2
10
+ O2J3FYO//C4qkiGENjqoGmILbH12ARjZT2K30/yr9x62oxUHe27OB07uFcgAkRER
11
+ GW2zTwl8ElrbvhXJTL8Y6WW4kKWzwT0lQR3Ag/swQmIXnAYQ1WXA/furQOGruUrw
12
+ yBJZHUDHXTcnHpB5l/EDWKYXaIqNPAwA6ZjZ7GYFGZamrrGfdHSjCiGZON2mWSKx
13
+ 45NHWZnI1WA3uyvSjz61GNiSOwiDUWhgMqyqUzyspDEsZoJLcJ+LJxrT+/aAE6uq
14
+ xv+ChnGRUV6OX+OIrcysmJOcyzHGYnQAIGTNc8HZRqJ6/kC9AgMBAAGjgeAwgd0w
15
+ HQYDVR0OBBYEFLDHtNv69Ad0jKRLK15D6UxjUrOyMIGtBgNVHSMEgaUwgaKAFLDH
16
+ tNv69Ad0jKRLK15D6UxjUrOyoX+kfTB7MQswCQYDVQQGEwJYWDESMBAGA1UECBMJ
17
+ VW50cnVzdGVkMRIwEAYDVQQHEwlFdmlsdmlsbGUxFDASBgNVBAoTC0V2aWwgSGFj
18
+ a2VyMRowGAYDVQQLExFBdHRhY2sgRGVwYXJ0bWVudDESMBAGA1UEAxMJbG9jYWxo
19
+ b3N0ggkAnQgTHX7V0MswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA
20
+ msrLcoUQp0RT8PkOmB580e8QxZljRJVgtHJrQszFLyPtGW9bhIBsf3M72+BjPPvx
21
+ 6QUO303y1bkcu/suG6WGa4gm59FGMOOvxSQKNC0q2SwmjDyZG3zNLvC3xE0olEte
22
+ y3zcxoN+8kvh9QDij2g51J97yqbwZ8v9midBYZ28d7Nq+I/9w6GxfEHHvBV/ACJx
23
+ AaoRS++oGS8DGyHoFWqoQ5f1c7vk0QhyG5a7YKT7jk30IKkwVte1pQCk8VOpF06K
24
+ TSA/WB/OlLThcZdcQlTw3YrrvCr95oqBDV+9AFXfaJkM+h/2AENtkJvhW3Y/jw7T
25
+ f71xbWagZXclIxthRIt+DQ==
26
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEpAIBAAKCAQEAsijC5mNpgnNQP9fIPhLCjZoh8rDImp3hsdmbNjtidxWDv/wu
3
+ KpIhhDY6qBpiC2x9dgEY2U9it9P8q/cetqMVB3tuzgdO7hXIAJERERlts08JfBJa
4
+ 274VyUy/GOlluJCls8E9JUEdwIP7MEJiF5wGENVlwP37q0Dhq7lK8MgSWR1Ax103
5
+ Jx6QeZfxA1imF2iKjTwMAOmY2exmBRmWpq6xn3R0owohmTjdplkiseOTR1mZyNVg
6
+ N7sr0o8+tRjYkjsIg1FoYDKsqlM8rKQxLGaCS3Cfiyca0/v2gBOrqsb/goZxkVFe
7
+ jl/jiK3MrJiTnMsxxmJ0ACBkzXPB2Uaiev5AvQIDAQABAoIBAG+8jthN+yt8xRT1
8
+ cbo0q96Bj88VPwtx/846i1UNE6laTgJH2HCMrAauuEUcHufJSDqNX5dTabefdbYo
9
+ zBOB3ruNl6YSAVfjQ0fPs+OEjj/KT0mIfYGaCzHwN14Za9nAppxBkubdmxpV7GGN
10
+ ENZ73XYLUMEkygXTMHYyRSUUZiWK3jEuU6oPk5krzYbvf86c6BEtyMe9/T6625qM
11
+ BPVhFD6EEyZpp1SBcwvqzHqvZ1nc0mQ7fQhstlFmiBplzHPp8woEWd6NPhduyyAb
12
+ aTkZuy3TSOJ26FaA92wYR3KrAaQdxusNvEkRBxIVJDMRBWQawRi2v6mRKJWnrMe2
13
+ A1InbWUCgYEA3iX8OTuf/6KsEFthAwd0Ndo8TC/q/BRnHrlUi9y9eT2jKfk4kWdh
14
+ ge+VkdAoT1A07r8P+HOlbxTB7gBJEIzqjZ91WsG9wa5VP4N2kGDgFHRq/OgyWpDa
15
+ P5zB3sTWQLgzKlEJM3OgvfxX7IdsE+Uh7KkkrEI4q59U7VKz2x5HvRcCgYEAzU7C
16
+ ARAQsftN6x1wNIQs6qNBQiIU6N0plYOdVXgop3DOlZ4MZZ+iYi0zj1pS35ucmQtd
17
+ xZBkWH83F8ME1zz5Sn2SDL3L7coBP8EFD7kqHLNzFhQuSfQ2KYf1iBhRZLduseRx
18
+ NElB4H0UxRUHYCoPl73YFtOEsXIhoVO29vhL3UsCgYEAtxl177JuaOSqj3zR1A5T
19
+ wYNUCbPBKe6jJBa7UeAqJ4EfOBxbfLVKEC/qBtocL2s7hcDjJ/Qh2hGw2jtP/Z04
20
+ Qmy47IodnkLTrtrrYYsHhrSB7lxwDGeyC5Zn0PZKZeOtAGb0f30BczZHPgRMl4VX
21
+ VdoACR832HUmKcntxmAJ3xcCgYEAgcWjiWpvMyEnClNsRjW58oJI0JWcY+jPzSsJ
22
+ OyodgGEko5voOCAkUyxBJ/6u3ZqN7IsrtaJkWy/mUgW6PJbU+InQ1G7vxRlnmrXW
23
+ Di87eDLRrwYIkERmK/A9ec3tPN1ZgeZky+j2VACcLUryg41yl7avLRZ8DHGY4lF5
24
+ GDiwM2sCgYBbooN99DdxduI8ERICkqlDO0v8WM682xsX/6fljnNosyx++sH6hLuJ
25
+ mSpNt59mIi5eOJ9eHPiB/qw+FuZevU0wQgsOgyQ6t/AtLFQLmt6HOERUkgWOGipq
26
+ FEiawsFJfJtucyOzfhZGdjzXSzarLyHjjWpg206LiFFOP0whNnhE7g==
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,83 @@
1
+ Certificate:
2
+ Data:
3
+ Version: 3 (0x2)
4
+ Serial Number:
5
+ 9d:08:13:1d:7e:d5:d0:cc
6
+ Signature Algorithm: sha1WithRSAEncryption
7
+ Issuer: C=XX, ST=Untrusted, L=Evilville, O=Evil Hacker, OU=Attack Department, CN=localhost
8
+ Validity
9
+ Not Before: Sep 10 16:49:33 2016 GMT
10
+ Not After : Dec 1 16:49:33 2050 GMT
11
+ Subject: C=XX, ST=Untrusted, O=Evil Hacker, OU=Attack Department, CN=localhost
12
+ Subject Public Key Info:
13
+ Public Key Algorithm: rsaEncryption
14
+ RSA Public Key: (2048 bit)
15
+ Modulus (2048 bit):
16
+ 00:9b:6b:27:d0:31:39:bc:3b:57:27:70:c2:ec:78:
17
+ dc:52:e9:8b:98:d9:ef:c0:8c:c6:cb:c1:8d:48:5c:
18
+ 6e:17:8c:8d:bd:68:be:ad:77:40:e1:d2:bb:c1:20:
19
+ 54:a6:7f:d5:d8:4b:5b:af:ac:a9:c7:8b:76:2b:da:
20
+ 31:b9:13:0f:6f:19:69:fe:1b:60:ee:59:5a:0e:cb:
21
+ 0b:e7:88:4e:89:1b:75:4c:0d:ef:21:c2:7a:38:bf:
22
+ 95:96:5b:8e:eb:90:ca:8a:2c:09:1d:4c:bd:e5:e8:
23
+ 4d:82:06:64:99:51:4c:2f:07:69:80:f6:87:a4:4c:
24
+ 74:9c:d8:92:0d:fa:8c:d2:64:95:c5:a2:b3:9d:b4:
25
+ 01:2d:03:68:94:3d:42:31:e0:cc:9f:0b:fe:d1:3c:
26
+ 79:ed:8b:96:80:32:df:f1:e1:96:e2:3a:32:94:f7:
27
+ d4:05:40:5d:f7:17:b1:52:39:e6:7c:6b:92:be:30:
28
+ 2e:88:b8:55:d1:df:fe:45:dd:93:c6:94:47:28:57:
29
+ e2:31:be:26:33:f7:e1:8a:d6:3a:a8:9d:c2:c5:5b:
30
+ 51:0b:c2:21:20:68:72:eb:b6:0c:b0:58:13:e8:e4:
31
+ bd:1f:91:53:c8:3e:07:d4:16:37:70:f9:e1:07:d3:
32
+ 56:18:39:de:9d:00:e6:f8:d5:32:71:67:df:7b:dc:
33
+ 96:bb
34
+ Exponent: 65537 (0x10001)
35
+ X509v3 extensions:
36
+ X509v3 Basic Constraints:
37
+ CA:FALSE
38
+ Netscape Comment:
39
+ OpenSSL Generated Certificate
40
+ X509v3 Subject Key Identifier:
41
+ 42:B1:92:1D:66:1A:E4:DC:49:3E:65:4B:79:3B:8C:E3:0E:96:0B:87
42
+ X509v3 Authority Key Identifier:
43
+ keyid:B0:C7:B4:DB:FA:F4:07:74:8C:A4:4B:2B:5E:43:E9:4C:63:52:B3:B2
44
+
45
+ Signature Algorithm: sha1WithRSAEncryption
46
+ a1:ed:c0:3f:02:4b:e4:77:2a:2c:98:b4:5f:3f:ed:a2:c8:a4:
47
+ 91:5b:8e:7d:c2:83:3a:07:1d:e6:31:56:18:ef:bd:d8:53:ae:
48
+ a2:e8:b0:c3:f1:1f:43:5f:d9:23:56:10:a6:ff:df:42:b0:4f:
49
+ 94:d5:38:28:21:b4:5e:14:f6:96:ca:89:0c:8d:11:57:1c:83:
50
+ 1d:9b:bf:14:54:f3:50:60:f2:57:c0:41:37:47:7b:0d:46:f9:
51
+ 21:65:65:05:12:58:34:a8:8e:38:14:8b:5a:e7:b3:c9:f4:6f:
52
+ 3f:85:8c:3d:cd:87:d7:3e:76:e7:02:f0:11:4b:c5:af:61:e5:
53
+ 7f:ec:1d:92:e6:70:8a:b2:1f:36:5b:25:29:bd:92:39:9a:e2:
54
+ d8:cf:95:f1:20:ac:68:61:fb:b2:28:3e:b4:01:52:d8:27:a6:
55
+ ef:81:14:27:af:8a:4f:05:fe:c8:02:86:6e:66:a3:c4:e5:c8:
56
+ 0f:f6:91:6b:da:db:2c:f6:11:6c:bb:29:0c:e3:3d:87:b4:64:
57
+ ab:4a:5f:19:d3:75:11:68:ef:37:a5:f0:b2:2a:45:2e:d9:06:
58
+ d4:86:7e:44:56:15:53:3c:08:5e:8a:fd:be:46:e0:f4:4a:01:
59
+ d3:9f:bb:82:a5:ac:0d:6a:d4:b3:bc:11:eb:df:47:a2:14:5e:
60
+ 3c:66:0f:5d
61
+ -----BEGIN CERTIFICATE-----
62
+ MIID4jCCAsqgAwIBAgIJAJ0IEx1+1dDMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNV
63
+ BAYTAlhYMRIwEAYDVQQIEwlVbnRydXN0ZWQxEjAQBgNVBAcTCUV2aWx2aWxsZTEU
64
+ MBIGA1UEChMLRXZpbCBIYWNrZXIxGjAYBgNVBAsTEUF0dGFjayBEZXBhcnRtZW50
65
+ MRIwEAYDVQQDEwlsb2NhbGhvc3QwIBcNMTYwOTEwMTY0OTMzWhgPMjA1MDEyMDEx
66
+ NjQ5MzNaMGcxCzAJBgNVBAYTAlhYMRIwEAYDVQQIEwlVbnRydXN0ZWQxFDASBgNV
67
+ BAoTC0V2aWwgSGFja2VyMRowGAYDVQQLExFBdHRhY2sgRGVwYXJ0bWVudDESMBAG
68
+ A1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
69
+ m2sn0DE5vDtXJ3DC7HjcUumLmNnvwIzGy8GNSFxuF4yNvWi+rXdA4dK7wSBUpn/V
70
+ 2Etbr6ypx4t2K9oxuRMPbxlp/htg7llaDssL54hOiRt1TA3vIcJ6OL+VlluO65DK
71
+ iiwJHUy95ehNggZkmVFMLwdpgPaHpEx0nNiSDfqM0mSVxaKznbQBLQNolD1CMeDM
72
+ nwv+0Tx57YuWgDLf8eGW4joylPfUBUBd9xexUjnmfGuSvjAuiLhV0d/+Rd2TxpRH
73
+ KFfiMb4mM/fhitY6qJ3CxVtRC8IhIGhy67YMsFgT6OS9H5FTyD4H1BY3cPnhB9NW
74
+ GDnenQDm+NUycWffe9yWuwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIB
75
+ DQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUQrGS
76
+ HWYa5NxJPmVLeTuM4w6WC4cwHwYDVR0jBBgwFoAUsMe02/r0B3SMpEsrXkPpTGNS
77
+ s7IwDQYJKoZIhvcNAQEFBQADggEBAKHtwD8CS+R3KiyYtF8/7aLIpJFbjn3CgzoH
78
+ HeYxVhjvvdhTrqLosMPxH0Nf2SNWEKb/30KwT5TVOCghtF4U9pbKiQyNEVccgx2b
79
+ vxRU81Bg8lfAQTdHew1G+SFlZQUSWDSojjgUi1rns8n0bz+FjD3Nh9c+ducC8BFL
80
+ xa9h5X/sHZLmcIqyHzZbJSm9kjma4tjPlfEgrGhh+7IoPrQBUtgnpu+BFCevik8F
81
+ /sgChm5mo8TlyA/2kWva2yz2EWy7KQzjPYe0ZKtKXxnTdRFo7zel8LIqRS7ZBtSG
82
+ fkRWFVM8CF6K/b5G4PRKAdOfu4KlrA1q1LO8EevfR6IUXjxmD10=
83
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEAm2sn0DE5vDtXJ3DC7HjcUumLmNnvwIzGy8GNSFxuF4yNvWi+
3
+ rXdA4dK7wSBUpn/V2Etbr6ypx4t2K9oxuRMPbxlp/htg7llaDssL54hOiRt1TA3v
4
+ IcJ6OL+VlluO65DKiiwJHUy95ehNggZkmVFMLwdpgPaHpEx0nNiSDfqM0mSVxaKz
5
+ nbQBLQNolD1CMeDMnwv+0Tx57YuWgDLf8eGW4joylPfUBUBd9xexUjnmfGuSvjAu
6
+ iLhV0d/+Rd2TxpRHKFfiMb4mM/fhitY6qJ3CxVtRC8IhIGhy67YMsFgT6OS9H5FT
7
+ yD4H1BY3cPnhB9NWGDnenQDm+NUycWffe9yWuwIDAQABAoIBAAXqs25SoW8QF0ZS
8
+ HamhBEpHx9++1EjRUzQonzdVBX/yAudmGHREKP0v56P3liFslniQjeIHQcNuBMaw
9
+ nNn95sWFAysAYdVRI4OSqVZcMxk3KWUG1sbDP6HvcUNzIuLG9V8DRCmQZV5eVK0R
10
+ jzzjAnJ75sFZIVrY6kuaVx0fH8NWr8d3NMEOivsXXfZy3QPFNrNiH46BB1dT9kMV
11
+ 2+TOvS0G59jWWy/+fhRNQNjLIXiHt5zrZRA+u/f25r0UAWff7vp5l0k3ljQOB1rx
12
+ Gg3OfkjI3xdWwK3h3RH31rUBs/JTNhWKMbUCMTTSqWdJTrwCXAFq3jt4G92fPCI8
13
+ HJ5Ei2ECgYEAzRAWLJUPTEc1o7uCje65MSSrRxbjtrlFXWe7in+FS+ragsAxbHZ+
14
+ tCFRhtQyPtAWRpNZDeX9rLBki8VI8+PUsOUA6EnXdXzaCY087tJrge6LZP+zeDgk
15
+ LWSaVlX2GZmoIJ6jBjHmPLdimpz2zRsk9Duk58pI+Z39lDnp3xF73AsCgYEAwgYy
16
+ ubGai3uSWt/TsTjEpceoV6AFDXQqj8rIFhInjjJdCDNbLfXOEjSmV9bJJCsIBWgy
17
+ jOvOB/gLBb4rgdWuxlfNaDnlUDNZAT2uICLji7Zfer/WbibnHGZ9OHjqwVxaofed
18
+ 1dOBiBv/NZzXDt1H4M6j+v7Nv2pTSEm7ERnrLhECgYByfFG08D+LOZJz6CMadLZF
19
+ /o/1b40Qnd1hKaHl0A4udV8rcnvlbz6L+LIYkW2/7dMR8f/dJ5N6Dz0DX9C8AW3k
20
+ mOXpyhgViu/8NzNWrnnBH9oJOE0NiGKCSVF1dCai4kugcpDXy5IcQdI2Of38QvRd
21
+ utL1adVWL2O8lpzAonVBQwKBgFF7juQDXXcEj2NQqrO7toI0xlL+ZgDPb2xx6fOy
22
+ 7h++sOlXwAweNcvZhp5PGqvw0m6K4ufhw+X+2oov4k+lcL/lceM6pT44QkHOKIlg
23
+ fZVYIuMHG8Oo3NhFhoMn7NcFtR5eQk/hgn2p3FUkqACbF6umvKEVT0z7Fzy9ki1N
24
+ aEIxAoGAHXvJ0Sc63asb8jw9Z9mPXK3Ke2z4zgxKmx6NGIEqM771U6+RWX1lVs1V
25
+ wrvNP3whwhc12ZSeDxiVDQsIFepsghIJOcc26muY7n9cyR8Y+DsV2OsTeeXk+AAC
26
+ CKlz+DopSb4TNMYy3TiYTg8g7VUyrsssZ6TSYetLXJbqh/AEK78=
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,98 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'async/io/ssl_socket'
22
+
23
+ RSpec.describe Async::Reactor do
24
+ include_context Async::RSpec::Leaks
25
+
26
+ let(:ssl_client_params) do
27
+ {
28
+ ca_file: File.expand_path(certificate_authority_key_file, __dir__)
29
+ }
30
+ end
31
+
32
+ let(:ssl_server_params) do
33
+ {
34
+ cert: OpenSSL::X509::Certificate.new(File.read(server_cert_file)),
35
+ key: OpenSSL::PKey::RSA.new(File.read(server_key_file))
36
+ }
37
+ end
38
+
39
+ # Shared port for localhost network tests.
40
+ let(:endpoint) {Async::IO::Endpoint.tcp("localhost", 6779, reuse_port: true)}
41
+ let(:server_endpoint) {Async::IO::SecureEndpoint.new(endpoint, ssl_params: ssl_server_params)}
42
+ let(:client_endpoint) {Async::IO::SecureEndpoint.new(endpoint, ssl_params: ssl_client_params)}
43
+
44
+ let(:data) {"The quick brown fox jumped over the lazy dog."}
45
+
46
+ around(:each) do |example|
47
+ # Accept a single incoming connection and then finish.
48
+ subject.async do |task|
49
+ server_endpoint.bind do |server|
50
+ server.listen(10)
51
+
52
+ server.accept do |peer, address|
53
+ data = peer.read(512)
54
+ peer.write(data)
55
+ end rescue nil
56
+ end
57
+ end
58
+
59
+ result = example.run
60
+
61
+ if result.is_a? Exception
62
+ result
63
+ else
64
+ subject.run
65
+ end
66
+ end
67
+
68
+ describe "#connect" do
69
+ context "with a trusted certificate" do
70
+ let(:certificate_authority_key_file) {File.expand_path("ssl/trusted-ca.crt", __dir__)}
71
+ let(:server_cert_file) {File.expand_path("ssl/trusted-cert.crt", __dir__)}
72
+ let(:server_key_file) {File.expand_path("ssl/trusted-cert.key", __dir__)}
73
+
74
+ it "should start server and send data" do
75
+ subject.async do
76
+ client_endpoint.connect do |client|
77
+ client.write(data)
78
+ expect(client.read(512)).to be == data
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ context "with an untrusted certificate" do
85
+ let(:certificate_authority_key_file) {File.expand_path("ssl/trusted-ca.crt", __dir__)}
86
+ let(:server_cert_file) {File.expand_path("ssl/untrusted-cert.crt", __dir__)}
87
+ let(:server_key_file) {File.expand_path("ssl/untrusted-cert.key", __dir__)}
88
+
89
+ it "should fail to connect" do
90
+ subject.async do
91
+ expect do
92
+ client_endpoint.connect
93
+ end.to raise_error(OpenSSL::SSL::SSLError)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -24,7 +24,7 @@ RSpec.describe Async::Reactor do
24
24
  include_context Async::RSpec::Leaks
25
25
 
26
26
  # Shared port for localhost network tests.
27
- let(:server_address) {Async::IO::Address.tcp("localhost", 6779)}
27
+ let(:server_address) {Async::IO::Address.tcp("localhost", 6788)}
28
28
  let(:data) {"The quick brown fox jumped over the lazy dog."}
29
29
 
30
30
  around(:each) do |example|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-io
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-30 00:00:00.000000000 Z
11
+ date: 2018-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -100,6 +100,7 @@ files:
100
100
  - lib/async/io/generic.rb
101
101
  - lib/async/io/protocol/line.rb
102
102
  - lib/async/io/socket.rb
103
+ - lib/async/io/ssl_socket.rb
103
104
  - lib/async/io/stream.rb
104
105
  - lib/async/io/tcp_socket.rb
105
106
  - lib/async/io/udp_socket.rb
@@ -112,6 +113,16 @@ files:
112
113
  - spec/async/io/generic_spec.rb
113
114
  - spec/async/io/protocol/line_spec.rb
114
115
  - spec/async/io/socket_spec.rb
116
+ - spec/async/io/ssl/gen_certs.sh
117
+ - spec/async/io/ssl/trusted-ca.crt
118
+ - spec/async/io/ssl/trusted-ca.key
119
+ - spec/async/io/ssl/trusted-cert.crt
120
+ - spec/async/io/ssl/trusted-cert.key
121
+ - spec/async/io/ssl/untrusted-ca.crt
122
+ - spec/async/io/ssl/untrusted-ca.key
123
+ - spec/async/io/ssl/untrusted-cert.crt
124
+ - spec/async/io/ssl/untrusted-cert.key
125
+ - spec/async/io/ssl_socket_spec.rb
115
126
  - spec/async/io/stream_spec.rb
116
127
  - spec/async/io/tcp_socket_spec.rb
117
128
  - spec/async/io/udp_socket_spec.rb
@@ -137,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
148
  version: '0'
138
149
  requirements: []
139
150
  rubyforge_project:
140
- rubygems_version: 2.6.10
151
+ rubygems_version: 2.7.2
141
152
  signing_key:
142
153
  specification_version: 4
143
154
  summary: Provides support for asynchonous TCP, UDP, UNIX and SSL sockets.
@@ -148,6 +159,16 @@ test_files:
148
159
  - spec/async/io/generic_spec.rb
149
160
  - spec/async/io/protocol/line_spec.rb
150
161
  - spec/async/io/socket_spec.rb
162
+ - spec/async/io/ssl/gen_certs.sh
163
+ - spec/async/io/ssl/trusted-ca.crt
164
+ - spec/async/io/ssl/trusted-ca.key
165
+ - spec/async/io/ssl/trusted-cert.crt
166
+ - spec/async/io/ssl/trusted-cert.key
167
+ - spec/async/io/ssl/untrusted-ca.crt
168
+ - spec/async/io/ssl/untrusted-ca.key
169
+ - spec/async/io/ssl/untrusted-cert.crt
170
+ - spec/async/io/ssl/untrusted-cert.key
171
+ - spec/async/io/ssl_socket_spec.rb
151
172
  - spec/async/io/stream_spec.rb
152
173
  - spec/async/io/tcp_socket_spec.rb
153
174
  - spec/async/io/udp_socket_spec.rb