tttls1.3 0.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 +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.rubocop.yml +16 -0
- data/.travis.yml +8 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +21 -0
- data/README.md +52 -0
- data/Rakefile +133 -0
- data/example/helper.rb +17 -0
- data/example/https_client.rb +32 -0
- data/example/https_client_using_0rtt.rb +64 -0
- data/example/https_client_using_hrr.rb +35 -0
- data/example/https_client_using_ticket.rb +56 -0
- data/lib/tttls1.3/cipher_suites.rb +102 -0
- data/lib/tttls1.3/client.rb +745 -0
- data/lib/tttls1.3/connection.rb +380 -0
- data/lib/tttls1.3/cryptograph/aead.rb +118 -0
- data/lib/tttls1.3/cryptograph/passer.rb +22 -0
- data/lib/tttls1.3/cryptograph.rb +3 -0
- data/lib/tttls1.3/error.rb +22 -0
- data/lib/tttls1.3/key_schedule.rb +242 -0
- data/lib/tttls1.3/message/alert.rb +86 -0
- data/lib/tttls1.3/message/application_data.rb +27 -0
- data/lib/tttls1.3/message/certificate.rb +121 -0
- data/lib/tttls1.3/message/certificate_verify.rb +59 -0
- data/lib/tttls1.3/message/change_cipher_spec.rb +26 -0
- data/lib/tttls1.3/message/client_hello.rb +100 -0
- data/lib/tttls1.3/message/encrypted_extensions.rb +65 -0
- data/lib/tttls1.3/message/end_of_early_data.rb +29 -0
- data/lib/tttls1.3/message/extension/alpn.rb +70 -0
- data/lib/tttls1.3/message/extension/cookie.rb +47 -0
- data/lib/tttls1.3/message/extension/early_data_indication.rb +58 -0
- data/lib/tttls1.3/message/extension/key_share.rb +236 -0
- data/lib/tttls1.3/message/extension/pre_shared_key.rb +205 -0
- data/lib/tttls1.3/message/extension/psk_key_exchange_modes.rb +54 -0
- data/lib/tttls1.3/message/extension/record_size_limit.rb +46 -0
- data/lib/tttls1.3/message/extension/server_name.rb +91 -0
- data/lib/tttls1.3/message/extension/signature_algorithms.rb +69 -0
- data/lib/tttls1.3/message/extension/signature_algorithms_cert.rb +25 -0
- data/lib/tttls1.3/message/extension/status_request.rb +106 -0
- data/lib/tttls1.3/message/extension/supported_groups.rb +145 -0
- data/lib/tttls1.3/message/extension/supported_versions.rb +98 -0
- data/lib/tttls1.3/message/extension/unknown_extension.rb +38 -0
- data/lib/tttls1.3/message/extensions.rb +173 -0
- data/lib/tttls1.3/message/finished.rb +44 -0
- data/lib/tttls1.3/message/new_session_ticket.rb +89 -0
- data/lib/tttls1.3/message/record.rb +232 -0
- data/lib/tttls1.3/message/server_hello.rb +116 -0
- data/lib/tttls1.3/message.rb +48 -0
- data/lib/tttls1.3/sequence_number.rb +31 -0
- data/lib/tttls1.3/signature_scheme.rb +31 -0
- data/lib/tttls1.3/transcript.rb +69 -0
- data/lib/tttls1.3/utils.rb +91 -0
- data/lib/tttls1.3/version.rb +5 -0
- data/lib/tttls1.3.rb +16 -0
- data/spec/aead_spec.rb +95 -0
- data/spec/alert_spec.rb +54 -0
- data/spec/alpn_spec.rb +55 -0
- data/spec/application_data_spec.rb +26 -0
- data/spec/certificate_spec.rb +55 -0
- data/spec/certificate_verify_spec.rb +51 -0
- data/spec/change_cipher_spec_spec.rb +26 -0
- data/spec/cipher_suites_spec.rb +39 -0
- data/spec/client_hello_spec.rb +83 -0
- data/spec/client_spec.rb +319 -0
- data/spec/connection_spec.rb +114 -0
- data/spec/cookie_spec.rb +98 -0
- data/spec/early_data_indication_spec.rb +64 -0
- data/spec/encrypted_extensions_spec.rb +94 -0
- data/spec/error_spec.rb +18 -0
- data/spec/extensions_spec.rb +170 -0
- data/spec/finished_spec.rb +55 -0
- data/spec/key_schedule_spec.rb +198 -0
- data/spec/key_share_spec.rb +199 -0
- data/spec/new_session_ticket_spec.rb +80 -0
- data/spec/pre_shared_key_spec.rb +167 -0
- data/spec/psk_key_exchange_modes_spec.rb +45 -0
- data/spec/record_size_limit_spec.rb +61 -0
- data/spec/record_spec.rb +105 -0
- data/spec/server_hello_spec.rb +101 -0
- data/spec/server_name_spec.rb +110 -0
- data/spec/signature_algorithms_cert_spec.rb +73 -0
- data/spec/signature_algorithms_spec.rb +100 -0
- data/spec/spec_helper.rb +872 -0
- data/spec/status_request_spec.rb +73 -0
- data/spec/supported_groups_spec.rb +79 -0
- data/spec/supported_versions_spec.rb +136 -0
- data/spec/transcript_spec.rb +69 -0
- data/spec/unknown_extension_spec.rb +90 -0
- data/spec/utils_spec.rb +215 -0
- data/tttls1.3.gemspec +25 -0
- metadata +197 -0
data/spec/aead_spec.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
RSpec.describe Aead do
|
7
|
+
context 'aead using CipherSuite::TLS_AES_128_GCM_SHA256' do
|
8
|
+
let(:cipher) do
|
9
|
+
Aead.new(cipher_suite: CipherSuite::TLS_AES_128_GCM_SHA256,
|
10
|
+
write_key: TESTBINARY_SERVER_PARAMETERS_WRITE_KEY,
|
11
|
+
write_iv: TESTBINARY_SERVER_PARAMETERS_WRITE_IV,
|
12
|
+
sequence_number: SequenceNumber.new)
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:content) do
|
16
|
+
TESTBINARY_SERVER_PARAMETERS
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:encrypted_record) do
|
20
|
+
TESTBINARY_SERVER_PARAMETERS_RECORD[5..]
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:record_header) do
|
24
|
+
TESTBINARY_SERVER_PARAMETERS_RECORD[0...5]
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should encrypt content of server parameters' do
|
28
|
+
expect(cipher.encrypt(content, ContentType::HANDSHAKE))
|
29
|
+
.to eq encrypted_record
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should decrypt encrypted_record server parameters' do
|
33
|
+
expect(cipher.decrypt(encrypted_record, record_header))
|
34
|
+
.to eq [content, ContentType::HANDSHAKE]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'aead using CipherSuite::TLS_AES_128_GCM_SHA256' do
|
39
|
+
let(:cipher) do
|
40
|
+
Aead.new(cipher_suite: CipherSuite::TLS_AES_128_GCM_SHA256,
|
41
|
+
write_key: TESTBINARY_CLIENT_FINISHED_WRITE_KEY,
|
42
|
+
write_iv: TESTBINARY_CLIENT_FINISHED_WRITE_IV,
|
43
|
+
sequence_number: SequenceNumber.new)
|
44
|
+
end
|
45
|
+
|
46
|
+
let(:content) do
|
47
|
+
TESTBINARY_CLIENT_FINISHED
|
48
|
+
end
|
49
|
+
|
50
|
+
let(:encrypted_record) do
|
51
|
+
TESTBINARY_CLIENT_FINISHED_RECORD[5..]
|
52
|
+
end
|
53
|
+
|
54
|
+
let(:record_header) do
|
55
|
+
TESTBINARY_CLIENT_FINISHED_RECORD[0...5]
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should encrypt content of client finished' do
|
59
|
+
expect(cipher.encrypt(content, ContentType::HANDSHAKE))
|
60
|
+
.to eq encrypted_record
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should decrypt encrypted_record client finished' do
|
64
|
+
expect(cipher.decrypt(encrypted_record, record_header))
|
65
|
+
.to eq [content, ContentType::HANDSHAKE]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'aead using CipherSuite::TLS_AES_128_GCM_SHA256, ' \
|
70
|
+
'HelloRetryRequest,' do
|
71
|
+
let(:cipher) do
|
72
|
+
Aead.new(cipher_suite: CipherSuite::TLS_AES_128_GCM_SHA256,
|
73
|
+
write_key: TESTBINARY_HRR_SERVER_PARAMETERS_WRITE_KEY,
|
74
|
+
write_iv: TESTBINARY_HRR_SERVER_PARAMETERS_WRITE_IV,
|
75
|
+
sequence_number: SequenceNumber.new)
|
76
|
+
end
|
77
|
+
|
78
|
+
let(:content) do
|
79
|
+
TESTBINARY_HRR_SERVER_PARAMETERS
|
80
|
+
end
|
81
|
+
|
82
|
+
let(:encrypted_record) do
|
83
|
+
TESTBINARY_HRR_SERVER_PARAMETERS_RECORD[5..]
|
84
|
+
end
|
85
|
+
|
86
|
+
let(:record_header) do
|
87
|
+
TESTBINARY_HRR_SERVER_PARAMETERS_RECORD[0...5]
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should decrypt encrypted_record server parameters' do
|
91
|
+
expect(cipher.decrypt(encrypted_record, record_header))
|
92
|
+
.to eq [content, ContentType::HANDSHAKE]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/spec/alert_spec.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
RSpec.describe Alert do
|
7
|
+
context 'unexpected_message alert' do
|
8
|
+
let(:message) do
|
9
|
+
Alert.new(level: AlertLevel::FATAL,
|
10
|
+
description: ALERT_DESCRIPTION[:unexpected_message])
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should be serialized' do
|
14
|
+
expect(message.serialize).to eq AlertLevel::FATAL \
|
15
|
+
+ ALERT_DESCRIPTION[:unexpected_message]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should return error' do
|
19
|
+
expect(message.to_error).to be_a_kind_of(ErrorAlerts)
|
20
|
+
expect(message.to_error.message).to eq 'unexpected_message'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'unexpected_message alert, not given level' do
|
25
|
+
let(:message) do
|
26
|
+
Alert.new(description: ALERT_DESCRIPTION[:unexpected_message])
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should be serialized' do
|
30
|
+
expect(message.serialize).to eq AlertLevel::FATAL \
|
31
|
+
+ ALERT_DESCRIPTION[:unexpected_message]
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should return error' do
|
35
|
+
expect(message.to_error).to be_a_kind_of(ErrorAlerts)
|
36
|
+
expect(message.to_error.message).to eq 'unexpected_message'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'valid alert binary' do
|
41
|
+
let(:message) do
|
42
|
+
Alert.deserialize(TESTBINARY_ALERT)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should generate object' do
|
46
|
+
expect(message.level).to eq AlertLevel::WARNING
|
47
|
+
expect(message.description).to eq ALERT_DESCRIPTION[:close_notify]
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should generate serializable object' do
|
51
|
+
expect(message.serialize).to eq TESTBINARY_ALERT
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/spec/alpn_spec.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
using Refinements
|
6
|
+
|
7
|
+
RSpec.describe Alpn do
|
8
|
+
context 'valid alpn' do
|
9
|
+
let(:protocol_name_list) do
|
10
|
+
['h2', 'http/1.1', 'http/1.0']
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:extension) do
|
14
|
+
Alpn.new(protocol_name_list)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should be generated' do
|
18
|
+
expect(extension.extension_type)
|
19
|
+
.to eq ExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION
|
20
|
+
expect(extension.protocol_name_list).to eq protocol_name_list
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should be serialized' do
|
24
|
+
expect(extension.serialize)
|
25
|
+
.to eq ExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION \
|
26
|
+
+ 23.to_uint16 \
|
27
|
+
+ 21.to_uint16 \
|
28
|
+
+ 'h2'.prefix_uint8_length \
|
29
|
+
+ 'http/1.1'.prefix_uint8_length \
|
30
|
+
+ 'http/1.0'.prefix_uint8_length
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'invalid alpn, empty,' do
|
35
|
+
let(:extension) do
|
36
|
+
Alpn.new([])
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should not be generated' do
|
40
|
+
expect { extension }.to raise_error(ErrorAlerts)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'valid alpn binary' do
|
45
|
+
let(:extension) do
|
46
|
+
Alpn.deserialize(TESTBINARY_ALPN)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should generate valid object' do
|
50
|
+
expect(extension.extension_type)
|
51
|
+
.to eq ExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION
|
52
|
+
expect(extension.protocol_name_list).to eq ['h2', 'http/1.1']
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
RSpec.describe ApplicationData do
|
7
|
+
context 'application_data' do
|
8
|
+
let(:message) do
|
9
|
+
ApplicationData.new(TESTBINARY_CLIENT_APPLICATION_DATA)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should be serialized' do
|
13
|
+
expect(message.serialize).to eq TESTBINARY_CLIENT_APPLICATION_DATA
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'valid application_data binary' do
|
18
|
+
let(:message) do
|
19
|
+
ApplicationData.deserialize(TESTBINARY_CLIENT_APPLICATION_DATA)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should generate valid serializable object' do
|
23
|
+
expect(message.serialize).to eq TESTBINARY_CLIENT_APPLICATION_DATA
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
using Refinements
|
6
|
+
|
7
|
+
RSpec.describe Certificate do
|
8
|
+
context 'valid certificate' do
|
9
|
+
let(:certificate) do
|
10
|
+
OpenSSL::X509::Certificate.new(File.read(__dir__ + '/../tmp/server.crt'))
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:message) do
|
14
|
+
Certificate.new(certificate_list: [CertificateEntry.new(certificate)])
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should be generated' do
|
18
|
+
expect(message.msg_type).to eq HandshakeType::CERTIFICATE
|
19
|
+
expect(message.certificate_request_context).to be_empty
|
20
|
+
|
21
|
+
certificate_entry = message.certificate_list.first
|
22
|
+
expect(certificate_entry.cert_data.subject.to_s).to eq '/CN=localhost'
|
23
|
+
expect(certificate_entry.extensions).to be_empty
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should be serialized' do
|
27
|
+
expect(message.serialize).to eq HandshakeType::CERTIFICATE \
|
28
|
+
+ 990.to_uint24 \
|
29
|
+
+ 0.to_uint8 \
|
30
|
+
+ 986.to_uint24 \
|
31
|
+
+ 981.to_uint24 \
|
32
|
+
+ certificate.to_der \
|
33
|
+
+ 0.to_uint16
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'valid certificate binary' do
|
38
|
+
let(:message) do
|
39
|
+
Certificate.deserialize(TESTBINARY_CERTIFICATE)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should generate valid object' do
|
43
|
+
expect(message.msg_type).to eq HandshakeType::CERTIFICATE
|
44
|
+
expect(message.certificate_request_context).to be_empty
|
45
|
+
|
46
|
+
certificate_entry = message.certificate_list.first
|
47
|
+
expect(certificate_entry.cert_data.subject.to_s).to eq '/CN=rsa'
|
48
|
+
expect(certificate_entry.extensions).to be_empty
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should generate serializable object' do
|
52
|
+
expect(message.serialize).to eq TESTBINARY_CERTIFICATE
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
using Refinements
|
6
|
+
|
7
|
+
RSpec.describe CertificateVerify do
|
8
|
+
context 'valid certificate_verify' do
|
9
|
+
let(:signature) do
|
10
|
+
OpenSSL::Random.random_bytes(128)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:message) do
|
14
|
+
CertificateVerify.new(
|
15
|
+
signature_scheme: SignatureScheme::RSA_PSS_RSAE_SHA256,
|
16
|
+
signature: signature
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should be generated' do
|
21
|
+
expect(message.msg_type).to eq HandshakeType::CERTIFICATE_VERIFY
|
22
|
+
expect(message.signature_scheme) \
|
23
|
+
.to eq SignatureScheme::RSA_PSS_RSAE_SHA256
|
24
|
+
expect(message.signature).to eq signature
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should be serialized' do
|
28
|
+
expect(message.serialize).to eq HandshakeType::CERTIFICATE_VERIFY \
|
29
|
+
+ 132.to_uint24 \
|
30
|
+
+ SignatureScheme::RSA_PSS_RSAE_SHA256 \
|
31
|
+
+ signature.prefix_uint16_length
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'valid certificate_verify binary' do
|
36
|
+
let(:message) do
|
37
|
+
CertificateVerify.deserialize(TESTBINARY_CERTIFICATE_VERIFY)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should generate valid object' do
|
41
|
+
expect(message.msg_type).to eq HandshakeType::CERTIFICATE_VERIFY
|
42
|
+
expect(message.signature_scheme) \
|
43
|
+
.to eq SignatureScheme::RSA_PSS_RSAE_SHA256
|
44
|
+
expect(message.signature.length).to eq 128
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should generate serializable object' do
|
48
|
+
expect(message.serialize).to eq TESTBINARY_CERTIFICATE_VERIFY
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
RSpec.describe ChangeCipherSpec do
|
7
|
+
context 'change_cipher_spec' do
|
8
|
+
let(:message) do
|
9
|
+
ChangeCipherSpec.new
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should be serialized' do
|
13
|
+
expect(message.serialize).to eq "\x01"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'valid change_cipher_spec binary' do
|
18
|
+
let(:message) do
|
19
|
+
ChangeCipherSpec.deserialize(TESTBINARY_CHANGE_CIPHER_SPEC)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should generate valid serializable object' do
|
23
|
+
expect(message.serialize).to eq "\x01"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
using Refinements
|
6
|
+
|
7
|
+
RSpec.describe CipherSuites do
|
8
|
+
context 'valid cipher suites binary' do
|
9
|
+
let(:cs) do
|
10
|
+
CipherSuites.deserialize(TESTBINARY_CIPHER_SUITES)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should generate valid object' do
|
14
|
+
expect(cs).to eq [CipherSuite::TLS_AES_256_GCM_SHA384,
|
15
|
+
CipherSuite::TLS_CHACHA20_POLY1305_SHA256,
|
16
|
+
CipherSuite::TLS_AES_128_GCM_SHA256]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'invalid cipher suites binary, too short' do
|
21
|
+
let(:cs) do
|
22
|
+
CipherSuites.deserialize(TESTBINARY_CIPHER_SUITES[0...-1])
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should not generate object' do
|
26
|
+
expect { cs }.to raise_error(ErrorAlerts)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'invalid cipher suites binary, binary is nil' do
|
31
|
+
let(:cs) do
|
32
|
+
CipherSuites.deserialize(nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should not generate object' do
|
36
|
+
expect { cs }.to raise_error(ErrorAlerts)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
using Refinements
|
6
|
+
|
7
|
+
RSpec.describe ClientHello do
|
8
|
+
context 'default client_hello' do
|
9
|
+
let(:random) do
|
10
|
+
OpenSSL::Random.random_bytes(32)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:legacy_session_id) do
|
14
|
+
Array.new(32, 0).map(&:chr).join
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:cipher_suites) do
|
18
|
+
CipherSuites.new([TLS_AES_256_GCM_SHA384,
|
19
|
+
TLS_CHACHA20_POLY1305_SHA256,
|
20
|
+
TLS_AES_128_GCM_SHA256])
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:message) do
|
24
|
+
ClientHello.new(random: random,
|
25
|
+
legacy_session_id: legacy_session_id,
|
26
|
+
cipher_suites: cipher_suites)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should be generated' do
|
30
|
+
expect(message.msg_type).to eq HandshakeType::CLIENT_HELLO
|
31
|
+
expect(message.legacy_version).to eq ProtocolVersion::TLS_1_2
|
32
|
+
expect(message.random).to eq random
|
33
|
+
expect(message.legacy_session_id).to eq legacy_session_id
|
34
|
+
expect(message.cipher_suites).to eq [TLS_AES_256_GCM_SHA384,
|
35
|
+
TLS_CHACHA20_POLY1305_SHA256,
|
36
|
+
TLS_AES_128_GCM_SHA256]
|
37
|
+
expect(message.legacy_compression_methods).to eq ["\x00"]
|
38
|
+
expect(message.extensions).to be_empty
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should be serialized' do
|
42
|
+
expect(message.serialize).to eq HandshakeType::CLIENT_HELLO \
|
43
|
+
+ 79.to_uint24 \
|
44
|
+
+ ProtocolVersion::TLS_1_2 \
|
45
|
+
+ random \
|
46
|
+
+ legacy_session_id.length.to_uint8 \
|
47
|
+
+ legacy_session_id \
|
48
|
+
+ cipher_suites.serialize \
|
49
|
+
+ "\x01\x00" \
|
50
|
+
+ Extensions.new.serialize
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'valid client_hello binary' do
|
55
|
+
let(:message) do
|
56
|
+
ClientHello.deserialize(TESTBINARY_CLIENT_HELLO)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should generate valid object' do
|
60
|
+
expect(message.msg_type).to eq HandshakeType::CLIENT_HELLO
|
61
|
+
expect(message.legacy_version).to eq ProtocolVersion::TLS_1_2
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should generate valid serializable object' do
|
65
|
+
expect(message.serialize).to eq TESTBINARY_CLIENT_HELLO
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'valid client_hello binary, 0-RTT,' do
|
70
|
+
let(:message) do
|
71
|
+
ClientHello.deserialize(TESTBINARY_0_RTT_CLIENT_HELLO)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should generate valid object' do
|
75
|
+
expect(message.msg_type).to eq HandshakeType::CLIENT_HELLO
|
76
|
+
expect(message.legacy_version).to eq ProtocolVersion::TLS_1_2
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should generate valid serializable object' do
|
80
|
+
expect(message.serialize).to eq TESTBINARY_0_RTT_CLIENT_HELLO
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|