tttls1.3 0.2.18 → 0.3.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +8 -5
  3. data/Gemfile +2 -0
  4. data/README.md +6 -3
  5. data/example/helper.rb +5 -2
  6. data/example/https_client_using_0rtt.rb +1 -1
  7. data/example/https_client_using_ech.rb +32 -0
  8. data/example/https_client_using_grease_ech.rb +26 -0
  9. data/example/https_client_using_grease_psk.rb +66 -0
  10. data/example/https_client_using_hrr_and_ech.rb +32 -0
  11. data/example/https_client_using_hrr_and_ticket.rb +1 -1
  12. data/example/https_client_using_ticket.rb +1 -1
  13. data/interop/client_spec.rb +3 -2
  14. data/interop/server_spec.rb +1 -3
  15. data/interop/{helper.rb → spec_helper.rb} +12 -5
  16. data/lib/tttls1.3/client.rb +553 -32
  17. data/lib/tttls1.3/connection.rb +9 -8
  18. data/lib/tttls1.3/cryptograph/aead.rb +1 -1
  19. data/lib/tttls1.3/error.rb +1 -1
  20. data/lib/tttls1.3/hpke.rb +91 -0
  21. data/lib/tttls1.3/key_schedule.rb +111 -8
  22. data/lib/tttls1.3/message/alert.rb +2 -1
  23. data/lib/tttls1.3/message/client_hello.rb +2 -1
  24. data/lib/tttls1.3/message/encrypted_extensions.rb +2 -1
  25. data/lib/tttls1.3/message/extension/alpn.rb +4 -5
  26. data/lib/tttls1.3/message/extension/compress_certificate.rb +1 -1
  27. data/lib/tttls1.3/message/extension/ech.rb +241 -0
  28. data/lib/tttls1.3/message/extension/key_share.rb +2 -4
  29. data/lib/tttls1.3/message/extension/server_name.rb +1 -1
  30. data/lib/tttls1.3/message/extensions.rb +20 -7
  31. data/lib/tttls1.3/message/record.rb +1 -1
  32. data/lib/tttls1.3/message/server_hello.rb +3 -5
  33. data/lib/tttls1.3/message.rb +3 -1
  34. data/lib/tttls1.3/named_group.rb +1 -1
  35. data/lib/tttls1.3/server.rb +2 -2
  36. data/lib/tttls1.3/utils.rb +8 -0
  37. data/lib/tttls1.3/version.rb +1 -1
  38. data/lib/tttls1.3.rb +4 -0
  39. data/spec/client_spec.rb +40 -0
  40. data/spec/connection_spec.rb +22 -7
  41. data/spec/ech_spec.rb +81 -0
  42. data/spec/extensions_spec.rb +1 -2
  43. data/spec/key_schedule_spec.rb +2 -2
  44. data/spec/server_spec.rb +22 -7
  45. data/spec/spec_helper.rb +41 -5
  46. data/tttls1.3.gemspec +2 -0
  47. metadata +39 -3
@@ -7,6 +7,7 @@ Dir[File.dirname(__FILE__) + '/extension/*.rb'].sort.each { |f| require f }
7
7
  module TTTLS13
8
8
  using Refinements
9
9
  module Message
10
+ # rubocop: disable Metrics/ClassLength
10
11
  class Extensions < Hash
11
12
  # @param extensions [Array of TTTLS13::Message::Extension::$Object]
12
13
  #
@@ -119,6 +120,7 @@ module TTTLS13
119
120
  # @raise [TTTLS13::Error::ErrorAlerts]
120
121
  #
121
122
  # @return [TTTLS13::Message::Extension::$Object, nil]
123
+ # rubocop: disable Metrics/AbcSize
122
124
  # rubocop: disable Metrics/CyclomaticComplexity
123
125
  # rubocop: disable Metrics/MethodLength
124
126
  # rubocop: disable Metrics/PerceivedComplexity
@@ -130,14 +132,12 @@ module TTTLS13
130
132
  Extension::ServerName.deserialize(binary)
