async-io 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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