tttls1.3 0.2.10 → 0.2.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +32 -0
  3. data/.rubocop.yml +6 -3
  4. data/Gemfile +3 -4
  5. data/README.md +5 -1
  6. data/Rakefile +66 -7
  7. data/example/helper.rb +3 -3
  8. data/example/https_client.rb +1 -1
  9. data/example/https_client_using_0rtt.rb +3 -3
  10. data/example/https_client_using_hrr.rb +1 -1
  11. data/example/https_client_using_hrr_and_ticket.rb +2 -2
  12. data/example/https_client_using_status_request.rb +31 -0
  13. data/example/https_client_using_ticket.rb +2 -2
  14. data/example/https_server.rb +3 -2
  15. data/interop/client_spec.rb +6 -6
  16. data/interop/server_spec.rb +6 -6
  17. data/lib/tttls1.3.rb +1 -0
  18. data/lib/tttls1.3/client.rb +97 -12
  19. data/lib/tttls1.3/connection.rb +44 -11
  20. data/lib/tttls1.3/cryptograph.rb +1 -1
  21. data/lib/tttls1.3/cryptograph/aead.rb +20 -7
  22. data/lib/tttls1.3/message.rb +1 -1
  23. data/lib/tttls1.3/message/alert.rb +2 -2
  24. data/lib/tttls1.3/message/extension/signature_algorithms.rb +13 -3
  25. data/lib/tttls1.3/message/extension/signature_algorithms_cert.rb +5 -4
  26. data/lib/tttls1.3/message/extension/status_request.rb +73 -17
  27. data/lib/tttls1.3/message/extensions.rb +33 -11
  28. data/lib/tttls1.3/server.rb +40 -13
  29. data/lib/tttls1.3/utils.rb +15 -0
  30. data/lib/tttls1.3/version.rb +1 -1
  31. data/spec/extensions_spec.rb +16 -0
  32. data/spec/fixtures/rsa_rsa.crt +15 -15
  33. data/spec/fixtures/rsa_rsa.key +25 -25
  34. data/spec/fixtures/rsa_rsa_ocsp.crt +18 -0
  35. data/spec/fixtures/rsa_rsa_ocsp.key +27 -0
  36. data/spec/server_hello_spec.rb +1 -1
  37. data/spec/signature_algorithms_cert_spec.rb +4 -0
  38. data/spec/signature_algorithms_spec.rb +4 -0
  39. data/spec/spec_helper.rb +35 -1
  40. data/spec/status_request_spec.rb +77 -10
  41. data/tttls1.3.gemspec +0 -1
  42. metadata +12 -7
  43. data/.github/workflows/main.yml +0 -25
@@ -44,10 +44,11 @@ module TTTLS13
44
44
  #
45
45
  # @return [TTTLS13::Message::Extensions]
46
46
  # rubocop: disable Metrics/CyclomaticComplexity
47
+ # rubocop: disable Metrics/PerceivedComplexity
47
48
  def self.deserialize(binary, msg_type)
48
49
  raise Error::ErrorAlerts, :internal_error if binary.nil?
49
50
 
50
- extensions = []
51
+ exs = Extensions.new
51
52
  i = 0
52
53
  while i < binary.length
53
54
  raise Error::ErrorAlerts, :decode_error if i + 4 > binary.length
@@ -66,32 +67,41 @@ module TTTLS13
66
67
  ex = Extension::UnknownExtension.new(extension_type: extension_type,
67
68
  extension_data: ex_bin)
68
69
  end
69
- extensions << ex
70
+
71
+ # There MUST NOT be more than one extension of the same type in a
72
+ # given extension block.
73
+ raise Error::ErrorAlerts, :unsupported_extension \
74
+ if exs.include?(extension_type)
75
+
76
+ exs[extension_type] = ex
70
77
  i += ex_len
71
78
  end
72
79
  raise Error::ErrorAlerts, :decode_error unless i == binary.length
73
80
 
74
- Extensions.new(extensions)
81
+ exs
75
82
  end
76
83
  # rubocop: enable Metrics/CyclomaticComplexity
84
+ # rubocop: enable Metrics/PerceivedComplexity
77
85
 
78
86
  # @param key [TTTLS13::Message::ExtensionType]
87
+ # @param default
79
88
  #