131
133
  when ExtensionType::STATUS_REQUEST
132
134
  if msg_type == HandshakeType::CLIENT_HELLO
133
- return Extension::OCSPStatusRequest.deserialize(binary)
135
+ Extension::OCSPStatusRequest.deserialize(binary)
136
+ elsif msg_type == HandshakeType::CERTIFICATE
137
+ Extension::OCSPResponse.deserialize(binary)
138
+ else
139
+ Extension::UnknownExtension.deserialize(binary, extension_type)
134
140
  end
135
-
136
- if msg_type == HandshakeType::CERTIFICATE
137
- return Extension::OCSPResponse.deserialize(binary)
138
- end
139
-
140
- Extension::UnknownExtension.deserialize(binary, extension_type)
141
141
  when ExtensionType::SUPPORTED_GROUPS
142
142
  Extension::SupportedGroups.deserialize(binary)
143
143
  when ExtensionType::SIGNATURE_ALGORITHMS
@@ -162,14 +162,27 @@ module TTTLS13
162
162
  Extension::SignatureAlgorithmsCert.deserialize(binary)
163
163
  when ExtensionType::KEY_SHARE
164
164
  Extension::KeyShare.deserialize(binary, msg_type)
165
+ when ExtensionType::ENCRYPTED_CLIENT_HELLO
166
+ case msg_type
167
+ when HandshakeType::CLIENT_HELLO
168
+ Extension::ECHClientHello.deserialize(binary)
169
+ when HandshakeType::ENCRYPTED_EXTENSIONS
170
+ Extension::ECHEncryptedExtensions.deserialize(binary)
171
+ when HandshakeType::HELLO_RETRY_REQUEST
172
+ Extension::ECHHelloRetryRequest.deserialize(binary)
173
+ else
174
+ Extension::UnknownExtension.deserialize(binary, extension_type)
175
+ end
165
176
  else
166
177
  Extension::UnknownExtension.deserialize(binary, extension_type)
167
178
  end
168
179
  end
180
+ # rubocop: enable Metrics/AbcSize
169
181
  # rubocop: enable Metrics/CyclomaticComplexity
170
182
  # rubocop: enable Metrics/MethodLength
171
183
  # rubocop: enable Metrics/PerceivedComplexity
172
184
  end
173
185
  end
186
+ # rubocop: enable Metrics/ClassLength
174
187
  end
175
188
  end
@@ -3,7 +3,7 @@
3
3
  module TTTLS13
4
4
  using Refinements
5
5
  module Message
6
- # https://tools.ietf.org/html/rfc8449#section-4
6
+ # https://datatracker.ietf.org/doc/html/rfc8449#section-4
7
7
  DEFAULT_RECORD_SIZE_LIMIT = 2**14 + 1
8
8
 
9
9
  # rubocop: disable Metrics/ClassLength
@@ -17,7 +17,8 @@ module TTTLS13
17
17
  ExtensionType::COOKIE,
18
18
  ExtensionType::PASSWORD_SALT,
19
19
  ExtensionType::SUPPORTED_VERSIONS,
20
- ExtensionType::KEY_SHARE
20
+ ExtensionType::KEY_SHARE,
21
+ ExtensionType::ENCRYPTED_CLIENT_HELLO
21
22
  ].freeze
22
23
  private_constant :APPEARABLE_HRR_EXTENSIONS
23
24
 
@@ -61,7 +62,6 @@ module TTTLS13
61
62
  @cipher_suite = cipher_suite
62
63
  @legacy_compression_method = legacy_compression_method
63
64
  @extensions = extensions
64
- @hrr = (random == HRR_RANDOM)
65
65
  end
66
66
  # rubocop: enable Metrics/ParameterLists
67
67
 
@@ -108,10 +108,8 @@ module TTTLS13
108
108
  exs_bin = binary.slice(i, exs_len)
109
109
  if random == HRR_RANDOM
