tttls1.3 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|