tttls1.3 0.2.19 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.19'
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
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
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.19
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: 2023-01-28 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,7 +100,11 @@ 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
@@ -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