tttls1.3 0.2.12 → 0.2.16
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/.github/workflows/ci.yml +32 -0
- data/.rubocop.yml +2 -2
- data/Gemfile +3 -4
- data/README.md +4 -1
- data/example/helper.rb +3 -3
- data/example/https_client.rb +1 -1
- data/example/https_client_using_0rtt.rb +2 -2
- data/example/https_client_using_hrr.rb +1 -1
- data/example/https_client_using_hrr_and_ticket.rb +2 -2
- data/example/https_client_using_status_request.rb +2 -2
- data/example/https_client_using_ticket.rb +2 -2
- data/example/https_server.rb +2 -2
- data/interop/client_spec.rb +6 -6
- data/interop/server_spec.rb +6 -6
- data/lib/tttls1.3/client.rb +106 -65
- data/lib/tttls1.3/connection.rb +43 -30
- data/lib/tttls1.3/cryptograph/aead.rb +20 -7
- data/lib/tttls1.3/cryptograph.rb +1 -1
- data/lib/tttls1.3/message/alert.rb +2 -2
- data/lib/tttls1.3/message/client_hello.rb +1 -0
- data/lib/tttls1.3/message/compressed_certificate.rb +82 -0
- data/lib/tttls1.3/message/extension/alpn.rb +5 -2
- data/lib/tttls1.3/message/extension/compress_certificate.rb +58 -0
- data/lib/tttls1.3/message/extension/signature_algorithms.rb +15 -5
- data/lib/tttls1.3/message/extension/signature_algorithms_cert.rb +5 -4
- data/lib/tttls1.3/message/extension/supported_groups.rb +2 -2
- data/lib/tttls1.3/message/extensions.rb +31 -18
- data/lib/tttls1.3/message/record.rb +28 -16
- data/lib/tttls1.3/message.rb +23 -21
- data/lib/tttls1.3/server.rb +88 -37
- data/lib/tttls1.3/transcript.rb +3 -7
- data/lib/tttls1.3/version.rb +1 -1
- data/spec/client_spec.rb +28 -19
- data/spec/compress_certificate_spec.rb +54 -0
- data/spec/connection_spec.rb +22 -15
- data/spec/extensions_spec.rb +16 -0
- data/spec/fixtures/rsa_rsa.crt +15 -15
- data/spec/fixtures/rsa_rsa.key +25 -25
- data/spec/key_schedule_spec.rb +48 -25
- data/spec/record_spec.rb +2 -2
- data/spec/server_hello_spec.rb +1 -1
- data/spec/server_spec.rb +23 -11
- data/spec/signature_algorithms_cert_spec.rb +4 -0
- data/spec/signature_algorithms_spec.rb +4 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/transcript_spec.rb +34 -20
- data/tttls1.3.gemspec +0 -1
- metadata +11 -7
- data/.github/workflows/main.yml +0 -25
data/lib/tttls1.3/server.rb
CHANGED
@@ -44,6 +44,11 @@ module TTTLS13
|
|
44
44
|
].freeze
|
45
45
|
private_constant :DEFAULT_SP_NAMED_GROUP_LIST
|
46
46
|
|
47
|
+
DEFAULT_SP_COMPRESS_CERTIFICATE_ALGORITHMS = [
|
48
|
+
Message::Extension::CertificateCompressionAlgorithm::ZLIB
|
49
|
+
].freeze
|
50
|
+
private_constant :DEFAULT_SP_COMPRESS_CERTIFICATE_ALGORITHMS
|
51
|
+
|
47
52
|
DEFAULT_SERVER_SETTINGS = {
|
48
53
|
crt_file: nil,
|
49
54
|
chain_files: nil,
|
@@ -52,6 +57,8 @@ module TTTLS13
|
|
52
57
|
signature_algorithms: DEFAULT_SP_SIGNATURE_ALGORITHMS,
|
53
58
|
supported_groups: DEFAULT_SP_NAMED_GROUP_LIST,
|
54
59
|
alpn: nil,
|
60
|
+
process_ocsp_response: nil,
|
61
|
+
compress_certificate_algorithms: DEFAULT_SP_COMPRESS_CERTIFICATE_ALGORITHMS,
|
55
62
|
compatibility_mode: true,
|
56
63
|
loglevel: Logger::WARN
|
57
64
|
}.freeze
|
@@ -139,7 +146,6 @@ module TTTLS13
|
|
139
146
|
transcript = Transcript.new
|
140
147
|
key_schedule = nil # TTTLS13::KeySchedule
|
141
148
|
priv_key = nil # OpenSSL::PKey::$Object
|
142
|
-
|
143
149
|
hs_wcipher = nil # TTTLS13::Cryptograph::$Object
|
144
150
|
hs_rcipher = nil # TTTLS13::Cryptograph::$Object
|
145
151
|
|
@@ -150,7 +156,7 @@ module TTTLS13
|
|
150
156
|
logger.debug('ServerState::START')
|
151
157
|
|
152
158
|
receivable_ccs = transcript.include?(CH1)
|
153
|
-
ch = transcript[CH] = recv_client_hello(receivable_ccs)
|
159
|
+
ch, = transcript[CH] = recv_client_hello(receivable_ccs)
|
154
160
|
|
155
161
|
# support only TLS 1.3
|
156
162
|
terminate(:protocol_version) unless ch.negotiated_tls_1_3?
|
@@ -182,7 +188,7 @@ module TTTLS13
|
|
182
188
|
logger.debug('ServerState::RECVD_CH')
|
183
189
|
|
184
190
|
# select parameters
|
185
|
-
ch = transcript[CH]
|
191
|
+
ch, = transcript[CH]
|
186
192
|
@cipher_suite = select_cipher_suite(ch)
|
187
193
|
@named_group = select_named_group(ch)
|
188
194
|
@signature_scheme = select_signature_scheme(ch, @crt)
|
@@ -191,8 +197,9 @@ module TTTLS13
|
|
191
197
|
|
192
198
|
# send HRR
|
193
199
|
if @named_group.nil?
|
194
|
-
ch1 = transcript[CH1] = transcript.delete(CH)
|
195
|
-
|
200
|
+
ch1, = transcript[CH1] = transcript.delete(CH)
|
201
|
+
hrr = send_hello_retry_request(ch1, @cipher_suite)
|
202
|
+
transcript[HRR] = [hrr, hrr.serialize]
|
196
203
|
@state = ServerState::START
|
197
204
|
next
|
198
205
|
end
|
@@ -200,10 +207,14 @@ module TTTLS13
|
|
200
207
|
when ServerState::NEGOTIATED
|
201
208
|
logger.debug('ServerState::NEGOTIATED')
|
202
209
|
|
203
|
-
ch = transcript[CH]
|
210
|
+
ch, = transcript[CH]
|
204
211
|
extensions, priv_key = gen_sh_extensions(@named_group)
|
205
|
-
|
206
|
-
|
212
|
+
sh = send_server_hello(
|
213
|
+
extensions,
|
214
|
+
@cipher_suite,
|
215
|
+
ch.legacy_session_id
|
216
|
+
)
|
217
|
+
transcript[SH] = [sh, sh.serialize]
|
207
218
|
send_ccs if @settings[:compatibility_mode]
|
208
219
|
|
209
220
|
# generate shared secret
|
@@ -234,25 +245,30 @@ module TTTLS13
|
|
234
245
|
when ServerState::WAIT_FLIGHT2
|
235
246
|
logger.debug('ServerState::WAIT_FLIGHT2')
|
236
247
|
|
237
|
-
ch = transcript[CH]
|
248
|
+
ch, = transcript[CH]
|
238
249
|
rsl = @send_record_size \
|
239
|
-
|
240
|
-
ee =
|
250
|
+
if ch.extensions.include?(Message::ExtensionType::RECORD_SIZE_LIMIT)
|
251
|
+
ee = gen_encrypted_extensions(ch, @alpn, rsl)
|
252
|
+
transcript[EE] = [ee, ee.serialize]
|
241
253
|
# TODO: [Send CertificateRequest]
|
242
|
-
|
254
|
+
|
255
|
+
# status_request
|
256
|
+
ocsp_response = fetch_ocsp_response \
|
257
|
+
if ch.extensions.include?(Message::ExtensionType::STATUS_REQUEST)
|
258
|
+
ct = gen_certificate(@crt, ch, @chain, ocsp_response)
|
259
|
+
transcript[CT] = [ct, ct.serialize]
|
243
260
|
digest = CipherSuite.digest(@cipher_suite)
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
transcript.hash(digest, CT)
|
248
|
-
)
|
261
|
+
hash = transcript.hash(digest, CT)
|
262
|
+
cv = gen_certificate_verify(@key, @signature_scheme, hash)
|
263
|
+
transcript[CV] = [cv, cv.serialize]
|
249
264
|
finished_key = key_schedule.server_finished_key
|
250
265
|
signature = sign_finished(
|
251
266
|
digest: digest,
|
252
267
|
finished_key: finished_key,
|
253
268
|
hash: transcript.hash(digest, CV)
|
254
269
|
)
|
255
|
-
sf =
|
270
|
+
sf = Message::Finished.new(signature)
|
271
|
+
transcript[SF] = [sf, sf.serialize]
|
256
272
|
send_server_parameters([ee, ct, cv, sf], hs_wcipher)
|
257
273
|
@state = ServerState::WAIT_FINISHED
|
258
274
|
when ServerState::WAIT_CERT
|
@@ -262,7 +278,7 @@ module TTTLS13
|
|
262
278
|
when ServerState::WAIT_FINISHED
|
263
279
|
logger.debug('ServerState::WAIT_FINISHED')
|
264
280
|
|
265
|
-
cf = transcript[CF] = recv_finished(hs_rcipher)
|
281
|
+
cf, = transcript[CF] = recv_finished(hs_rcipher)
|
266
282
|
digest = CipherSuite.digest(@cipher_suite)
|
267
283
|
verified = verified_finished?(
|
268
284
|
finished: cf,
|
@@ -320,12 +336,15 @@ module TTTLS13
|
|
320
336
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
321
337
|
#
|
322
338
|
# @return [TTTLS13::Message::ClientHello]
|
339
|
+
# @return [String]
|
323
340
|
def recv_client_hello(receivable_ccs)
|
324
|
-
ch = recv_message(
|
325
|
-
|
341
|
+
ch, orig_msg = recv_message(
|
342
|
+
receivable_ccs: receivable_ccs,
|
343
|
+
cipher: Cryptograph::Passer.new
|
344
|
+
)
|
326
345
|
terminate(:unexpected_message) unless ch.is_a?(Message::ClientHello)
|
327
346
|
|
328
|
-
ch
|
347
|
+
[ch, orig_msg]
|
329
348
|
end
|
330
349
|
|
331
350
|
# @param extensions [TTTLS13::Message::Extensions]
|
@@ -350,7 +369,7 @@ module TTTLS13
|
|
350
369
|
#
|
351
370
|
# @return [TTTLS13::Message::ServerHello]
|
352
371
|
def send_hello_retry_request(ch1, cipher_suite)
|
353
|
-
exs =
|
372
|
+
exs = Message::Extensions.new
|
354
373
|
# supported_versions
|
355
374
|
exs << Message::Extension::SupportedVersions.new(
|
356
375
|
msg_type: Message::HandshakeType::SERVER_HELLO
|
@@ -372,7 +391,7 @@ module TTTLS13
|
|
372
391
|
random: Message::HRR_RANDOM,
|
373
392
|
legacy_session_id_echo: ch1.legacy_session_id,
|
374
393
|
cipher_suite: cipher_suite,
|
375
|
-
extensions:
|
394
|
+
extensions: exs
|
376
395
|
)
|
377
396
|
send_handshakes(Message::ContentType::HANDSHAKE, [sh],
|
378
397
|
Cryptograph::Passer.new)
|
@@ -403,14 +422,39 @@ module TTTLS13
|
|
403
422
|
end
|
404
423
|
|
405
424
|
# @param crt [OpenSSL::X509::Certificate]
|
425
|
+
# @param ch [TTTLS13::Message::ClientHell]
|
406
426
|
# @param chain [Array of OpenSSL::X509::Certificate]
|
427
|
+
# @param ocsp_response [OpenSSL::OCSP::Response]
|
407
428
|
#
|
408
|
-
# @return [TTTLS13::Message::Certificate, nil]
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
429
|
+
# @return [TTTLS13::Message::Certificate, CompressedCertificate, nil]
|
430
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
431
|
+
def gen_certificate(crt, ch, chain = [], ocsp_response = nil)
|
432
|
+
exs = Message::Extensions.new
|
433
|
+
# status_request
|
434
|
+
exs << Message::Extension::OCSPResponse.new(ocsp_response) \
|
435
|
+
unless ocsp_response.nil?
|
436
|
+
ces = [Message::CertificateEntry.new(crt, exs)] \
|
437
|
+
+ (chain || []).map { |c| Message::CertificateEntry.new(c) }
|
438
|
+
ct = Message::Certificate.new(certificate_list: ces)
|
439
|
+
|
440
|
+
# compress_certificate
|
441
|
+
cc = ch.extensions[Message::ExtensionType::COMPRESS_CERTIFICATE]
|
442
|
+
if !cc.nil? && !cc.algorithms.empty?
|
443
|
+
cca = (@settings[:compress_certificate_algorithms] || []).find do |a|
|
444
|
+
cc.algorithms.include?(a)
|
445
|
+
end
|
446
|
+
|
447
|
+
unless cca.nil?
|
448
|
+
ct = Message::CompressedCertificate.new(
|
449
|
+
certificate_message: ct,
|
450
|
+
algorithm: cca
|
451
|
+
)
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
ct
|
413
456
|
end
|
457
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
414
458
|
|
415
459
|
# @param key [OpenSSL::PKey::PKey]
|
416
460
|
# @param signature_scheme [TTTLS13::SignatureScheme]
|
@@ -432,11 +476,12 @@ module TTTLS13
|
|
432
476
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
433
477
|
#
|
434
478
|
# @return [TTTLS13::Message::Finished]
|
479
|
+
# @return [String]
|
435
480
|
def recv_finished(cipher)
|
436
|
-
cf = recv_message(receivable_ccs: true, cipher: cipher)
|
481
|
+
cf, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
|
437
482
|
terminate(:unexpected_message) unless cf.is_a?(Message::Finished)
|
438
483
|
|
439
|
-
cf
|
484
|
+
[cf, orig_msg]
|
440
485
|
end
|
441
486
|
|
442
487
|
# @param named_group [TTTLS13::NamedGroup]
|
@@ -444,7 +489,7 @@ module TTTLS13
|
|
444
489
|
# @return [TTTLS13::Message::Extensions]
|
445
490
|
# @return [OpenSSL::PKey::EC.$Object]
|
446
491
|
def gen_sh_extensions(named_group)
|
447
|
-
exs =
|
492
|
+
exs = Message::Extensions.new
|
448
493
|
# supported_versions: only TLS 1.3
|
449
494
|
exs << Message::Extension::SupportedVersions.new(
|
450
495
|
msg_type: Message::HandshakeType::SERVER_HELLO
|
@@ -455,7 +500,7 @@ module TTTLS13
|
|
455
500
|
= Message::Extension::KeyShare.gen_sh_key_share(named_group)
|
456
501
|
exs << key_share
|
457
502
|
|
458
|
-
[
|
503
|
+
[exs, priv_key]
|
459
504
|
end
|
460
505
|
|
461
506
|
# @param ch [TTTLS13::Message::ClientHello]
|
@@ -464,15 +509,16 @@ module TTTLS13
|
|
464
509
|
#
|
465
510
|
# @return [TTTLS13::Message::Extensions]
|
466
511
|
def gen_ee_extensions(ch, alpn, record_size_limit)
|
467
|
-
exs =
|
512
|
+
exs = Message::Extensions.new
|
468
513
|
|
469
514
|
# server_name
|
470
515
|
exs << Message::Extension::ServerName.new('') \
|
471
516
|
if ch.extensions.include?(Message::ExtensionType::SERVER_NAME)
|
472
517
|
|
473
518
|
# supported_groups
|
474
|
-
exs
|
475
|
-
|
519
|
+
exs << Message::Extension::SupportedGroups.new(
|
520
|
+
@settings[:supported_groups]
|
521
|
+
)
|
476
522
|
|
477
523
|
# alpn
|
478
524
|
exs << Message::Extension::Alpn.new([alpn]) unless alpn.nil?
|
@@ -481,7 +527,7 @@ module TTTLS13
|
|
481
527
|
exs << Message::Extension::RecordSizeLimit.new(record_size_limit) \
|
482
528
|
unless record_size_limit.nil?
|
483
529
|
|
484
|
-
|
530
|
+
exs
|
485
531
|
end
|
486
532
|
|
487
533
|
# @param key [OpenSSL::PKey::PKey]
|
@@ -543,6 +589,11 @@ module TTTLS13
|
|
543
589
|
|
544
590
|
matching_san?(crt, server_name)
|
545
591
|
end
|
592
|
+
|
593
|
+
# @return [OpenSSL::OCSP::Response, nil]
|
594
|
+
def fetch_ocsp_response
|
595
|
+
@settings[:process_ocsp_response]&.call
|
596
|
+
end
|
546
597
|
end
|
547
598
|
# rubocop: enable Metrics/ClassLength
|
548
599
|
end
|
data/lib/tttls1.3/transcript.rb
CHANGED
@@ -19,10 +19,6 @@ module TTTLS13
|
|
19
19
|
CF = 12
|
20
20
|
|
21
21
|
class Transcript < Hash
|
22
|
-
def initialize
|
23
|
-
super
|
24
|
-
end
|
25
|
-
|
26
22
|
alias super_include? include?
|
27
23
|
|
28
24
|
# @param digest [String] name of digest algorithm
|
@@ -62,12 +58,12 @@ module TTTLS13
|
|
62
58
|
exc_prefix = Message::HandshakeType::MESSAGE_HASH \
|
63
59
|
+ "\x00\x00" \
|
64
60
|
+ OpenSSL::Digest.new(digest).digest_length.to_uint8 \
|
65
|
-
+ OpenSSL::Digest.digest(digest, self[CH1].
|
66
|
-
+ self[HRR].
|
61
|
+
+ OpenSSL::Digest.digest(digest, self[CH1].last) \
|
62
|
+
+ self[HRR].last
|
67
63
|
end
|
68
64
|
|
69
65
|
messages = (CH..end_index).to_a.map do |m|
|
70
|
-
include?(m) ? self[m].
|
66
|
+
include?(m) ? self[m].last : ''
|
71
67
|
end
|
72
68
|
exc_prefix + messages.join
|
73
69
|
end
|
data/lib/tttls1.3/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -11,7 +11,7 @@ RSpec.describe Client do
|
|
11
11
|
client = Client.new(mock_socket, 'localhost')
|
12
12
|
extensions, _priv_keys = client.send(:gen_ch_extensions)
|
13
13
|
client.send(:send_client_hello, extensions)
|
14
|
-
Record.deserialize(mock_socket.read, Cryptograph::Passer.new)
|
14
|
+
Record.deserialize(mock_socket.read, Cryptograph::Passer.new).first
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'should send default ClientHello' do
|
@@ -37,7 +37,7 @@ RSpec.describe Client do
|
|
37
37
|
+ msg_len.to_uint16 \
|
38
38
|
+ TESTBINARY_SERVER_HELLO)
|
39
39
|
client = Client.new(mock_socket, 'localhost')
|
40
|
-
client.send(:recv_server_hello)
|
40
|
+
client.send(:recv_server_hello).first
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'should receive ServerHello' do
|
@@ -65,20 +65,20 @@ RSpec.describe Client do
|
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'should receive EncryptedExtensions' do
|
68
|
-
message = client.send(:recv_encrypted_extensions, cipher)
|
68
|
+
message, = client.send(:recv_encrypted_extensions, cipher)
|
69
69
|
expect(message.msg_type).to eq HandshakeType::ENCRYPTED_EXTENSIONS
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'should receive Certificate' do
|
73
73
|
client.send(:recv_encrypted_extensions, cipher) # to skip
|
74
|
-
message = client.send(:recv_certificate, cipher)
|
74
|
+
message, = client.send(:recv_certificate, cipher)
|
75
75
|
expect(message.msg_type).to eq HandshakeType::CERTIFICATE
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'should receive CertificateVerify' do
|
79
79
|
client.send(:recv_encrypted_extensions, cipher) # to skip
|
80
80
|
client.send(:recv_certificate, cipher) # to skip
|
81
|
-
message = client.send(:recv_certificate_verify, cipher)
|
81
|
+
message, = client.send(:recv_certificate_verify, cipher)
|
82
82
|
expect(message.msg_type).to eq HandshakeType::CERTIFICATE_VERIFY
|
83
83
|
end
|
84
84
|
|
@@ -86,7 +86,7 @@ RSpec.describe Client do
|
|
86
86
|
client.send(:recv_encrypted_extensions, cipher) # to skip
|
87
87
|
client.send(:recv_certificate, cipher) # to skip
|
88
88
|
client.send(:recv_certificate_verify, cipher) # to skip
|
89
|
-
message = client.send(:recv_finished, cipher)
|
89
|
+
message, = client.send(:recv_finished, cipher)
|
90
90
|
expect(message.msg_type).to eq HandshakeType::FINISHED
|
91
91
|
end
|
92
92
|
end
|
@@ -97,14 +97,20 @@ RSpec.describe Client do
|
|
97
97
|
end
|
98
98
|
|
99
99
|
let(:transcript) do
|
100
|
+
ch = ClientHello.deserialize(TESTBINARY_CLIENT_HELLO)
|
101
|
+
sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
|
102
|
+
ee = EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS)
|
103
|
+
ct = Certificate.deserialize(TESTBINARY_CERTIFICATE)
|
104
|
+
cv = CertificateVerify.deserialize(TESTBINARY_CERTIFICATE_VERIFY)
|
105
|
+
sf = Finished.deserialize(TESTBINARY_SERVER_FINISHED)
|
100
106
|
transcript = Transcript.new
|
101
107
|
transcript.merge!(
|
102
|
-
CH =>
|
103
|
-
SH =>
|
104
|
-
EE =>
|
105
|
-
CT =>
|
106
|
-
CV =>
|
107
|
-
SF =>
|
108
|
+
CH => [ch, TESTBINARY_CLIENT_HELLO],
|
109
|
+
SH => [sh, TESTBINARY_SERVER_HELLO],
|
110
|
+
EE => [ee, TESTBINARY_ENCRYPTED_EXTENSIONS],
|
111
|
+
CT => [ct, TESTBINARY_CERTIFICATE],
|
112
|
+
CV => [cv, TESTBINARY_CERTIFICATE_VERIFY],
|
113
|
+
SF => [sf, TESTBINARY_SERVER_FINISHED]
|
108
114
|
)
|
109
115
|
transcript
|
110
116
|
end
|
@@ -140,7 +146,7 @@ RSpec.describe Client do
|
|
140
146
|
write_iv: TESTBINARY_CLIENT_FINISHED_WRITE_IV,
|
141
147
|
sequence_number: SequenceNumber.new
|
142
148
|
)
|
143
|
-
Record.deserialize(mock_socket.read, hs_rcipher)
|
149
|
+
Record.deserialize(mock_socket.read, hs_rcipher).first
|
144
150
|
end
|
145
151
|
|
146
152
|
it 'should send Finished' do
|
@@ -170,14 +176,17 @@ RSpec.describe Client do
|
|
170
176
|
end
|
171
177
|
|
172
178
|
let(:transcript) do
|
179
|
+
ch = ClientHello.deserialize(TESTBINARY_CLIENT_HELLO)
|
180
|
+
sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
|
181
|
+
ee = EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS)
|
173
182
|
transcript = Transcript.new
|
174
183
|
transcript.merge!(
|
175
|
-
CH =>
|
176
|
-
SH =>
|
177
|
-
EE =>
|
178
|
-
CT => ct,
|
179
|
-
CV => cv,
|
180
|
-
SF => sf
|
184
|
+
CH => [ch, TESTBINARY_CLIENT_HELLO],
|
185
|
+
SH => [sh, TESTBINARY_SERVER_HELLO],
|
186
|
+
EE => [ee, TESTBINARY_ENCRYPTED_EXTENSIONS],
|
187
|
+
CT => [ct, TESTBINARY_CERTIFICATE],
|
188
|
+
CV => [cv, TESTBINARY_CERTIFICATE_VERIFY],
|
189
|
+
SF => [sf, TESTBINARY_SERVER_FINISHED]
|
181
190
|
)
|
182
191
|
end
|
183
192
|
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'spec_helper'
|
5
|
+
using Refinements
|
6
|
+
|
7
|
+
RSpec.describe Alpn do
|
8
|
+
context 'valid compress_certificate' do
|
9
|
+
let(:algorithms) do
|
10
|
+
[CertificateCompressionAlgorithm::ZLIB]
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:extension) do
|
14
|
+
CompressCertificate.new(algorithms)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should be generated' do
|
18
|
+
expect(extension.extension_type)
|
19
|
+
.to eq ExtensionType::COMPRESS_CERTIFICATE
|
20
|
+
expect(extension.algorithms).to eq algorithms
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should be serialized' do
|
24
|
+
expect(extension.serialize)
|
25
|
+
.to eq ExtensionType::COMPRESS_CERTIFICATE \
|
26
|
+
+ 3.to_uint16 \
|
27
|
+
+ 2.to_uint8 \
|
28
|
+
+ "\x00\x01"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'invalid compress_certificate, empty,' do
|
33
|
+
let(:extension) do
|
34
|
+
CompressCertificate.new([])
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should not be generated' do
|
38
|
+
expect { extension }.to raise_error(ErrorAlerts)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'valid compress_certificate binary' do
|
43
|
+
let(:extension) do
|
44
|
+
CompressCertificate.deserialize(TESTBINARY_COMPRESS_CERTIFICATE)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should generate valid object' do
|
48
|
+
expect(extension.extension_type)
|
49
|
+
.to eq ExtensionType::COMPRESS_CERTIFICATE
|
50
|
+
expect(extension.algorithms)
|
51
|
+
.to eq [CertificateCompressionAlgorithm::ZLIB]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/spec/connection_spec.rb
CHANGED
@@ -32,15 +32,18 @@ RSpec.describe Connection do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
let(:transcript) do
|
35
|
+
ch = ClientHello.deserialize(TESTBINARY_CLIENT_HELLO)
|
36
|
+
sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
|
37
|
+
ee = EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS)
|
35
38
|
transcript = Transcript.new
|
36
39
|
transcript.merge!(
|
37
|
-
CH =>
|
38
|
-
SH =>
|
39
|
-
EE =>
|
40
|
-
CT => ct,
|
41
|
-
CV => cv,
|
42
|
-
CF => cf,
|
43
|
-
SF => sf
|
40
|
+
CH => [ch, TESTBINARY_CLIENT_HELLO],
|
41
|
+
SH => [sh, TESTBINARY_SERVER_HELLO],
|
42
|
+
EE => [ee, TESTBINARY_ENCRYPTED_EXTENSIONS],
|
43
|
+
CT => [ct, TESTBINARY_CERTIFICATE],
|
44
|
+
CV => [cv, TESTBINARY_CERTIFICATE_VERIFY],
|
45
|
+
CF => [cf, TESTBINARY_CLIENT_FINISHED],
|
46
|
+
SF => [sf, TESTBINARY_SERVER_FINISHED]
|
44
47
|
)
|
45
48
|
end
|
46
49
|
|
@@ -115,16 +118,20 @@ RSpec.describe Connection do
|
|
115
118
|
end
|
116
119
|
|
117
120
|
let(:transcript) do
|
121
|
+
ch1 = ClientHello.deserialize(TESTBINARY_HRR_CLIENT_HELLO1)
|
122
|
+
hrr = ServerHello.deserialize(TESTBINARY_HRR_HELLO_RETRY_REQUEST)
|
123
|
+
ch = ClientHello.deserialize(TESTBINARY_HRR_CLIENT_HELLO)
|
124
|
+
sh = ServerHello.deserialize(TESTBINARY_HRR_SERVER_HELLO)
|
125
|
+
ee = EncryptedExtensions.deserialize(TESTBINARY_HRR_ENCRYPTED_EXTENSIONS)
|
118
126
|
transcript = Transcript.new
|
119
127
|
transcript.merge!(
|
120
|
-
CH1 =>
|
121
|
-
HRR =>
|
122
|
-
CH =>
|
123
|
-
SH =>
|
124
|
-
EE =>
|
125
|
-
|
126
|
-
|
127
|
-
CV => cv
|
128
|
+
CH1 => [ch1, TESTBINARY_HRR_CLIENT_HELLO1],
|
129
|
+
HRR => [hrr, TESTBINARY_HRR_HELLO_RETRY_REQUEST],
|
130
|
+
CH => [ch, TESTBINARY_HRR_CLIENT_HELLO],
|
131
|
+
SH => [sh, TESTBINARY_HRR_SERVER_HELLO],
|
132
|
+
EE => [ee, TESTBINARY_HRR_ENCRYPTED_EXTENSIONS],
|
133
|
+
CT => [ct, TESTBINARY_HRR_CERTIFICATE],
|
134
|
+
CV => [cv, TESTBINARY_HRR_CERTIFICATE_VERIFY]
|
128
135
|
)
|
129
136
|
end
|
130
137
|
|
data/spec/extensions_spec.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require_relative 'spec_helper'
|
5
|
+
using Refinements
|
5
6
|
|
6
7
|
RSpec.describe Extensions do
|
7
8
|
context 'empty extensions' do
|
@@ -167,4 +168,19 @@ RSpec.describe Extensions do
|
|
167
168
|
expect(extensions).to include ExtensionType::RECORD_SIZE_LIMIT
|
168
169
|
end
|
169
170
|
end
|
171
|
+
|
172
|
+
context 'duplicated extension_type' do
|
173
|
+
let(:server_name) do
|
174
|
+
ServerName.new('example.com')
|
175
|
+
end
|
176
|
+
|
177
|
+
let(:testbinary) do
|
178
|
+
server_name.serialize * 2
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should raise error, if extension_type get duplicated' do
|
182
|
+
expect { Extensions.deserialize(testbinary, HandshakeType::CLIENT_HELLO) }
|
183
|
+
.to raise_error(ErrorAlerts)
|
184
|
+
end
|
185
|
+
end
|
170
186
|
end
|
data/spec/fixtures/rsa_rsa.crt
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
-----BEGIN CERTIFICATE-----
|
2
|
-
|
3
|
-
|
2
|
+
MIIC2TCCAcGgAwIBAgIJALo0YKZBVqYnMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
|
3
|
+
BAMMB3Rlc3QtY2EwHhcNMjAwNzE1MTU0NTE4WhcNMzAwNzEzMTU0NTE4WjAUMRIw
|
4
4
|
EAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
5
|
+
AQC65xzvPQrsXXRVsQ4rcrmvOF0gdWV38JKlhHUrS50//T0S55FUSBkuVXUDCZDx
|
6
|
+
dOf0y/5HaMb3hm68+ld5B/oNtoPlJWW6Sgc8OLERQy9qGpwR0mXND4SnZ9or7RDV
|
7
|
+
8tAEg/Hzq5rm6Xy2WClSR+nHg2tVh2Szde39j7o8ivJpHPzfEyZh37y9oIiY2/FP
|
8
|
+
QpbAe8n3Ses04D3jhZRoysdcuneWuG3h5DJ9X4IhZUBM54nEO5IQElyYnF6xY/Lt
|
9
|
+
Gykf8+ydiuAZpZF5FGGfoiKB7XdIwhSlK1XRFeBbHRqyAFjpSNtqy6RPdJINLseb
|
10
|
+
wG6DNSxcLm91C6ZJaaqu7Qp1AgMBAAGjMDAuMAkGA1UdEwQCMAAwCwYDVR0PBAQD
|
11
|
+
AgWgMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEALqaQ
|
12
|
+
J5H9jB2VmIEDxhXAQTeqW1Hmp0oHhL1XcAvNS+JILjFfAdjMe/3Kei3hQJv8j8sE
|
13
|
+
uck3o7iA4kcE0ydUzO7TM7efjqcksyZrmWSB0xj+NHjcybwhD4Selr1vBSCU0IHN
|
14
|
+
Ap+zYbBX7eQawm2lIzniBvS6MmP+dgZjhy73FVQ4oSz+wTcg1iPkhulYL4iV/HSG
|
15
|
+
fND5gUvlRbLHGTETpCdq7iJNOpNl/OYboJLPvVpx8H7Jc+L2bQl05fj/koO35xaL
|
16
|
+
JuZGj5aVOKw45WvqERpe1RI3077dWE6bAr9DzrW13IqmFMbPD817pcB6+ILZnMAF
|
17
|
+
RhobWRU6PA4TdDP8bg==
|
18
18
|
-----END CERTIFICATE-----
|
data/spec/fixtures/rsa_rsa.key
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
-----BEGIN RSA PRIVATE KEY-----
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
/
|
25
|
-
|
26
|
-
|
2
|
+
MIIEowIBAAKCAQEAuucc7z0K7F10VbEOK3K5rzhdIHVld/CSpYR1K0udP/09EueR
|
3
|
+
VEgZLlV1AwmQ8XTn9Mv+R2jG94ZuvPpXeQf6DbaD5SVlukoHPDixEUMvahqcEdJl
|
4
|
+
zQ+Ep2faK+0Q1fLQBIPx86ua5ul8tlgpUkfpx4NrVYdks3Xt/Y+6PIryaRz83xMm
|
5
|
+
Yd+8vaCImNvxT0KWwHvJ90nrNOA944WUaMrHXLp3lrht4eQyfV+CIWVATOeJxDuS
|
6
|
+
EBJcmJxesWPy7RspH/PsnYrgGaWReRRhn6Iige13SMIUpStV0RXgWx0asgBY6Ujb
|
7
|
+
asukT3SSDS7Hm8BugzUsXC5vdQumSWmqru0KdQIDAQABAoIBABPIjNaB9psIVV0Q
|
8
|
+
rbhJn3/9jlX2NzRX4Z3lhGV9znpMet96ZXavXwL5hrY4mAAG6NqPkS3L2Guw7h3Q
|
9
|
+
vduQzZYQAKwLplXuqg9kzNFP9D/d6zEzvRTUlK0HoB9QK50J45zmvoCVZIMWqd2/
|
10
|
+
PTh5ZjR5I65c83rPe86AHS11Y61edr+vvGtI07kvj7EzR3jie0Lzzpj7TbmjTt5U
|
11
|
+
v9rskcxjulQOmp8t/3ouptUhi16PRXPof0yzRGo6rrCUoQ7Cuy1dbFZ96dIBxrt4
|
12
|
+
h9suE6MtpXdsGfI5FZPOKHqUcw8hZfUgeOYm4OTV3vBYie0xJ77i9YgqR+UwymjA
|
13
|
+
NK4AOY0CgYEA553JtUvl8py76HjL3DxfbU38Dq22AF9sdUAs9Xwy9B8Y6R9SyrPI
|
14
|
+
nab+3EE0gz5NnFLFCILK4A7ewe3OB3bE7/P4mc7JlUWM2LAcBz7K50seIKD3r+cj
|
15
|
+
VzLHarOBi/VZ0pe1lDj/cuQ6cXTLHbKtk2XGCRnCBMJlog4ruFMYJ+sCgYEAzpRD
|
16
|
+
3YtuQcT0rtvK05BcdWD3nGgsrAauLvKz80LIu4zX9nfz/H6lNRpZYJ2jrLR1ikbX
|
17
|
+
XVWIsNlWizAuWEbGokUEYDTuhkh3591nrdPyB6/0Lm2Snl+q7mKIUFrZ08MXe7U8
|
18
|
+
Z/qPq2VLVSzCyoGX0l4GuNymgDH6NVR/i5yQXx8CgYBNJ1OUz+aWbb1ukCagg3/q
|
19
|
+
QksPfLAe6aqQWENhtvCmP2Gl7mg+26qdUY6eQh5DBdMGms/FqQP5pRpxEU1LUTYD
|
20
|
+
FIsgeTDPR67GU8vSYglnCK/NgLFhaCZumpyxH4Cs5Zr5Os4ixOXbGMmbF6O9jdKi
|
21
|
+
Qgm46FqoCTWfyQapTQzD5wKBgGQV4WuNCjZDPmkZhANMhf84o77bmgkek3WbkSPi
|
22
|
+
z25OprN7GnLSySgZRARTW+Fo7Sm5eM53impkYlG9XjbW05X66kvSWV4l7jIgSwMl
|
23
|
+
FLY0wZFc9RRWNXKZuoF0AuVeOBpvjHy0ILdhtEXoEdgbQXtios8d2G1zyU3dSo5R
|
24
|
+
pIDxAoGBAIlXeI9tB0X9ywXKylI3CyHi8ex/k6o4WTj/5fH4bYp4faHBRm78Ho81
|
25
|
+
Ih9rewMw7fMC3YUN3rcyvHRQqbJ2Wcxpyf0k45GMxTRasoVXCXgV/sMNCHh/ddZM
|
26
|
+
Gf5ZTeq10gJPofBlPObg5VrlCLRnIFaNI4izpq2A+/FqTrEvSGlf
|
27
27
|
-----END RSA PRIVATE KEY-----
|