110
110
  msg_type = HandshakeType::HELLO_RETRY_REQUEST
111
- @hrr = true
112
111
  else
113
112
  msg_type = HandshakeType::SERVER_HELLO
114
- @hrr = false
115
113
  end
116
114
  extensions = Extensions.deserialize(exs_bin, msg_type)
117
115
  i += exs_len
@@ -132,7 +130,7 @@ module TTTLS13
132
130
 
133
131
  # @return [Boolean]
134
132
  def hrr?
135
- @hrr
133
+ @random == HRR_RANDOM
136
134
  end
137
135
 
138
136
  # @return [Boolean]
@@ -27,7 +27,7 @@ module TTTLS13
27
27
  HELLO_VERIFY_REQUEST = "\x03" # RESERVED
28
28
  NEW_SESSION_TICKET = "\x04"
29
29
  END_OF_EARLY_DATA = "\x05"
30
- HELLO_RETRY_REQUEST = "\x06" # RESERVED
30
+ HELLO_RETRY_REQUEST = "\x06"
31
31
  ENCRYPTED_EXTENSIONS = "\x08"
32
32
  CERTIFICATE = "\x0b"
33
33
  SERVER_KEY_EXCHANGE = "\x0c" # RESERVED
@@ -72,6 +72,8 @@ module TTTLS13
72
72
  POST_HANDSHAKE_AUTH = "\x00\x31"
73
73
  SIGNATURE_ALGORITHMS_CERT = "\x00\x32"
74
74
  KEY_SHARE = "\x00\x33"
75
+ # https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-17#section-11.1
76
+ ENCRYPTED_CLIENT_HELLO = "\xfe\x0d"
75
77
  end
76
78
 
77
79
  DEFINED_EXTENSIONS = ExtensionType.constants.map do |c|
@@ -64,7 +64,7 @@ module TTTLS13
64
64
  # secp384r1 | | NIST P-384
65
65
  # secp521r1 | | NIST P-521
66
66
  #
67
- # https://tools.ietf.org/html/rfc4492#appendix-A
67
+ # https://datatracker.ietf.org/doc/html/rfc4492#appendix-A
68
68
  #
69
69
  # @param groups [Array of TTTLS13::Message::Extension::NamedGroup]
70
70
  #
@@ -136,7 +136,7 @@ module TTTLS13
136
136
  # v
137
137
  # CONNECTED
138
138
  #
139
- # https://tools.ietf.org/html/rfc8446#appendix-A.2
139
+ # https://datatracker.ietf.org/doc/html/rfc8446#appendix-A.2
140
140
  #
141
141
  # rubocop: disable Metrics/AbcSize
142
142
  # rubocop: disable Metrics/BlockLength
@@ -323,7 +323,7 @@ module TTTLS13
323
323
  transcript[CH].first.random,
324
324
  key_schedule.client_application_traffic_secret
325
325
  )
326
- @exporter_master_secret = key_schedule.exporter_master_secret
326
+ @exporter_secret = key_schedule.exporter_secret
327
327
  @state = ServerState::CONNECTED
328
328
  when ServerState::CONNECTED
329
329
  logger.debug('ServerState::CONNECTED')
@@ -38,6 +38,14 @@ module TTTLS13
38
38
 
39
39
  [self >> 32, self].pack('N2')
40
40
  end
41
+
42
+ def zeros
43
+ if positive?
44
+ "\x00" * self
45
+ else
46
+ ''
47
+ end
48
+ end
41
49
  end
42
50
 
43
51
  refine String do
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTTLS13
4
- VERSION = '0.2.18'
4
+ VERSION = '0.3.0'
5
5
  end
data/lib/tttls1.3.rb CHANGED
@@ -5,6 +5,9 @@ require 'net/http'
5
5
  require 'pp'
6
6
  require 'logger'
7
7
 
8
+ require 'ech_config'
9
+ require 'hpke'
10
+
8
11
  require 'tttls1.3/version'
9
12
  require 'tttls1.3/utils'