80
89
  # @return [TTTLS13::Message::Extension::$Object]
81
- def [](key)
90
+ def fetch(key, default = nil)
82
91
  return nil if super_fetch(key, nil).is_a?(Extension::UnknownExtension)
83
92
 
84
- super_fetch(key, nil)
93
+ super_fetch(key, default)
85
94
  end
86
95
 
87
- # @param key [TTTLS13::Message::ExtensionType]
88
- # @param default
96
+ def [](key)
97
+ fetch(key)
98
+ end
99
+
100
+ # @param ex [TTTLS13::Message::Extension::$Object]
89
101
  #
90
102
  # @return [TTTLS13::Message::Extension::$Object]
91
- def fetch(key, default = nil)
92
- return nil if super_fetch(key, nil).is_a?(Extension::UnknownExtension)
93
-
94
- super_fetch(key, default)
103
+ def <<(ex)
104
+ store(ex.extension_type, ex)
95
105
  end
96
106
 
97
107
  class << self
@@ -110,12 +120,23 @@ module TTTLS13
110
120
  #
111
121
  # @return [TTTLS13::Message::Extension::$Object, nil]
112
122
  # rubocop: disable Metrics/CyclomaticComplexity
123
+ # rubocop: disable Metrics/MethodLength
113
124
  def deserialize_extension(binary, extension_type, msg_type)
114
125
  raise Error::ErrorAlerts, :internal_error if binary.nil?
115
126
 
116
127
  case extension_type
117
128
  when ExtensionType::SERVER_NAME
118
129
  Extension::ServerName.deserialize(binary)
130
+ when ExtensionType::STATUS_REQUEST
131
+ if msg_type == HandshakeType::CLIENT_HELLO
132
+ return Extension::OCSPStatusRequest.deserialize(binary)
133
+ end
134
+
135
+ if msg_type == HandshakeType::CERTIFICATE
136
+ return Extension::OCSPResponse.deserialize(binary)
137
+ end
138
+
139
+ Extension::UnknownExtension.deserialize(binary, extension_type)
119
140
  when ExtensionType::SUPPORTED_GROUPS
120
141
  Extension::SupportedGroups.deserialize(binary)
121
142
  when ExtensionType::SIGNATURE_ALGORITHMS
@@ -143,6 +164,7 @@ module TTTLS13
143
164
  end
144
165
  end
145
166
  # rubocop: enable Metrics/CyclomaticComplexity
167
+ # rubocop: enable Metrics/MethodLength
146
168
  end
147
169
  end
148
170
  end
@@ -46,11 +46,13 @@ module TTTLS13
46
46
 
47
47
  DEFAULT_SERVER_SETTINGS = {
48
48
  crt_file: nil,
49
+ chain_files: nil,
49
50
  key_file: nil,
50
51
  cipher_suites: DEFAULT_SP_CIPHER_SUITES,
51
52
  signature_algorithms: DEFAULT_SP_SIGNATURE_ALGORITHMS,
52
53
  supported_groups: DEFAULT_SP_NAMED_GROUP_LIST,
53
54
  alpn: nil,
55
+ process_ocsp_response: nil,
54
56
  compatibility_mode: true,
55
57
  loglevel: Logger::WARN
56
58
  }.freeze
@@ -75,6 +77,14 @@ module TTTLS13
75
77
  klass = @crt.public_key.class
76
78
  @key = klass.new(File.read(@settings[:key_file]))
77
79
  raise Error::ConfigError unless @crt.check_private_key(@key)
80
+
81
+ @chain = @settings[:chain_files]&.map do |f|
82
+ OpenSSL::X509::Certificate.new(File.read(f))
83
+ end
84
+ @chain ||= []
85
+ ([@crt] + @chain).each_cons(2) do |cert, sign|
86
+ raise Error::ConfigError unless cert.verify(sign.public_key)
87
+ end
78
88
  end
79
89
 
80
90
  # NOTE:
@@ -227,10 +237,14 @@ module TTTLS13
227
237
 
228
238
  ch = transcript[CH]
229
239
  rsl = @send_record_size \
230
- unless ch.extensions[Message::ExtensionType::RECORD_SIZE_LIMIT].nil?
240
+ if ch.extensions.include?(Message::ExtensionType::RECORD_SIZE_LIMIT)
231
241
  ee = transcript[EE] = gen_encrypted_extensions(ch, @alpn, rsl)
