tttls1.3 0.1.4 → 0.2.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 +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
|