10
13
  require 'tttls1.3/logging'
@@ -18,6 +21,7 @@ require 'tttls1.3/key_schedule'
18
21
  require 'tttls1.3/message'
19
22
  require 'tttls1.3/sequence_number'
20
23
  require 'tttls1.3/sslkeylogfile'
24
+ require 'tttls1.3/hpke'
21
25
  require 'tttls1.3/connection'
22
26
  require 'tttls1.3/client'
23
27
  require 'tttls1.3/server'
data/spec/client_spec.rb CHANGED
@@ -270,4 +270,44 @@ RSpec.describe Client do
270
270
  'SHA256')).to eq TESTBINARY_0_RTT_PSK
271
271
  end
272
272
  end
273
+
274
+ context 'EncodedClientHelloInner length' do
275
+ let(:server_name) do
276
+ 'localhost'
277
+ end
278
+
279
+ let(:client) do
280
+ Client.new(nil, server_name)
281
+ end
282
+
283
+ let(:maximum_name_length) do
284
+ 0
285
+ end
286
+
287
+ let(:encoded) do
288
+ extensions, = client.send(:gen_ch_extensions)
289
+ inner_ech = Message::Extension::ECHClientHello.new_inner
290
+ Message::ClientHello.new(
291
+ legacy_session_id: '',
292
+ cipher_suites: CipherSuites.new(DEFAULT_CH_CIPHER_SUITES),
293
+ extensions: extensions.merge(
294
+ Message::ExtensionType::ENCRYPTED_CLIENT_HELLO => inner_ech
295
+ )
296
+ )
297
+ end
298
+
299
+ let(:padding_encoded_ch_inner) do
300
+ client.send(
301
+ :padding_encoded_ch_inner,
302
+ encoded.serialize[4..],
303
+ server_name.length,
304
+ maximum_name_length
305
+ )
306
+ end
307
+
308
+ it 'should be equal placeholder_encoded_ch_inner_len' do
309
+ expect(client.send(:placeholder_encoded_ch_inner_len))
310
+ .to eq padding_encoded_ch_inner.length
311
+ end
312
+ end
273
313
  end
@@ -6,13 +6,28 @@ require_relative 'spec_helper'
6
6
  RSpec.describe Connection do
7
7
  context 'connection, Simple 1-RTT Handshake,' do
8
8
  let(:key) do
9
- rsa = OpenSSL::PKey::RSA.new
10
- rsa.set_key(OpenSSL::BN.new(TESTBINARY_PKEY_MODULUS, 2),
11
- OpenSSL::BN.new(TESTBINARY_PKEY_PUBLIC_EXPONENT, 2),
12
- OpenSSL::BN.new(TESTBINARY_PKEY_PRIVATE_EXPONENT, 2))
13
- rsa.set_factors(OpenSSL::BN.new(TESTBINARY_PKEY_PRIME1, 2),
14
- OpenSSL::BN.new(TESTBINARY_PKEY_PRIME2, 2))
15
- rsa
9
+ n = OpenSSL::BN.new(TESTBINARY_PKEY_MODULUS, 2)
10
+ e = OpenSSL::BN.new(TESTBINARY_PKEY_PUBLIC_EXPONENT, 2)
11
+ d = OpenSSL::BN.new(TESTBINARY_PKEY_PRIVATE_EXPONENT, 2)
12
+ p = OpenSSL::BN.new(TESTBINARY_PKEY_PRIME1, 2)
13
+ q = OpenSSL::BN.new(TESTBINARY_PKEY_PRIME2, 2)
14
+ dmp1 = d % (p - 1.to_bn)
15
+ dmq1 = d % (q - 1.to_bn)
16
+ iqmp = q**-1.to_bn % p
17
+ asn1 = OpenSSL::ASN1::Sequence(
18
+ [
19
+ OpenSSL::ASN1::Integer(0),
20
+ OpenSSL::ASN1::Integer(n),
21
+ OpenSSL::ASN1::Integer(e),
22
+ OpenSSL::ASN1::Integer(d),
23
+ OpenSSL::ASN1::Integer(p),
24
+ OpenSSL::ASN1::Integer(q),
25
+ OpenSSL::ASN1::Integer(dmp1),
26
+ OpenSSL::ASN1::Integer(dmq1),
27
+ OpenSSL::ASN1::Integer(iqmp)
28
+ ]
29
+ )
30
+ OpenSSL::PKey::RSA.new(asn1)
16
31
  end