232
242
  # TODO: [Send CertificateRequest]
233
- ct = transcript[CT] = gen_certificate(@crt)
243
+
244
+ # status_request
245
+ ocsp_response = fetch_ocsp_response \
246
+ if ch.extensions.include?(Message::ExtensionType::STATUS_REQUEST)
247
+ ct = transcript[CT] = gen_certificate(@crt, @chain, ocsp_response)
234
248
  digest = CipherSuite.digest(@cipher_suite)
235
249
  cv = transcript[CV] = gen_certificate_verify(
236
250
  @key,
@@ -341,7 +355,7 @@ module TTTLS13
341
355
  #
342
356
  # @return [TTTLS13::Message::ServerHello]
343
357
  def send_hello_retry_request(ch1, cipher_suite)
344
- exs = []
358
+ exs = Message::Extensions.new
345
359
  # supported_versions
346
360
  exs << Message::Extension::SupportedVersions.new(
347
361
  msg_type: Message::HandshakeType::SERVER_HELLO
@@ -363,7 +377,7 @@ module TTTLS13
363
377
  random: Message::HRR_RANDOM,
364
378
  legacy_session_id_echo: ch1.legacy_session_id,
365
379
  cipher_suite: cipher_suite,
366
- extensions: Message::Extensions.new(exs)
380
+ extensions: exs
367
381
  )
368
382
  send_handshakes(Message::ContentType::HANDSHAKE, [sh],
369
383
  Cryptograph::Passer.new)
@@ -394,11 +408,18 @@ module TTTLS13
394
408
  end
395
409
 
396
410
  # @param crt [OpenSSL::X509::Certificate]
411
+ # @param chain [Array of OpenSSL::X509::Certificate]
412
+ # @param ocsp_response [OpenSSL::OCSP::Response]
397
413
  #
398
414
  # @return [TTTLS13::Message::Certificate, nil]
399
- def gen_certificate(crt)
400
- ce = Message::CertificateEntry.new(crt)
401
- Message::Certificate.new(certificate_list: [ce])
415
+ def gen_certificate(crt, chain = [], ocsp_response = nil)
416
+ exs = Message::Extensions.new
417
+ # status_request
418
+ exs << Message::Extension::OCSPResponse.new(ocsp_response) \
419
+ unless ocsp_response.nil?
420
+ ces = [Message::CertificateEntry.new(crt, exs)] \
421
+ + (chain || []).map { |c| Message::CertificateEntry.new(c) }
422
+ Message::Certificate.new(certificate_list: ces)
402
423
  end
403
424
 
404
425
  # @param key [OpenSSL::PKey::PKey]
@@ -433,7 +454,7 @@ module TTTLS13
433
454
  # @return [TTTLS13::Message::Extensions]
434
455
  # @return [OpenSSL::PKey::EC.$Object]
435
456
  def gen_sh_extensions(named_group)
436
- exs = []
457
+ exs = Message::Extensions.new
437
458
  # supported_versions: only TLS 1.3
438
459
  exs << Message::Extension::SupportedVersions.new(
439
460
  msg_type: Message::HandshakeType::SERVER_HELLO
@@ -444,7 +465,7 @@ module TTTLS13
444
465
  = Message::Extension::KeyShare.gen_sh_key_share(named_group)
445
466
  exs << key_share
446
467
 
447
- [Message::Extensions.new(exs), priv_key]
468
+ [exs, priv_key]
448
469
  end
449
470
 
450
471
  # @param ch [TTTLS13::Message::ClientHello]
@@ -453,15 +474,16 @@ module TTTLS13
453
474
  #
454
475
  # @return [TTTLS13::Message::Extensions]
455
476
  def gen_ee_extensions(ch, alpn, record_size_limit)
456
- exs = []
477
+ exs = Message::Extensions.new
457
478
 
458
479
  # server_name
459
480
  exs << Message::Extension::ServerName.new('') \
460
481
  if ch.extensions.include?(Message::ExtensionType::SERVER_NAME)
461
482
 
462
483
  # supported_groups
463
- exs \
464
- << Message::Extension::SupportedGroups.new(@settings[:supported_groups])
484
+ exs << Message::Extension::SupportedGroups.new(
485
+ @settings[:supported_groups]
486
+ )
465
487
 
466
488
  # alpn
467
489
  exs << Message::Extension::Alpn.new([alpn]) unless alpn.nil?
@@ -470,7 +492,7 @@ module TTTLS13
470
492
  exs << Message::Extension::RecordSizeLimit.new(record_size_limit) \
471
493
  unless record_size_limit.nil?
472
494
 
473
- Message::Extensions.new(exs)
495
+ exs
474
496
  end
475
497
 
476
498
  # @param key [OpenSSL::PKey::PKey]
@@ -532,6 +554,11 @@ module TTTLS13
532
554
 
533
555
  matching_san?(crt, server_name)
534
556
  end
557
+
558
+ # @return [OpenSSL::OCSP::Response, nil]
559
+ def fetch_ocsp_response
560
+ @settings[:process_ocsp_response]&.call
561
+ end
535
562
  end
536
563
  # rubocop: enable Metrics/ClassLength
537
564
  end
@@ -61,6 +61,21 @@ module TTTLS13
61
61
  length.to_uint64 + self
62
62
  end
63
63
  end
64
+
65
+ refine OpenSSL::X509::Certificate do
66
+ unless method_defined?(:ocsp_uris)
67
+ define_method(:ocsp_uris) do
68
+ aia = extensions.find { |ex| ex.oid == 'authorityInfoAccess' }
69
+ return nil if aia.nil?
70
+
71
+ ostr = OpenSSL::ASN1.decode(aia.to_der).value.last
72
+ ocsp = OpenSSL::ASN1.decode(ostr.value)
73
+ .map(&:value)
74
+ .select { |des| des.first.value == 'OCSP' }
75
+ ocsp&.map { |o| o[1].value }
76
+ end
77
+ end
78
+ end
64
79
  end
65
80
 
66
81
  module Convert
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTTLS13
4
- VERSION = '0.2.10'
4
+ VERSION = '0.2.15'
5
5
  end
@@ -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
@@ -1,18 +1,18 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- MIIC2TCCAcGgAwIBAgIJAM8aTIrMzHgzMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
3
- BAMMB3Rlc3QtY2EwHhcNMTkwNTI1MDEzODAyWhcNMjAwNTI0MDEzODAyWjAUMRIw
2
+ MIIC2TCCAcGgAwIBAgIJALo0YKZBVqYnMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
3
+ BAMMB3Rlc3QtY2EwHhcNMjAwNzE1MTU0NTE4WhcNMzAwNzEzMTU0NTE4WjAUMRIw
4
4
  EAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
5
- AQDb9cGc2hOrLp3VWpxw8WgDqEL3LzZ5a6iYwibeR4AEB5FJLhS3Wvxa1xOS510C
6
- Kyfk/0znJvN9y+C8tFpB1BAN1OpPvaMPcYWx9CfEeoXaA5+QtU0MWJV7uYMtEUEx
7
- mEOvDKK1ZvHhw7xUzwcJTFRo6ZY6LqjiozlSPkTrVRIWoy7qEzXnOza36xX18xVt
8
- azvJBBudtTrjjBfQv2DJdF44icWqOBvAwg54BAbaH3bZ1WOg5oRnOPeVumYbPBsl
9
- dCDs67S1+RHKMEjRTk7gzuGog9lxJVMluU7iyreROD9+GvJEY3ra2KH96rtIgzo6
10
- KFHlC4Ih18zRfJZePgMGi5zVAgMBAAGjMDAuMAkGA1UdEwQCMAAwCwYDVR0PBAQD
11
- AgWgMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAjDs
12
- 4PgPL2Tn8+TxFWEPjh3VUB2kNyYK4LFA/ooN81pDLmm9/qc0FcUs16YQIqYdZICc
13
- vE83z3RlTmSjsynaRXxYh0VGVE2g2pWiPzEGTGE5HJy2JOtidMiacskmvetbTyYd
14
- TLdTEFiAlXF9e24OanglmFr9QnA/Z/zQkuIb4t7KN8Dufsi3ljkoJ+puuPxrEQj0
15
- 4BfBo381jK5WULHJ2G9pz5pvy1GZLfj1tQyG2wkI/vV2tjFN+LLO7NCY3V6RjvEZ
16
- bH4ZdAQz9fbbp7eCXImP+OJYt97Q3RZFJjUWhmh4qFebelkeN3RnmWSFrgjh0O67
17
- pyNwVv0//MYIEhMUVQ==
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-----
@@ -1,27 +1,27 @@
1
1
  -----BEGIN RSA PRIVATE KEY-----
2
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- +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
- 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
- THS6m0Jarx2gNzFF3WuA2Ea4gtHKSo3guMHyDi8h7vUMd/4n9gFQgmq3PPQS7+J0
24
- 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
- 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
- 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
27
27
  -----END RSA PRIVATE KEY-----
@@ -0,0 +1,18 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIC4TCCAcmgAwIBAgIJALkL6IyOlMwWMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
3
+ BAMMB3Rlc3QtY2EwHhcNMTkxMTI2MDczMzExWhcNMjkxMTIzMDczMzExWjAUMRIw
4
+ EAYDVQQDDAl0ZXN0LW9jc3AwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
5
+ AQDapLrB5S2yXQ9Wt/O9SZzoMW8IChsPgtZYC8h4Z/bcbqRb/6Bq5YfcYxq84cD/
6
+ 8xn7e8R2OCNgva8GBlMy7d0czt3ysLnNlZ+dPu7MU4yS/R40LOhMGEf71mf6PLqj
7
+ 1ecaEclgbIhyIGHlUXQIAnhhpAwzHxKVAhcgBgQFs8NgNViAE3BpjyUW0qXE5RUY
8
+ BQ7V9/Kn/fnsfOk6jMF20V2Kxn5Sj/c+D59+vFX3FmQyqsTKoAKoUuNsFOvHGV0d
9
+ gxLggE5wq4AodrA40MY95HgCZ2rDfEKgfc9rKhLGz6s0etGFMVtjqK6YvpQYUOaS
10
+ 8JStLrGF1eINoJJFibIf69v9AgMBAAGjODA2MAkGA1UdEwQCMAAwEwYDVR0lBAww
11
+ CgYIKwYBBQUHAwkwFAYDVR0RBA0wC4IJdGVzdC1vY3NwMA0GCSqGSIb3DQEBCwUA
12
+ A4IBAQBHC6jRQyZhBJIdfP9CGpNO1dNHicwpFJ61ofwgzW1jEkVfBtVpqvEaEbYE
13
+ LVxru1s8VY281trhwRuZkDRv5hB/CUUbdPICwQlkyCdUoYURrJEm/mirK9494AGh
14
+ f33S+bMXZGAYLYoPYlSGj8EpL1Do3nvJK8//coRJlTEBcfgIIUlRMaeOiGrg3zpM
15
+ 1KGxO3GtG1mpod7BEMv3ZGI85p8wXF4N2Z+phBoAyRGW+R4VW3tF5bbqiKlRr3Lt
16
+ HNsuXHSQykKpxD085eeQLTZGVESrCcmNv8XvVxwGE1r0kmlwexADNvP3HDXseie+
17
+ 8QFIt+zvJb/lDy4xbCT/M4a7L9Gn
18
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEpAIBAAKCAQEA2qS6weUtsl0PVrfzvUmc6DFvCAobD4LWWAvIeGf23G6kW/+g
3
+ auWH3GMavOHA//MZ+3vEdjgjYL2vBgZTMu3dHM7d8rC5zZWfnT7uzFOMkv0eNCzo
4
+ TBhH+9Zn+jy6o9XnGhHJYGyIciBh5VF0CAJ4YaQMMx8SlQIXIAYEBbPDYDVYgBNw
5
+ aY8lFtKlxOUVGAUO1ffyp/357HzpOozBdtFdisZ+Uo/3Pg+ffrxV9xZkMqrEyqAC
6
+ qFLjbBTrxxldHYMS4IBOcKuAKHawONDGPeR4Amdqw3xCoH3PayoSxs+rNHrRhTFb
7
+ Y6iumL6UGFDmkvCUrS6xhdXiDaCSRYmyH+vb/QIDAQABAoIBAQC/s1D/siYHzeol
8
+ +XFelI1bVARqwxmI1wmB9wrU7yqViPjYpN+M+iTNyaLm2vUyNH6ibZkKohv6tTUh
9
+ DiiibcXBfWtCX0r5gueIomYThmmpcv6pdnpSRbPPjeRqlhZ6kZBn3hJ3VZGoptXO
10
+ j0UxxKCx03jS1bqgJU4LSNr7+OojjeKh8D9bxwCizhGx9239QwChtQTPr4U3aeTb
11
+ Qwx8WtNH/2zvpdylyXW/eg8MO4WPYXpxWSGQnRJG5knPa7hF+iRnszysbUPNBVUd
12
+ TUQJHBdtukt+7hDbPyMpMu0DwpqhOqsEk2avacWuCYEEE/SWmJ/mvLokbfECSUpy
13
+ ZqfXJPLNAoGBAPtd+m2YVmLJmjO2skv+zGG5KhHNF2cY6xLQWuHW/yChNjSzpLYm
14
+ YygyOd4hBH39ieQkBRs0QOX9S5Dzv6ERU1cr0CVDJeb9TQ9UTxXc01paJ+aoZNr5
15
+ uHoGO16xBR4tmidc4HmbHDFSwmRAFhkooHM9MVACUFABIdWqwEwSZa/HAoGBAN6s
16
+ WhPrsDyRAfKFV9bwD1P5aMPu6pjWOFO3bRIisPRtVzilamCkKvXCh1SyYHaNRjjG
17
+ fQYEZeCZTxHi7GxZltRG5DRsmm8rDz6E4OrTQMHfQNDiuw78uZZ9+YYwaIM3nt1i
18
+ /lN2hs79zj/HPf5qX9rw+CarOL0bdW97a/Monx4bAoGAeMqXXfT3hi9E15bypQxD
19
+ IK6/JaC9n0BdLkRLd/09ymtNxhORkipuOdGw9yo8o2Kj0arxfTol+Z83oedP7dGK
20
+ j/gw5McYvqB4WGZ2PpZIRkHOrMu883FPEexOuVktkWvuiP3brPQ5nwYa/dvCAsMA
21
+ H4CHYuBJwbhZjvinwaaRkN8CgYA9sQh/zmOUVCRy+Yh9jyLgBBCHgDDUyTzvzLjW
22
+ NnBKN+TbV9DiF3mjfxKZX5YkIj3bSvqmaR+Em1Txwqn31tZX15AwCgq7U/W0P4JE
23
+ 7ORbEixV8wsaOuB8FkjEabL677T+5wdJPmRZAq5asyu0yenmsa4+oF9m3S2rBknB
24
+ I3b6EwKBgQD1+0+xdGomMeKHg8jWuDytdlWmNXmbiV0g2yOm533jG67vGDPfgd0H
25
+ PNC62d7r5EhIVJwQZmW/GdOfZ7tI91XN+GjNyslr9t299hoMeRMT+Db2U+mQvKuS
26
+ Oz+MHhO8YnOz9GFbQShqiCFj4zTU/0Ga/BY8Y52lURftt/QIXo+7Vg==
27
+ -----END RSA PRIVATE KEY-----
@@ -187,7 +187,7 @@ RSpec.describe ServerHello do
187
187
  let(:message) do
188
188
  sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
189
189
  extensions = sh.instance_variable_get(:@extensions)
190
- extensions[ExtensionType::SUPPORTED_VERSIONS] = nil
190
+ extensions.delete(ExtensionType::SUPPORTED_VERSIONS)
191
191
  sh.instance_variable_set(:@extensions, extensions)
192
192
  sh
193
193
  end
@@ -24,6 +24,8 @@ RSpec.describe SignatureAlgorithmsCert do
24
24
  end
25
25
 
26
26
  it 'should be generated' do
27
+ expect(extension).to be_a(SignatureAlgorithmsCert)
28
+
27
29
  expect(extension.extension_type)
28
30
  .to eq ExtensionType::SIGNATURE_ALGORITHMS_CERT
29
31
  expect(extension.supported_signature_algorithms)
@@ -58,6 +60,8 @@ RSpec.describe SignatureAlgorithmsCert do
58
60
  end
59
61
 
60
62
  it 'should generate valid object' do
63
+ expect(extension).to be_a(SignatureAlgorithmsCert)
64
+
61
65
  expect(extension.extension_type)
62
66
  .to eq ExtensionType::SIGNATURE_ALGORITHMS_CERT
63
67
  expect(extension.supported_signature_algorithms)