tttls1.3 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/README.md +35 -13
- data/Rakefile +2 -4
- data/example/helper.rb +30 -7
- data/example/https_client.rb +3 -20
- data/example/https_client_using_0rtt.rb +10 -24
- data/example/https_client_using_hrr.rb +3 -20
- data/example/https_client_using_ticket.rb +3 -20
- data/example/https_server.rb +43 -0
- data/interop/client_spec.rb +111 -22
- data/interop/helper.rb +1 -0
- data/interop/server_spec.rb +182 -0
- data/lib/tttls1.3/client.rb +115 -98
- data/lib/tttls1.3/connection.rb +119 -32
- data/lib/tttls1.3/message/certificate.rb +18 -0
- data/lib/tttls1.3/message/client_hello.rb +38 -0
- data/lib/tttls1.3/message/encrypted_extensions.rb +20 -16
- data/lib/tttls1.3/message/extension/key_share.rb +24 -2
- data/lib/tttls1.3/message/extension/supported_groups.rb +0 -87
- data/lib/tttls1.3/message/extensions.rb +1 -27
- data/lib/tttls1.3/message/new_session_ticket.rb +14 -0
- data/lib/tttls1.3/message/record.rb +23 -20
- data/lib/tttls1.3/message/server_hello.rb +27 -0
- data/lib/tttls1.3/message.rb +35 -2
- data/lib/tttls1.3/named_group.rb +89 -0
- data/lib/tttls1.3/server.rb +439 -0
- data/lib/tttls1.3/transcript.rb +6 -0
- data/lib/tttls1.3/version.rb +1 -1
- data/lib/tttls1.3.rb +3 -0
- data/spec/certificate_spec.rb +28 -1
- data/spec/client_spec.rb +14 -10
- data/spec/connection_spec.rb +43 -13
- data/spec/encrypted_extensions_spec.rb +4 -4
- data/spec/fixtures/rsa_ca.crt +29 -0
- data/spec/fixtures/rsa_ca.key +51 -0
- data/spec/fixtures/rsa_rsa.crt +23 -0
- data/spec/fixtures/rsa_rsa.key +27 -0
- data/spec/fixtures/rsa_secp256r1.crt +19 -0
- data/spec/fixtures/rsa_secp256r1.key +5 -0
- data/spec/fixtures/rsa_secp384r1.crt +19 -0
- data/spec/fixtures/rsa_secp384r1.key +6 -0
- data/spec/fixtures/rsa_secp521r1.crt +20 -0
- data/spec/fixtures/rsa_secp521r1.key +7 -0
- data/spec/server_spec.rb +186 -0
- data/spec/spec_helper.rb +43 -0
- metadata +28 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39cf5b4e5fd508981bdefedc27502ac14b984699983d44160d9a836b2ab2aa2b
|
4
|
+
data.tar.gz: 0250c8ad97ef5bef6a52d7b6e22c990b842ce66a8ab6e2d3abc0c6ef90a4eb13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8ef15683ceabb9396eb51e5831f3dc48ed9c4df11871f10458160804891107fe3bff2d0c1810ad294134c8bec4d63534b2aee7cc6c8bff5f7ae07462bf753ef
|
7
|
+
data.tar.gz: 7baf720c22742962380449ad01372264634e878113858643cdc8a0db55e0f0cf07e0bd45cd80ad461cab9a337c89c7e0ad9c0e0057e02cbcda77a0765f10bdb9
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -12,29 +12,18 @@ Backward compatibility and performance are not an objective.
|
|
12
12
|
This gem should not be used for production software.
|
13
13
|
|
14
14
|
|
15
|
-
## Features
|
16
|
-
|
17
|
-
tttls1.3 provides client API with the following features:
|
18
|
-
|
19
|
-
* Simple 1-RTT Handshake
|
20
|
-
* HelloRetryRequest
|
21
|
-
* Resumed 0-RTT Handshake (with PSK from ticket)
|
22
|
-
|
23
|
-
NOT supports X25519, X448, FFDHE, AES-CCM, Client Authentication, Post-Handshake Authentication, KeyUpdate, external PSKs.
|
24
|
-
|
25
|
-
|
26
15
|
## Getting started
|
27
16
|
|
28
17
|
tttls1.3 gem is available at [rubygems.org](https://rubygems.org/gems/tttls1.3). You can install with:
|
29
18
|
|
30
|
-
```
|
19
|
+
```bash
|
31
20
|
$ gem install tttls1.3
|
32
21
|
```
|
33
22
|
|
34
23
|
This implementation provides only minimal API, so your code is responsible for application layer.
|
35
24
|
Roughly, this works as follows:
|
36
25
|
|
37
|
-
```
|
26
|
+
```ruby
|
38
27
|
require 'tttls1.3'
|
39
28
|
|
40
29
|
socket = YourTransport.new
|
@@ -46,9 +35,42 @@ client.read
|
|
46
35
|
client.close
|
47
36
|
```
|
48
37
|
|
38
|
+
```ruby
|
39
|
+
require 'tttls1.3'
|
40
|
+
|
41
|
+
socket = YourTransport.new
|
42
|
+
server = TTTLS13::Server.new(socket.accept)
|
43
|
+
server.accept
|
44
|
+
|
45
|
+
server.read
|
46
|
+
server.write(YOUR_MESSAGE)
|
47
|
+
server.close
|
48
|
+
```
|
49
|
+
|
49
50
|
HTTPS examples are [here](https://github.com/thekuwayama/tttls1.3/tree/master/example).
|
50
51
|
|
51
52
|
|
53
|
+
## Features
|
54
|
+
|
55
|
+
### Client
|
56
|
+
|
57
|
+
tttls1.3 provides client API with the following features:
|
58
|
+
|
59
|
+
* Simple 1-RTT Handshake
|
60
|
+
* HelloRetryRequest
|
61
|
+
* Resumed 0-RTT Handshake (with PSK from ticket)
|
62
|
+
|
63
|
+
**NOT supports** certificate with OID RSASSA-PSS, X25519, X448, FFDHE, AES-CCM, Client Authentication, Post-Handshake Authentication, KeyUpdate, external PSKs.
|
64
|
+
|
65
|
+
### Server
|
66
|
+
|
67
|
+
tttls1.3 provides server API with the following features:
|
68
|
+
|
69
|
+
* Simple 1-RTT Handshake
|
70
|
+
|
71
|
+
**NOT supports** certificate with OID RSASSA-PSS, X25519, X448, FFDHE, AES-CCM, Client Authentication, Post-Handshake Authentication, KeyUpdate, external PSKs.
|
72
|
+
|
73
|
+
|
52
74
|
## License
|
53
75
|
|
54
76
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -6,8 +6,6 @@ require 'rspec/core/rake_task'
|
|
6
6
|
require 'openssl'
|
7
7
|
require 'fileutils'
|
8
8
|
|
9
|
-
RuboCop::RakeTask.new
|
10
|
-
|
11
9
|
TMP_DIR = __dir__ + '/tmp'
|
12
10
|
CA_KEY = TMP_DIR + '/ca.key'
|
13
11
|
CA_CRT = TMP_DIR + '/ca.crt'
|
@@ -128,6 +126,6 @@ task :del_certs do
|
|
128
126
|
end
|
129
127
|
end
|
130
128
|
|
131
|
-
|
132
|
-
|
129
|
+
RuboCop::RakeTask.new
|
130
|
+
RSpec::Core::RakeTask.new(:spec)
|
133
131
|
task default: %i[rubocop spec]
|
data/example/helper.rb
CHANGED
@@ -4,13 +4,36 @@ $LOAD_PATH << __dir__ + '/../lib'
|
|
4
4
|
|
5
5
|
require 'socket'
|
6
6
|
require 'tttls1.3'
|
7
|
+
require 'webrick'
|
8
|
+
|
9
|
+
def simple_http_request(hostname)
|
10
|
+
s = <<~BIN
|
11
|
+
GET / HTTP/1.1
|
12
|
+
Host: #{hostname}
|
13
|
+
User-Agent: https_client
|
14
|
+
Accept: */*
|
7
15
|
|
8
|
-
def http_get(hostname)
|
9
|
-
<<~BIN
|
10
|
-
GET / HTTP/1.1\r
|
11
|
-
Host: #{hostname}\r
|
12
|
-
User-Agent: https_client\r
|
13
|
-
Accept: */*\r
|
14
|
-
\r
|
15
16
|
BIN
|
17
|
+
s.gsub("\n", "\r\n")
|
18
|
+
end
|
19
|
+
|
20
|
+
def recv_http_response(client)
|
21
|
+
# status line, header
|
22
|
+
buf = ''
|
23
|
+
buf += client.read until buf.include?(WEBrick::CRLF * 2)
|
24
|
+
header = buf.split(WEBrick::CRLF * 2).first
|
25
|
+
# header; Content-Length
|
26
|
+
cl_line = header.split(WEBrick::CRLF).find { |s| s.match(/Content-Length:/i) }
|
27
|
+
|
28
|
+
# body
|
29
|
+
unless cl_line.nil?
|
30
|
+
cl = cl_line.split(':').last.to_i
|
31
|
+
buf = buf.split(WEBrick::CRLF * 2)[1..].join
|
32
|
+
while buf.length < cl
|
33
|
+
s = client.read
|
34
|
+
buf += s
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
header + WEBrick::CRLF * 2 + buf
|
16
39
|
end
|
data/example/https_client.rb
CHANGED
@@ -4,29 +4,12 @@
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
6
|
hostname, port = (ARGV[0] || 'localhost:4433').split(':')
|
7
|
-
|
7
|
+
req = simple_http_request(hostname)
|
8
8
|
|
9
9
|
socket = TCPSocket.new(hostname, port)
|
10
10
|
settings = { ca_file: __dir__ + '/../tmp/ca.crt' }
|
11
11
|
client = TTTLS13::Client.new(socket, hostname, settings)
|
12
12
|
client.connect
|
13
|
-
client.write(
|
14
|
-
|
15
|
-
# status line, header
|
16
|
-
buffer = ''
|
17
|
-
buffer += client.read until buffer.include?("\r\n\r\n")
|
18
|
-
print header = buffer.split("\r\n\r\n").first
|
19
|
-
# header; Content-Length
|
20
|
-
cl_line = header.split("\r\n").find { |s| s.match(/Content-Length:/i) }
|
21
|
-
|
22
|
-
# body
|
23
|
-
unless cl_line.nil?
|
24
|
-
cl = cl_line.split(':').last.to_i
|
25
|
-
print buffer = buffer.split("\r\n\r\n")[1..].join
|
26
|
-
while buffer.length < cl
|
27
|
-
print s = client.read
|
28
|
-
buffer += s
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
13
|
+
client.write(req)
|
14
|
+
print recv_http_response(client)
|
32
15
|
client.close
|
@@ -4,7 +4,7 @@
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
6
|
hostname, port = (ARGV[0] || 'localhost:4433').split(':')
|
7
|
-
|
7
|
+
req = simple_http_request(hostname)
|
8
8
|
|
9
9
|
settings_2nd = {
|
10
10
|
ca_file: __dir__ + '/../tmp/ca.crt'
|
@@ -23,7 +23,9 @@ settings_1st = {
|
|
23
23
|
ca_file: __dir__ + '/../tmp/ca.crt',
|
24
24
|
process_new_session_ticket: process_new_session_ticket
|
25
25
|
}
|
26
|
-
|
26
|
+
|
27
|
+
succeed_early_data = false
|
28
|
+
|
27
29
|
[
|
28
30
|
# Initial Handshake:
|
29
31
|
settings_1st,
|
@@ -34,31 +36,15 @@ accepted_early_data = false
|
|
34
36
|
client = TTTLS13::Client.new(socket, hostname, settings)
|
35
37
|
|
36
38
|
# send message using early data; 0-RTT
|
37
|
-
client.early_data(
|
39
|
+
client.early_data(req) if i == 1 && settings.include?(:ticket)
|
38
40
|
client.connect
|
39
41
|
# send message after Simple 1-RTT Handshake
|
40
|
-
client.write(
|
41
|
-
|
42
|
-
# status line, header
|
43
|
-
buffer = ''
|
44
|
-
buffer += client.read until buffer.include?("\r\n\r\n")
|
45
|
-
print header = buffer.split("\r\n\r\n").first
|
46
|
-
# header; Content-Length
|
47
|
-
cl_line = header.split("\r\n").find { |s| s.match(/Content-Length:/i) }
|
48
|
-
|
49
|
-
# body
|
50
|
-
unless cl_line.nil?
|
51
|
-
cl = cl_line.split(':').last.to_i
|
52
|
-
print buffer = buffer.split("\r\n\r\n")[1..].join
|
53
|
-
while buffer.length < cl
|
54
|
-
print s = client.read
|
55
|
-
buffer += s
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
42
|
+
client.write(req) if i.zero? || !client.succeed_early_data?
|
43
|
+
print recv_http_response(client)
|
59
44
|
client.close
|
60
|
-
|
45
|
+
|
46
|
+
succeed_early_data = client.succeed_early_data?
|
61
47
|
end
|
62
48
|
|
63
49
|
puts "\n" + '-' * 10
|
64
|
-
puts "early data of 2nd handshake: #{
|
50
|
+
puts "early data of 2nd handshake: #{succeed_early_data}"
|
@@ -4,7 +4,7 @@
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
6
|
hostname, port = (ARGV[0] || 'localhost:4433').split(':')
|
7
|
-
|
7
|
+
req = simple_http_request(hostname)
|
8
8
|
|
9
9
|
socket = TCPSocket.new(hostname, port)
|
10
10
|
settings = {
|
@@ -13,23 +13,6 @@ settings = {
|
|
13
13
|
}
|
14
14
|
client = TTTLS13::Client.new(socket, hostname, settings)
|
15
15
|
client.connect
|
16
|
-
client.write(
|
17
|
-
|
18
|
-
# status line, header
|
19
|
-
buffer = ''
|
20
|
-
buffer += client.read until buffer.include?("\r\n\r\n")
|
21
|
-
print header = buffer.split("\r\n\r\n").first
|
22
|
-
# header; Content-Length
|
23
|
-
cl_line = header.split("\r\n").find { |s| s.match(/Content-Length:/i) }
|
24
|
-
|
25
|
-
# body
|
26
|
-
unless cl_line.nil?
|
27
|
-
cl = cl_line.split(':').last.to_i
|
28
|
-
print buffer = buffer.split("\r\n\r\n")[1..].join
|
29
|
-
while buffer.length < cl
|
30
|
-
print s = client.read
|
31
|
-
buffer += s
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
16
|
+
client.write(req)
|
17
|
+
print recv_http_response(client)
|
35
18
|
client.close
|
@@ -4,7 +4,7 @@
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
6
|
hostname, port = (ARGV[0] || 'localhost:4433').split(':')
|
7
|
-
|
7
|
+
req = simple_http_request(hostname)
|
8
8
|
|
9
9
|
settings_2nd = {
|
10
10
|
ca_file: __dir__ + '/../tmp/ca.crt'
|
@@ -33,24 +33,7 @@ settings_1st = {
|
|
33
33
|
socket = TCPSocket.new(hostname, port)
|
34
34
|
client = TTTLS13::Client.new(socket, hostname, settings)
|
35
35
|
client.connect
|
36
|
-
client.write(
|
37
|
-
|
38
|
-
# status line, header
|
39
|
-
buffer = ''
|
40
|
-
buffer += client.read until buffer.include?("\r\n\r\n")
|
41
|
-
print header = buffer.split("\r\n\r\n").first
|
42
|
-
# header; Content-Length
|
43
|
-
cl_line = header.split("\r\n").find { |s| s.match(/Content-Length:/i) }
|
44
|
-
|
45
|
-
# body
|
46
|
-
unless cl_line.nil?
|
47
|
-
cl = cl_line.split(':').last.to_i
|
48
|
-
print buffer = buffer.split("\r\n\r\n")[1..].join
|
49
|
-
while buffer.length < cl
|
50
|
-
print s = client.read
|
51
|
-
buffer += s
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
36
|
+
client.write(req)
|
37
|
+
print recv_http_response(client)
|
55
38
|
client.close
|
56
39
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'helper'
|
5
|
+
|
6
|
+
port = ARGV[0] || 4433
|
7
|
+
|
8
|
+
tcpserver = TCPServer.open(port)
|
9
|
+
settings = { crt_file: __dir__ + '/../tmp/server.crt',
|
10
|
+
key_file: __dir__ + '/../tmp/server.key' }
|
11
|
+
|
12
|
+
# rubocop: disable Metrics/BlockLength
|
13
|
+
loop do
|
14
|
+
socket = tcpserver.accept
|
15
|
+
Thread.start(socket) do |s|
|
16
|
+
Timeout.timeout(5) do
|
17
|
+
server = TTTLS13::Server.new(s, settings)
|
18
|
+
server.accept
|
19
|
+
buffer = ''
|
20
|
+
buffer += server.read until buffer.include?(WEBrick::CRLF * 2)
|
21
|
+
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
|
22
|
+
req.parse(StringIO.new(buffer))
|
23
|
+
puts req.to_s
|
24
|
+
res = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
|
25
|
+
res.status = 200
|
26
|
+
res.body = 'Hello'
|
27
|
+
res.content_length = 5
|
28
|
+
res.content_type = 'text/html'
|
29
|
+
server.write(
|
30
|
+
res.status_line \
|
31
|
+
+ res.header.map { |k, v| k + ': ' + v }.join(WEBrick::CRLF) \
|
32
|
+
+ WEBrick::CRLF * 2 \
|
33
|
+
+ res.body
|
34
|
+
)
|
35
|
+
server.close
|
36
|
+
end
|
37
|
+
rescue Timeout::Error => e
|
38
|
+
puts e.to_s + "\n\n"
|
39
|
+
ensure
|
40
|
+
s.close
|
41
|
+
end
|
42
|
+
end
|
43
|
+
# rubocop: enable Metrics/BlockLength
|
data/interop/client_spec.rb
CHANGED
@@ -3,61 +3,144 @@
|
|
3
3
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
|
-
|
6
|
+
FIXTURES_DIR = __dir__ + '/../spec/fixtures'
|
7
7
|
|
8
8
|
RSpec.describe Client do
|
9
9
|
# testcases
|
10
|
+
# normal [Boolean] Is this nominal scenarios?
|
11
|
+
# opt [String] openssl s_server options
|
12
|
+
# crt [String] server crt file path
|
13
|
+
# key [String] server key file path
|
14
|
+
# settings [Hash] TTTLS13::Server settings
|
10
15
|
[
|
16
|
+
# rubocop: disable Metrics/LineLength
|
11
17
|
[
|
12
|
-
|
18
|
+
true,
|
19
|
+
'-ciphersuites TLS_AES_256_GCM_SHA384',
|
20
|
+
'rsa_rsa.crt',
|
21
|
+
'rsa_rsa.key',
|
13
22
|
cipher_suites: [CipherSuite::TLS_AES_256_GCM_SHA384]
|
14
23
|
],
|
15
24
|
[
|
16
|
-
|
25
|
+
true,
|
26
|
+
'-ciphersuites TLS_CHACHA20_POLY1305_SHA256',
|
27
|
+
'rsa_rsa.crt',
|
28
|
+
'rsa_rsa.key',
|
17
29
|
cipher_suites: [CipherSuite::TLS_CHACHA20_POLY1305_SHA256]
|
18
30
|
],
|
19
31
|
[
|
20
|
-
|
32
|
+
true,
|
33
|
+
'-ciphersuites TLS_AES_128_GCM_SHA256',
|
34
|
+
'rsa_rsa.crt',
|
35
|
+
'rsa_rsa.key',
|
21
36
|
cipher_suites: [CipherSuite::TLS_AES_128_GCM_SHA256]
|
22
37
|
],
|
23
38
|
[
|
24
|
-
|
39
|
+
false,
|
40
|
+
'-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256',
|
41
|
+
'rsa_rsa.crt',
|
42
|
+
'rsa_rsa.key',
|
43
|
+
cipher_suites: [CipherSuite::TLS_AES_128_GCM_SHA256]
|
44
|
+
],
|
45
|
+
[
|
46
|
+
true,
|
47
|
+
'-groups P-256',
|
48
|
+
'rsa_rsa.crt',
|
49
|
+
'rsa_rsa.key',
|
25
50
|
supported_groups: [NamedGroup::SECP256R1]
|
26
51
|
],
|
27
52
|
[
|
28
|
-
|
53
|
+
true,
|
54
|
+
'-groups P-384',
|
55
|
+
'rsa_rsa.crt',
|
56
|
+
'rsa_rsa.key',
|
29
57
|
supported_groups: [NamedGroup::SECP384R1]
|
30
58
|
],
|
31
59
|
[
|
32
|
-
|
60
|
+
true,
|
61
|
+
'-groups P-521',
|
62
|
+
'rsa_rsa.crt',
|
63
|
+
'rsa_rsa.key',
|
33
64
|
supported_groups: [NamedGroup::SECP521R1]
|
34
65
|
],
|
35
66
|
[
|
36
|
-
|
67
|
+
false,
|
68
|
+
'-groups P-256:P-384',
|
69
|
+
'rsa_rsa.crt',
|
70
|
+
'rsa_rsa.key',
|
71
|
+
supported_groups: [NamedGroup::SECP521R1]
|
72
|
+
],
|
73
|
+
[
|
74
|
+
true,
|
75
|
+
'-sigalgs RSA-PSS+SHA256',
|
76
|
+
'rsa_rsa.crt',
|
77
|
+
'rsa_rsa.key',
|
37
78
|
signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
|
38
79
|
signature_algorithms: [SignatureScheme::RSA_PSS_RSAE_SHA256]
|
39
80
|
],
|
40
81
|
[
|
41
|
-
|
82
|
+
true,
|
83
|
+
'-sigalgs RSA-PSS+SHA384',
|
84
|
+
'rsa_rsa.crt',
|
85
|
+
'rsa_rsa.key',
|
42
86
|
signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
|
43
87
|
signature_algorithms: [SignatureScheme::RSA_PSS_RSAE_SHA384]
|
44
88
|
],
|
45
89
|
[
|
46
|
-
|
90
|
+
true,
|
91
|
+
'-sigalgs RSA-PSS+SHA512',
|
92
|
+
'rsa_rsa.crt',
|
93
|
+
'rsa_rsa.key',
|
47
94
|
signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
|
48
95
|
signature_algorithms: [SignatureScheme::RSA_PSS_RSAE_SHA512]
|
49
96
|
],
|
50
97
|
[
|
51
|
-
|
98
|
+
true,
|
99
|
+
'-sigalgs ECDSA+SHA256',
|
100
|
+
'rsa_secp256r1.crt',
|
101
|
+
'rsa_secp256r1.key',
|
102
|
+
signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
|
103
|
+
signature_algorithms: [SignatureScheme::ECDSA_SECP256R1_SHA256]
|
104
|
+
],
|
105
|
+
[
|
106
|
+
true,
|
107
|
+
'-sigalgs ECDSA+SHA384',
|
108
|
+
'rsa_secp384r1.crt',
|
109
|
+
'rsa_secp384r1.key',
|
110
|
+
signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
|
111
|
+
signature_algorithms: [SignatureScheme::ECDSA_SECP384R1_SHA384]
|
112
|
+
],
|
113
|
+
[
|
114
|
+
true,
|
115
|
+
'-sigalgs ECDSA+SHA512',
|
116
|
+
'rsa_secp521r1.crt',
|
117
|
+
'rsa_secp521r1.key',
|
118
|
+
signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
|
119
|
+
signature_algorithms: [SignatureScheme::ECDSA_SECP521R1_SHA512]
|
120
|
+
],
|
121
|
+
[
|
122
|
+
false,
|
123
|
+
'-sigalgs ECDSA+SHA256:ECDSA+SHA384:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256',
|
124
|
+
'rsa_secp521r1.crt',
|
125
|
+
'rsa_secp521r1.key',
|
126
|
+
signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
|
127
|
+
signature_algorithms: [SignatureScheme::ECDSA_SECP521R1_SHA512]
|
128
|
+
],
|
129
|
+
[
|
130
|
+
true,
|
131
|
+
'-record_padding 8446',
|
132
|
+
'rsa_rsa.crt',
|
133
|
+
'rsa_rsa.key',
|
52
134
|
{}
|
53
135
|
]
|
54
|
-
|
136
|
+
# rubocop: enable Metrics/LineLength
|
137
|
+
].each do |normal, opt, crt, key, settings|
|
55
138
|
context 'client interop' do
|
56
139
|
before do
|
57
|
-
cmd = "docker run -v #{
|
140
|
+
cmd = "docker run -v #{FIXTURES_DIR}:/tmp -p 4433:4433 -it openssl " \
|
58
141
|
+ 'openssl s_server ' \
|
59
|
-
+
|
60
|
-
+
|
142
|
+
+ "-cert /tmp/#{crt} " \
|
143
|
+
+ "-key /tmp/#{key} " \
|
61
144
|
+ '-tls1_3 ' \
|
62
145
|
+ '-www ' \
|
63
146
|
+ '-quiet ' \
|
@@ -65,13 +148,13 @@ RSpec.describe Client do
|
|
65
148
|
pid = spawn(cmd)
|
66
149
|
Process.detach(pid)
|
67
150
|
|
68
|
-
sleep(2) # waiting for openssl s_server
|
151
|
+
sleep(2.5) # waiting for openssl s_server
|
69
152
|
end
|
70
153
|
|
71
154
|
let(:client) do
|
72
155
|
hostname = 'localhost'
|
73
156
|
@socket = TCPSocket.new(hostname, 4433)
|
74
|
-
settings[:ca_file] =
|
157
|
+
settings[:ca_file] = FIXTURES_DIR + '/rsa_ca.crt'
|
75
158
|
Client.new(@socket, hostname, settings)
|
76
159
|
end
|
77
160
|
|
@@ -80,11 +163,17 @@ RSpec.describe Client do
|
|
80
163
|
`docker ps -ql | xargs docker stop`
|
81
164
|
end
|
82
165
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
166
|
+
if normal
|
167
|
+
it "should connect with openssl s_server ...#{opt}" do
|
168
|
+
expect { client.connect }.to_not raise_error
|
169
|
+
expect { client.write("GET / HTTP/1.0\r\n\r\n") }.to_not raise_error
|
170
|
+
expect(client.read).to include "HTTP/1.0 200 ok\r\n"
|
171
|
+
expect { client.close }.to_not raise_error
|
172
|
+
end
|
173
|
+
else # exceptions scenarios
|
174
|
+
it "should NOT connect with openssl s_server ...#{opt}" do
|
175
|
+
expect { client.connect }.to raise_error ErrorAlerts
|
176
|
+
end
|
88
177
|
end
|
89
178
|
end
|
90
179
|
end
|