17
32
 
18
33
  let(:ct) do
data/spec/ech_spec.rb ADDED
@@ -0,0 +1,81 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe ECHClientHello do
8
+ context 'valid ECHClientHello outer binary' do
9
+ let(:extension) do
10
+ ECHClientHello.deserialize(TESTBINARY_ECH_OUTER)
11
+ end
12
+
13
+ it 'should generate valid object' do
14
+ expect(extension.extension_type)
15
+ .to eq ExtensionType::ENCRYPTED_CLIENT_HELLO
16
+ expect(extension.type).to eq ECHClientHelloType::OUTER
17
+ expect(extension.cipher_suite.kdf_id.uint16).to eq 1
18
+ expect(extension.cipher_suite.aead_id.uint16).to eq 1
19
+ expect(extension.config_id).to eq 32
20
+ expect(extension.enc.length).to eq 32
21
+ expect(extension.payload.length).to eq 239
22
+ end
23
+
24
+ it 'should be serialized' do
25
+ expect(extension.serialize)
26
+ .to eq ExtensionType::ENCRYPTED_CLIENT_HELLO \
27
+ + 281.to_uint16 \
28
+ + ECHClientHelloType::OUTER \
29
+ + 1.to_uint16 \
30
+ + 1.to_uint16 \
31
+ + 32.to_uint8 \
32
+ + extension.enc.prefix_uint16_length \
33
+ + extension.payload.prefix_uint16_length
34
+ end
35
+ end
36
+
37
+ context 'valid ECHClientHello inner binary' do
38
+ let(:extension) do
39
+ ECHClientHello.deserialize(TESTBINARY_ECH_INNER)
40
+ end
41
+
42
+ it 'should generate valid object' do
43
+ expect(extension.extension_type)
44
+ .to eq ExtensionType::ENCRYPTED_CLIENT_HELLO
45
+ expect(extension.type).to eq ECHClientHelloType::INNER
46
+ end
47
+
48
+ it 'should be serialized' do
49
+ expect(extension.serialize)
50
+ .to eq ExtensionType::ENCRYPTED_CLIENT_HELLO \
51
+ + 1.to_uint16 \
52
+ + ECHClientHelloType::INNER \
53
+ end
54
+ end
55
+
56
+ context 'valid ECHEncryptedExtensions binary' do
57
+ let(:extension) do
58
+ ECHEncryptedExtensions.deserialize(TESTBINARY_ECH_EE)
59
+ end
60
+
61
+ it 'should generate valid object' do
62
+ expect(extension.extension_type)
63
+ .to eq ExtensionType::ENCRYPTED_CLIENT_HELLO
64
+ expect(extension.retry_configs.is_a?(Array)).to be_truthy
65
+ expect(extension.retry_configs.length).to eq 1
66
+ expect(extension.retry_configs.first.is_a?(ECHConfig)).to be_truthy
67
+ end
68
+ end
69
+
70
+ context 'valid ECHHelloRetryRequest binary' do
71
+ let(:extension) do
72
+ ECHHelloRetryRequest.deserialize(TESTBINARY_ECH_HRR)
73
+ end
74
+
75
+ it 'should generate valid object' do
76
+ expect(extension.extension_type)
77
+ .to eq ExtensionType::ENCRYPTED_CLIENT_HELLO
78
+ expect(extension.confirmation).to eq "\x00" * 8
79
+ end
80
+ end
81
+ end
@@ -35,8 +35,7 @@ RSpec.describe Extensions do
35
35
  end
36
36
 
37
37
  let(:key_share) do
38
- ec = OpenSSL::PKey::EC.new('prime256v1')
39
- ec.generate_key!
38
+ ec = OpenSSL::PKey::EC.generate('prime256v1')
40
39
  KeyShare.new(
41
40
  msg_type: HandshakeType::CLIENT_HELLO,
42
41
  key_share_entry: [
@@ -37,9 +37,9 @@ RSpec.describe KeySchedule do
37
37
  .to eq TESTBINARY_C_AP_TRAFFIC
38
38
  expect(key_schedule.server_application_traffic_secret)
39
39
  .to eq TESTBINARY_S_AP_TRAFFIC
40
- expect(key_schedule.exporter_master_secret)
40
+ expect(key_schedule.exporter_secret)
41
41
  .to eq TESTBINARY_EXP_MASTER
42
- expect(key_schedule.resumption_master_secret)
42
+ expect(key_schedule.resumption_secret)
43
43
  .to eq TESTBINARY_RES_MASTER
44
44
  end
45
45
 
data/spec/server_spec.rb CHANGED
@@ -109,13 +109,28 @@ RSpec.describe Server do
109
109
 
110
110
  context 'server' do
111
111
  let(:key) do
112
- rsa = OpenSSL::PKey::RSA.new
113
- rsa.set_key(OpenSSL::BN.new(TESTBINARY_PKEY_MODULUS, 2),
114
- OpenSSL::BN.new(TESTBINARY_PKEY_PUBLIC_EXPONENT, 2),
115
- OpenSSL::BN.new(TESTBINARY_PKEY_PRIVATE_EXPONENT, 2))
116
- rsa.set_factors(OpenSSL::BN.new(TESTBINARY_PKEY_PRIME1, 2),
117
- OpenSSL::BN.new(TESTBINARY_PKEY_PRIME2, 2))
118
- rsa
112
+ n = OpenSSL::BN.new(TESTBINARY_PKEY_MODULUS, 2)
113
+ e = OpenSSL::BN.new(TESTBINARY_PKEY_PUBLIC_EXPONENT, 2)
114
+ d = OpenSSL::BN.new(TESTBINARY_PKEY_PRIVATE_EXPONENT, 2)
115
+ p = OpenSSL::BN.new(TESTBINARY_PKEY_PRIME1, 2)
116
+ q = OpenSSL::BN.new(TESTBINARY_PKEY_PRIME2, 2)
117
+ dmp1 = d % (p - 1.to_bn)
118
+ dmq1 = d % (q - 1.to_bn)
119
+ iqmp = q**-1.to_bn % p
120
+ asn1 = OpenSSL::ASN1::Sequence(
121
+ [
122
+ OpenSSL::ASN1::Integer(0),
123
+ OpenSSL::ASN1::Integer(n),
124
+ OpenSSL::ASN1::Integer(e),
125
+ OpenSSL::ASN1::Integer(d),
126
+ OpenSSL::ASN1::Integer(p),
127
+ OpenSSL::ASN1::Integer(q),
128
+ OpenSSL::ASN1::Integer(dmp1),
129
+ OpenSSL::ASN1::Integer(dmq1),
130
+ OpenSSL::ASN1::Integer(iqmp)
131
+ ]
132
+ )
133
+ OpenSSL::PKey::RSA.new(asn1)
119
134
  end
120
135
 
121
136
  let(:ct) do
data/spec/spec_helper.rb CHANGED
@@ -167,7 +167,7 @@ TESTBINARY_COMPRESS_CERTIFICATE = <<BIN.split.map(&:hex).map(&:chr).join
167
167
  02 00 01
168
168
  BIN
169
169
 
170
- # https://tools.ietf.org/html/rfc8448#section-3
170
+ # https://datatracker.ietf.org/doc/html/rfc8448#section-3
171
171
  # 2. Private Keys
172
172
  TESTBINARY_PKEY_MODULUS = <<BIN.split.map(&:hex).map(&:chr).join
173
173
  b4 bb 49 8f 82 79 30 3d 98 08 36 39 9b 36 c6 98
@@ -209,7 +209,43 @@ TESTBINARY_PKEY_PRIVATE_EXPONENT = <<BIN.split.map(&:hex).map(&:chr).join
209
209
  c3 08 8d f2 5a e6 79 23 3d f8 a3 bd a2 ff 99 41
210
210
  BIN
211
211
 
212
- # https://tools.ietf.org/html/rfc8448#section-3
212
+ TESTBINARY_ECH_OUTER = <<BIN.split.map(&:hex).map(&:chr).join
213
+ 00 00 01 00 01 20 00 20 00 01 02 03 04 05 06 07
214
+ 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17
215
+ 18 19 1a 1b 1c 1d 1e 1f 00 ef 00 01 02 03 04 05
216
+ 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15
217
+ 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
218
+ 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35
219
+ 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45
220
+ 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55
221
+ 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65
222
+ 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75
223
+ 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85
224
+ 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95
225
+ 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5
226
+ a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5
227
+ b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5
228
+ c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5
229
+ d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5
230
+ e6 e7 e8 e9 ea eb ec ed ee
231
+ BIN
232
+
233
+ TESTBINARY_ECH_INNER = <<BIN.split.map(&:hex).map(&:chr).join
234
+ 01
235
+ BIN
236
+
237
+ TESTBINARY_ECH_EE = <<BIN.split.map(&:hex).map(&:chr).join
238
+ 00 3a fe 0d 00 36 00 00 20 00 1e 00 00 00 00 00
239
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
240
+ 00 00 00 00 00 00 00 00 00 00 04 00 01 00 01 00
241
+ 09 6c 6f 63 61 6c 68 6f 73 74 00 00
242
+ BIN
243
+
244
+ TESTBINARY_ECH_HRR = <<BIN.split.map(&:hex).map(&:chr).join
245
+ 00 00 00 00 00 00 00 00
246
+ BIN
247
+
248
+ # https://datatracker.ietf.org/doc/html/rfc8448#section-3
213
249
  # 3. Simple 1-RTT Handshake
214
250
  TESTBINARY_CLIENT_HELLO = <<BIN.split.map(&:hex).map(&:chr).join
215
251
  01 00 00 c0 03 03 cb 34 ec b1 e7 81 63 ba 1c 38
@@ -517,7 +553,7 @@ TESTBINARY_CH_CF_TRANSCRIPT_HASH = <<BIN.split.map(&:hex).map(&:chr).join
517
553
  84 65 8d 60 49 e8 64 29 42 6d b8 7c 54 ad 14 3d
518
554
  BIN
519
555
 
520
- # https://tools.ietf.org/html/rfc8448#section-4
556
+ # https://datatracker.ietf.org/doc/html/rfc8448#section-4
521
557
  # 4. Resumed 0-RTT Handshake
522
558
  TESTBINARY_0_RTT_CLIENT_HELLO = <<BIN.split.map(&:hex).map(&:chr).join
523
559
  01 00 01 fc 03 03 1b c3 ce b6 bb e3 9c ff 93 83
@@ -642,7 +678,7 @@ BIN
642
678
  TESTBINARY_0_RTT_CLIENT_APPLICATION_WRITE_IV \
643
679
  = testbinary.split.map(&:hex).map(&:chr).join
644
680
 
645
- # https://tools.ietf.org/html/rfc8448#section-5
681
+ # https://datatracker.ietf.org/doc/html/rfc8448#section-5
646
682
  # 5. HelloRetryRequest
647
683
  TESTBINARY_HRR_CLIENT_HELLO1 = <<BIN.split.map(&:hex).map(&:chr).join
648
684
  01 00 00 b0 03 03 b0 b1 c5 a5 aa 37 c5 91 9f 2e
@@ -939,7 +975,7 @@ TESTBINARY_HRR_CH1_CF_TRANSCRIPT_HASH = <<BIN.split.map(&:hex).map(&:chr).join
939
975
  3c aa 6e 48 3c 6c 65 df 53 15 18 88 e5 01 65 f4
940
976
  BIN
941
977
 
942
- # https://tools.ietf.org/html/rfc8448#section-7
978
+ # https://datatracker.ietf.org/doc/html/rfc8448#section-7
943
979
  # 7. Compatibility Mode
944
980
  TESTBINARY_RECORD_CCS = <<BIN.split.map(&:hex).map(&:chr).join
945
981
  14 03 03 00 01 01
data/tttls1.3.gemspec CHANGED
@@ -20,6 +20,8 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ['lib']
21
21
 
22
22
  spec.add_development_dependency 'bundler', '~> 2.0'
23
+ spec.add_dependency 'ech_config', '~> 0.0.3'
24
+ spec.add_dependency 'hpke'
23
25
  spec.add_dependency 'logger'
24
26
  spec.add_dependency 'openssl'
25
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tttls1.3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.18
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thekuwayama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-18 00:00:00.000000000 Z
11
+ date: 2023-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ech_config
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: hpke
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: logger
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -72,14 +100,18 @@ files:
72
100
  - example/helper.rb
73
101
  - example/https_client.rb
74
102
  - example/https_client_using_0rtt.rb
103
+ - example/https_client_using_ech.rb
104
+ - example/https_client_using_grease_ech.rb
105
+ - example/https_client_using_grease_psk.rb
75
106
  - example/https_client_using_hrr.rb
107
+ - example/https_client_using_hrr_and_ech.rb
76
108
  - example/https_client_using_hrr_and_ticket.rb
77
109
  - example/https_client_using_status_request.rb
78
110
  - example/https_client_using_ticket.rb
79
111
  - example/https_server.rb
80
112
  - interop/client_spec.rb
81
- - interop/helper.rb
82
113
  - interop/server_spec.rb
114
+ - interop/spec_helper.rb
83
115
  - lib/tttls1.3.rb
84
116
  - lib/tttls1.3/cipher_suites.rb
85
117
  - lib/tttls1.3/client.rb
@@ -88,6 +120,7 @@ files:
88
120
  - lib/tttls1.3/cryptograph/aead.rb
89
121
  - lib/tttls1.3/cryptograph/passer.rb
90
122
  - lib/tttls1.3/error.rb
123
+ - lib/tttls1.3/hpke.rb
91
124
  - lib/tttls1.3/key_schedule.rb
92
125
  - lib/tttls1.3/logging.rb
93
126
  - lib/tttls1.3/message.rb
@@ -104,6 +137,7 @@ files:
104
137
  - lib/tttls1.3/message/extension/compress_certificate.rb
105
138
  - lib/tttls1.3/message/extension/cookie.rb
106
139
  - lib/tttls1.3/message/extension/early_data_indication.rb
140
+ - lib/tttls1.3/message/extension/ech.rb
107
141
  - lib/tttls1.3/message/extension/key_share.rb
108
142
  - lib/tttls1.3/message/extension/pre_shared_key.rb
109
143
  - lib/tttls1.3/message/extension/psk_key_exchange_modes.rb
@@ -142,6 +176,7 @@ files:
142
176
  - spec/connection_spec.rb
143
177
  - spec/cookie_spec.rb
144
178
  - spec/early_data_indication_spec.rb
179
+ - spec/ech_spec.rb
145
180
  - spec/encrypted_extensions_spec.rb
146
181
  - spec/end_of_early_data_spec.rb
147
182
  - spec/error_spec.rb
@@ -219,6 +254,7 @@ test_files:
219
254
  - spec/connection_spec.rb
220
255
  - spec/cookie_spec.rb
221
256
  - spec/early_data_indication_spec.rb
257
+ - spec/ech_spec.rb
222
258
  - spec/encrypted_extensions_spec.rb
223
259
  - spec/end_of_early_data_spec.rb
224
260
  - spec/error_spec.rb