tttls1.3 0.3.1 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/Gemfile +1 -0
- data/example/helper.rb +43 -0
- data/example/https_client_using_0rtt.rb +5 -3
- data/example/https_client_using_ech.rb +6 -7
- data/example/https_client_using_grease_ech.rb +0 -2
- data/example/https_client_using_hrr.rb +2 -1
- data/example/https_client_using_hrr_and_ech.rb +6 -7
- data/example/https_client_using_hrr_and_ticket.rb +4 -2
- data/example/https_client_using_status_request.rb +2 -1
- data/example/https_client_using_ticket.rb +4 -2
- data/example/https_client_using_ticket_and_ech.rb +57 -0
- data/example/https_server.rb +14 -1
- data/lib/tttls1.3/client.rb +205 -418
- data/lib/tttls1.3/connection.rb +21 -362
- data/lib/tttls1.3/ech.rb +426 -0
- data/lib/tttls1.3/endpoint.rb +276 -0
- data/lib/tttls1.3/message/certificate_verify.rb +1 -1
- data/lib/tttls1.3/message/extension/ech.rb +21 -24
- data/lib/tttls1.3/message/extension/ech_outer_extensions.rb +52 -0
- data/lib/tttls1.3/message/extension/signature_algorithms.rb +2 -2
- data/lib/tttls1.3/message/extension/supported_versions.rb +3 -3
- data/lib/tttls1.3/message/extension/unknown_extension.rb +2 -2
- data/lib/tttls1.3/message/extensions.rb +30 -0
- data/lib/tttls1.3/message.rb +1 -0
- data/lib/tttls1.3/server.rb +125 -63
- data/lib/tttls1.3/utils.rb +37 -0
- data/lib/tttls1.3/version.rb +1 -1
- data/lib/tttls1.3.rb +2 -1
- data/spec/client_spec.rb +21 -60
- data/spec/ech_outer_extensions_spec.rb +42 -0
- data/spec/ech_spec.rb +41 -0
- data/spec/{connection_spec.rb → endpoint_spec.rb} +41 -49
- data/spec/extensions_spec.rb +65 -0
- data/spec/server_spec.rb +12 -12
- data/spec/spec_helper.rb +4 -0
- metadata +11 -6
- data/lib/tttls1.3/hpke.rb +0 -91
data/lib/tttls1.3/version.rb
CHANGED
data/lib/tttls1.3.rb
CHANGED
@@ -21,7 +21,8 @@ require 'tttls1.3/key_schedule'
|
|
21
21
|
require 'tttls1.3/message'
|
22
22
|
require 'tttls1.3/sequence_number'
|
23
23
|
require 'tttls1.3/sslkeylogfile'
|
24
|
-
require 'tttls1.3/
|
24
|
+
require 'tttls1.3/ech'
|
25
25
|
require 'tttls1.3/connection'
|
26
|
+
require 'tttls1.3/endpoint'
|
26
27
|
require 'tttls1.3/client'
|
27
28
|
require 'tttls1.3/server'
|
data/spec/client_spec.rb
CHANGED
@@ -129,10 +129,11 @@ RSpec.describe Client do
|
|
129
129
|
client = Client.new(mock_socket, 'localhost')
|
130
130
|
digest = CipherSuite.digest(cipher_suite)
|
131
131
|
hash = transcript.hash(digest, EOED)
|
132
|
-
signature =
|
133
|
-
|
134
|
-
|
135
|
-
|
132
|
+
signature = Endpoint.sign_finished(
|
133
|
+
digest: digest,
|
134
|
+
finished_key: finished_key,
|
135
|
+
hash: hash
|
136
|
+
)
|
136
137
|
hs_wcipher = Cryptograph::Aead.new(
|
137
138
|
cipher_suite: cipher_suite,
|
138
139
|
write_key: TESTBINARY_CLIENT_FINISHED_WRITE_KEY,
|
@@ -215,20 +216,22 @@ RSpec.describe Client do
|
|
215
216
|
it 'should verify server Finished' do
|
216
217
|
digest = CipherSuite.digest(cipher_suite)
|
217
218
|
hash = transcript.hash(digest, CV)
|
218
|
-
expect(
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
219
|
+
expect(Endpoint.verified_finished?(
|
220
|
+
finished: sf,
|
221
|
+
digest: digest,
|
222
|
+
finished_key: key_schedule.server_finished_key,
|
223
|
+
hash: hash
|
224
|
+
)).to be true
|
223
225
|
end
|
224
226
|
|
225
227
|
it 'should sign client Finished' do
|
226
228
|
digest = CipherSuite.digest(cipher_suite)
|
227
229
|
hash = transcript.hash(digest, EOED)
|
228
|
-
expect(
|
229
|
-
|
230
|
-
|
231
|
-
|
230
|
+
expect(Endpoint.sign_finished(
|
231
|
+
digest: digest,
|
232
|
+
finished_key: key_schedule.client_finished_key,
|
233
|
+
hash: hash
|
234
|
+
)).to eq cf.verify_data
|
232
235
|
end
|
233
236
|
end
|
234
237
|
|
@@ -240,18 +243,16 @@ RSpec.describe Client do
|
|
240
243
|
Certificate.new(certificate_list: [CertificateEntry.new(server_crt)])
|
241
244
|
end
|
242
245
|
|
243
|
-
let(:client) do
|
244
|
-
Client.new(nil, 'localhost')
|
245
|
-
end
|
246
|
-
|
247
246
|
it 'should not certify certificate' do
|
248
|
-
expect(
|
247
|
+
expect(Endpoint.trusted_certificate?(certificate.certificate_list))
|
249
248
|
.to be false
|
250
249
|
end
|
251
250
|
|
252
251
|
it 'should certify certificate, received path to private ca.crt' do
|
253
|
-
expect(
|
254
|
-
|
252
|
+
expect(Endpoint.trusted_certificate?(
|
253
|
+
certificate.certificate_list,
|
254
|
+
__dir__ + '/fixtures/rsa_ca.crt'
|
255
|
+
)).to be true
|
255
256
|
end
|
256
257
|
end
|
257
258
|
|
@@ -270,44 +271,4 @@ RSpec.describe Client do
|
|
270
271
|
'SHA256')).to eq TESTBINARY_0_RTT_PSK
|
271
272
|
end
|
272
273
|
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
|
313
274
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'spec_helper'
|
5
|
+
using Refinements
|
6
|
+
|
7
|
+
RSpec.describe ECHOuterExtensions do
|
8
|
+
context 'valid ech_outer_extensions, [key_share]' do
|
9
|
+
let(:extension) do
|
10
|
+
ECHOuterExtensions.new([ExtensionType::KEY_SHARE])
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should be generated' do
|
14
|
+
expect(extension.extension_type).to eq ExtensionType::ECH_OUTER_EXTENSIONS
|
15
|
+
expect(extension.outer_extensions).to eq [ExtensionType::KEY_SHARE]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should be serialized' do
|
19
|
+
expect(extension.serialize).to eq ExtensionType::ECH_OUTER_EXTENSIONS \
|
20
|
+
+ 3.to_uint16 \
|
21
|
+
+ 2.to_uint8 \
|
22
|
+
+ ExtensionType::KEY_SHARE
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'valid ech_outer_extensions binary' do
|
27
|
+
let(:extension) do
|
28
|
+
ECHOuterExtensions.deserialize(TESTBINARY_ECH_OUTER_EXTENSIONS)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should generate valid object' do
|
32
|
+
expect(extension.extension_type).to be ExtensionType::ECH_OUTER_EXTENSIONS
|
33
|
+
expect(extension.outer_extensions).to eq [ExtensionType::KEY_SHARE]
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should generate serializable object' do
|
37
|
+
expect(extension.serialize)
|
38
|
+
.to eq ExtensionType::ECH_OUTER_EXTENSIONS \
|
39
|
+
+ TESTBINARY_ECH_OUTER_EXTENSIONS.prefix_uint16_length
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/ech_spec.rb
CHANGED
@@ -79,3 +79,44 @@ RSpec.describe ECHClientHello do
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
82
|
+
|
83
|
+
RSpec.describe Ech do
|
84
|
+
context 'EncodedClientHelloInner length' do
|
85
|
+
let(:server_name) do
|
86
|
+
'localhost'
|
87
|
+
end
|
88
|
+
|
89
|
+
let(:client) do
|
90
|
+
Client.new(nil, server_name)
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:maximum_name_length) do
|
94
|
+
0
|
95
|
+
end
|
96
|
+
|
97
|
+
let(:encoded) do
|
98
|
+
extensions, = client.send(:gen_ch_extensions)
|
99
|
+
inner_ech = Message::Extension::ECHClientHello.new_inner
|
100
|
+
Message::ClientHello.new(
|
101
|
+
legacy_session_id: '',
|
102
|
+
cipher_suites: CipherSuites.new(DEFAULT_CH_CIPHER_SUITES),
|
103
|
+
extensions: extensions.merge(
|
104
|
+
Message::ExtensionType::ENCRYPTED_CLIENT_HELLO => inner_ech
|
105
|
+
)
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
let(:padding_encoded_ch_inner) do
|
110
|
+
Ech.padding_encoded_ch_inner(
|
111
|
+
encoded.serialize[4..],
|
112
|
+
server_name.length,
|
113
|
+
maximum_name_length
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should be equal placeholder_encoded_ch_inner_len' do
|
118
|
+
expect(Ech.placeholder_encoded_ch_inner_len)
|
119
|
+
.to eq padding_encoded_ch_inner.length
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -3,8 +3,8 @@
|
|
3
3
|
|
4
4
|
require_relative 'spec_helper'
|
5
5
|
|
6
|
-
RSpec.describe
|
7
|
-
context '
|
6
|
+
RSpec.describe Endpoint do
|
7
|
+
context 'endpoint, Simple 1-RTT Handshake,' do
|
8
8
|
let(:key) do
|
9
9
|
n = OpenSSL::BN.new(TESTBINARY_PKEY_MODULUS, 2)
|
10
10
|
e = OpenSSL::BN.new(TESTBINARY_PKEY_PUBLIC_EXPONENT, 2)
|
@@ -66,39 +66,35 @@ RSpec.describe Connection do
|
|
66
66
|
CipherSuite.digest(CipherSuite::TLS_AES_128_GCM_SHA256)
|
67
67
|
end
|
68
68
|
|
69
|
-
let(:connection) do
|
70
|
-
Connection.new(nil)
|
71
|
-
end
|
72
|
-
|
73
69
|
it 'should verify server CertificateVerify.signature' do
|
74
70
|
public_key = ct.certificate_list.first.cert_data.public_key
|
75
71
|
signature_scheme = cv.signature_scheme
|
76
72
|
signature = cv.signature
|
77
73
|
|
78
|
-
expect(
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
74
|
+
expect(Endpoint.verified_certificate_verify?(
|
75
|
+
public_key: public_key,
|
76
|
+
signature_scheme: signature_scheme,
|
77
|
+
signature: signature,
|
78
|
+
context: 'TLS 1.3, server CertificateVerify',
|
79
|
+
hash: transcript.hash(digest, CT)
|
80
|
+
)).to be true
|
85
81
|
end
|
86
82
|
|
87
83
|
it 'should sign client Finished.verify_data' do
|
88
|
-
expect(
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
84
|
+
expect(Endpoint.sign_finished(
|
85
|
+
digest: 'SHA256',
|
86
|
+
finished_key: TESTBINARY_CLIENT_FINISHED_KEY,
|
87
|
+
hash: transcript.hash(digest, EOED)
|
88
|
+
)).to eq cf.verify_data
|
93
89
|
end
|
94
90
|
|
95
91
|
it 'should verify server Finished.verify_data' do
|
96
|
-
expect(
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
92
|
+
expect(Endpoint.verified_finished?(
|
93
|
+
finished: sf,
|
94
|
+
digest: 'SHA256',
|
95
|
+
finished_key: TESTBINARY_SERVER_FINISHED_KEY,
|
96
|
+
hash: transcript.hash(digest, CV)
|
97
|
+
)).to be true
|
102
98
|
end
|
103
99
|
|
104
100
|
it 'should sign server CertificateVerify.signature' do
|
@@ -107,23 +103,23 @@ RSpec.describe Connection do
|
|
107
103
|
|
108
104
|
# used RSASSA-PSS signature_scheme, salt is a random sequence.
|
109
105
|
# CertificateVerify.signature is random.
|
110
|
-
signature =
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
expect(
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
106
|
+
signature = Endpoint.sign_certificate_verify(
|
107
|
+
key: key,
|
108
|
+
signature_scheme: signature_scheme,
|
109
|
+
context: 'TLS 1.3, server CertificateVerify',
|
110
|
+
hash: transcript.hash(digest, CT)
|
111
|
+
)
|
112
|
+
expect(Endpoint.verified_certificate_verify?(
|
113
|
+
public_key: public_key,
|
114
|
+
signature_scheme: signature_scheme,
|
115
|
+
signature: signature,
|
116
|
+
context: 'TLS 1.3, server CertificateVerify',
|
117
|
+
hash: transcript.hash(digest, CT)
|
118
|
+
)).to be true
|
123
119
|
end
|
124
120
|
end
|
125
121
|
|
126
|
-
context '
|
122
|
+
context 'endpoint, HelloRetryRequest,' do
|
127
123
|
let(:ct) do
|
128
124
|
Certificate.deserialize(TESTBINARY_HRR_CERTIFICATE)
|
129
125
|
end
|
@@ -154,22 +150,18 @@ RSpec.describe Connection do
|
|
154
150
|
CipherSuite.digest(CipherSuite::TLS_AES_128_GCM_SHA256)
|
155
151
|
end
|
156
152
|
|
157
|
-
let(:connection) do
|
158
|
-
Connection.new(nil)
|
159
|
-
end
|
160
|
-
|
161
153
|
it 'should verify server CertificateVerify.signature' do
|
162
154
|
public_key = ct.certificate_list.first.cert_data.public_key
|
163
155
|
signature_scheme = cv.signature_scheme
|
164
156
|
signature = cv.signature
|
165
157
|
|
166
|
-
expect(
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
158
|
+
expect(Endpoint.verified_certificate_verify?(
|
159
|
+
public_key: public_key,
|
160
|
+
signature_scheme: signature_scheme,
|
161
|
+
signature: signature,
|
162
|
+
context: 'TLS 1.3, server CertificateVerify',
|
163
|
+
hash: transcript.hash(digest, CT)
|
164
|
+
)).to be true
|
173
165
|
end
|
174
166
|
end
|
175
167
|
end
|
data/spec/extensions_spec.rb
CHANGED
@@ -182,4 +182,69 @@ RSpec.describe Extensions do
|
|
182
182
|
.to raise_error(ErrorAlerts)
|
183
183
|
end
|
184
184
|
end
|
185
|
+
|
186
|
+
context 'removing and replacing extensions from EncodedClientHelloInner' do
|
187
|
+
let(:extensions) do
|
188
|
+
extensions, = Client.new(nil, 'localhost').send(:gen_ch_extensions)
|
189
|
+
extensions
|
190
|
+
end
|
191
|
+
|
192
|
+
let(:no_key_share_exs) do
|
193
|
+
Extensions.new(
|
194
|
+
extensions.filter { |k, _| k != ExtensionType::KEY_SHARE }.values
|
195
|
+
)
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'should be equal remove_and_replace! with []' do
|
199
|
+
expected = extensions.clone
|
200
|
+
got = extensions.remove_and_replace!([])
|
201
|
+
|
202
|
+
expect(got.keys).to eq expected.keys
|
203
|
+
expect(got[ExtensionType::ECH_OUTER_EXTENSIONS]).to eq nil
|
204
|
+
expect(extensions.keys - got.keys).to eq []
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should be equal remove_and_replace! with [key_share]' do
|
208
|
+
expected = extensions.filter { |k, _| k != ExtensionType::KEY_SHARE }
|
209
|
+
expected[ExtensionType::ECH_OUTER_EXTENSIONS] = \
|
210
|
+
Extension::ECHOuterExtensions.new([ExtensionType::KEY_SHARE])
|
211
|
+
got = extensions.remove_and_replace!([ExtensionType::KEY_SHARE])
|
212
|
+
|
213
|
+
expect(got.keys).to eq expected.keys
|
214
|
+
expect(got[ExtensionType::ECH_OUTER_EXTENSIONS].outer_extensions)
|
215
|
+
.to eq expected[ExtensionType::ECH_OUTER_EXTENSIONS].outer_extensions
|
216
|
+
expect(extensions.keys - got.keys)
|
217
|
+
.to eq expected[ExtensionType::ECH_OUTER_EXTENSIONS].outer_extensions
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'should be equal remove_and_replace! with' \
|
221
|
+
' [key_share,supported_versions]' do
|
222
|
+
outer_extensions = [
|
223
|
+
ExtensionType::KEY_SHARE,
|
224
|
+
ExtensionType::SUPPORTED_VERSIONS
|
225
|
+
]
|
226
|
+
expected = extensions.filter { |k, _| !outer_extensions.include?(k) }
|
227
|
+
expected[ExtensionType::ECH_OUTER_EXTENSIONS] = \
|
228
|
+
Extension::ECHOuterExtensions.new(
|
229
|
+
extensions.filter { |k, _| outer_extensions.include?(k) }.keys
|
230
|
+
)
|
231
|
+
got = extensions.remove_and_replace!(outer_extensions)
|
232
|
+
|
233
|
+
expect(got.keys).to eq expected.keys
|
234
|
+
expect(got[ExtensionType::ECH_OUTER_EXTENSIONS].outer_extensions)
|
235
|
+
.to eq expected[ExtensionType::ECH_OUTER_EXTENSIONS].outer_extensions
|
236
|
+
expect(extensions.keys - got.keys)
|
237
|
+
.to eq expected[ExtensionType::ECH_OUTER_EXTENSIONS].outer_extensions
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'should be equal remove_and_replace! with no key_share extensions' \
|
241
|
+
' & [key_share]' do
|
242
|
+
expected = no_key_share_exs.clone
|
243
|
+
got = no_key_share_exs.remove_and_replace!([ExtensionType::KEY_SHARE])
|
244
|
+
|
245
|
+
expect(got).to eq expected
|
246
|
+
expect(got[ExtensionType::ECH_OUTER_EXTENSIONS]).to eq nil
|
247
|
+
expect(no_key_share_exs.keys - got.keys).to eq []
|
248
|
+
end
|
249
|
+
end
|
185
250
|
end
|
data/spec/server_spec.rb
CHANGED
@@ -174,13 +174,13 @@ RSpec.describe Server do
|
|
174
174
|
signature_scheme = cv.signature_scheme
|
175
175
|
signature = cv.signature
|
176
176
|
digest = CipherSuite.digest(cipher_suite)
|
177
|
-
expect(
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
177
|
+
expect(Endpoint.verified_certificate_verify?(
|
178
|
+
public_key: public_key,
|
179
|
+
signature_scheme: signature_scheme,
|
180
|
+
signature: signature,
|
181
|
+
context: 'TLS 1.3, server CertificateVerify',
|
182
|
+
hash: transcript.hash(digest, CT)
|
183
|
+
)).to be true
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
@@ -213,12 +213,12 @@ RSpec.describe Server do
|
|
213
213
|
end
|
214
214
|
|
215
215
|
let(:signature) do
|
216
|
-
server = Server.new(nil)
|
217
216
|
digest = CipherSuite.digest(cipher_suite)
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
217
|
+
Endpoint.sign_finished(
|
218
|
+
digest: digest,
|
219
|
+
finished_key: key_schedule.server_finished_key,
|
220
|
+
hash: transcript.hash(digest, CV)
|
221
|
+
)
|
222
222
|
end
|
223
223
|
|
224
224
|
let(:sf) do
|
data/spec/spec_helper.rb
CHANGED
@@ -245,6 +245,10 @@ TESTBINARY_ECH_HRR = <<BIN.split.map(&:hex).map(&:chr).join
|
|
245
245
|
00 00 00 00 00 00 00 00
|
246
246
|
BIN
|
247
247
|
|
248
|
+
TESTBINARY_ECH_OUTER_EXTENSIONS = <<BIN.split.map(&:hex).map(&:chr).join
|
249
|
+
02 00 33
|
250
|
+
BIN
|
251
|
+
|
248
252
|
# https://datatracker.ietf.org/doc/html/rfc8448#section-3
|
249
253
|
# 3. Simple 1-RTT Handshake
|
250
254
|
TESTBINARY_CLIENT_HELLO = <<BIN.split.map(&:hex).map(&:chr).join
|
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.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thekuwayama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -108,6 +108,7 @@ files:
|
|
108
108
|
- example/https_client_using_hrr_and_ticket.rb
|
109
109
|
- example/https_client_using_status_request.rb
|
110
110
|
- example/https_client_using_ticket.rb
|
111
|
+
- example/https_client_using_ticket_and_ech.rb
|
111
112
|
- example/https_server.rb
|
112
113
|
- interop/client_spec.rb
|
113
114
|
- interop/server_spec.rb
|
@@ -119,8 +120,9 @@ files:
|
|
119
120
|
- lib/tttls1.3/cryptograph.rb
|
120
121
|
- lib/tttls1.3/cryptograph/aead.rb
|
121
122
|
- lib/tttls1.3/cryptograph/passer.rb
|
123
|
+
- lib/tttls1.3/ech.rb
|
124
|
+
- lib/tttls1.3/endpoint.rb
|
122
125
|
- lib/tttls1.3/error.rb
|
123
|
-
- lib/tttls1.3/hpke.rb
|
124
126
|
- lib/tttls1.3/key_schedule.rb
|
125
127
|
- lib/tttls1.3/logging.rb
|
126
128
|
- lib/tttls1.3/message.rb
|
@@ -138,6 +140,7 @@ files:
|
|
138
140
|
- lib/tttls1.3/message/extension/cookie.rb
|
139
141
|
- lib/tttls1.3/message/extension/early_data_indication.rb
|
140
142
|
- lib/tttls1.3/message/extension/ech.rb
|
143
|
+
- lib/tttls1.3/message/extension/ech_outer_extensions.rb
|
141
144
|
- lib/tttls1.3/message/extension/key_share.rb
|
142
145
|
- lib/tttls1.3/message/extension/pre_shared_key.rb
|
143
146
|
- lib/tttls1.3/message/extension/psk_key_exchange_modes.rb
|
@@ -173,12 +176,13 @@ files:
|
|
173
176
|
- spec/client_hello_spec.rb
|
174
177
|
- spec/client_spec.rb
|
175
178
|
- spec/compress_certificate_spec.rb
|
176
|
-
- spec/connection_spec.rb
|
177
179
|
- spec/cookie_spec.rb
|
178
180
|
- spec/early_data_indication_spec.rb
|
181
|
+
- spec/ech_outer_extensions_spec.rb
|
179
182
|
- spec/ech_spec.rb
|
180
183
|
- spec/encrypted_extensions_spec.rb
|
181
184
|
- spec/end_of_early_data_spec.rb
|
185
|
+
- spec/endpoint_spec.rb
|
182
186
|
- spec/error_spec.rb
|
183
187
|
- spec/extensions_spec.rb
|
184
188
|
- spec/finished_spec.rb
|
@@ -235,7 +239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
235
239
|
- !ruby/object:Gem::Version
|
236
240
|
version: '0'
|
237
241
|
requirements: []
|
238
|
-
rubygems_version: 3.
|
242
|
+
rubygems_version: 3.5.3
|
239
243
|
signing_key:
|
240
244
|
specification_version: 4
|
241
245
|
summary: TLS 1.3 implementation in Ruby (Tiny Trial TLS1.3 aka tttls1.3)
|
@@ -251,12 +255,13 @@ test_files:
|
|
251
255
|
- spec/client_hello_spec.rb
|
252
256
|
- spec/client_spec.rb
|
253
257
|
- spec/compress_certificate_spec.rb
|
254
|
-
- spec/connection_spec.rb
|
255
258
|
- spec/cookie_spec.rb
|
256
259
|
- spec/early_data_indication_spec.rb
|
260
|
+
- spec/ech_outer_extensions_spec.rb
|
257
261
|
- spec/ech_spec.rb
|
258
262
|
- spec/encrypted_extensions_spec.rb
|
259
263
|
- spec/end_of_early_data_spec.rb
|
264
|
+
- spec/endpoint_spec.rb
|
260
265
|
- spec/error_spec.rb
|
261
266
|
- spec/extensions_spec.rb
|
262
267
|
- spec/finished_spec.rb
|
data/lib/tttls1.3/hpke.rb
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module TTTLS13
|
5
|
-
# NOTE: Hpke module is the adapter for ech_config using hpke-rb.
|
6
|
-
module Hpke
|
7
|
-
module KemId
|
8
|
-
# https://www.iana.org/assignments/hpke/hpke.xhtml#hpke-kem-ids
|
9
|
-
P_256_SHA256 = 0x0010
|
10
|
-
P_384_SHA384 = 0x0011
|
11
|
-
P_521_SHA512 = 0x0012
|
12
|
-
X25519_SHA256 = 0x0020
|
13
|
-
X448_SHA512 = 0x0021
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.kem_id2dhkem(kem_id)
|
17
|
-
case kem_id
|
18
|
-
when KemId::P_256_SHA256
|
19
|
-
%i[p_256 sha256]
|
20
|
-
when KemId::P_384_SHA384
|
21
|
-
%i[p_384 sha384]
|
22
|
-
when KemId::P_521_SHA512
|
23
|
-
%i[p_521 sha512]
|
24
|
-
when KemId::X25519_SHA256
|
25
|
-
%i[x25519 sha256]
|
26
|
-
when KemId::X448_SHA512
|
27
|
-
%i[x448 sha512]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.kem_curve_name2dhkem(kem_curve_name)
|
32
|
-
case kem_curve_name
|
33
|
-
when :p_256
|
34
|
-
HPKE::DHKEM::EC::P_256
|
35
|
-
when :p_384
|
36
|
-
HPKE::DHKEM::EC::P_384
|
37
|
-
when :p_521
|
38
|
-
HPKE::DHKEM::EC::P_521
|
39
|
-
when :x25519
|
40
|
-
HPKE::DHKEM::X25519
|
41
|
-
when :x448
|
42
|
-
HPKE::DHKEM::X448
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
module KdfId
|
47
|
-
# https://www.iana.org/assignments/hpke/hpke.xhtml#hpke-kdf-ids
|
48
|
-
HKDF_SHA256 = 0x0001
|
49
|
-
HKDF_SHA384 = 0x0002
|
50
|
-
HKDF_SHA512 = 0x0003
|
51
|
-
end
|
52
|
-
|
53
|
-
def self.kdf_id2kdf_hash(kdf_id)
|
54
|
-
case kdf_id
|
55
|
-
when KdfId::HKDF_SHA256
|
56
|
-
:sha256
|
57
|
-
when KdfId::HKDF_SHA384
|
58
|
-
:sha384
|
59
|
-
when KdfId::HKDF_SHA512
|
60
|
-
:sha512
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
module AeadId
|
65
|
-
# https://www.iana.org/assignments/hpke/hpke.xhtml#hpke-aead-ids
|
66
|
-
AES_128_GCM = 0x0001
|
67
|
-
AES_256_GCM = 0x0002
|
68
|
-
CHACHA20_POLY1305 = 0x0003
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.aead_id2overhead_len(aead_id)
|
72
|
-
case aead_id
|
73
|
-
when AeadId::AES_128_GCM, AeadId::CHACHA20_POLY1305
|
74
|
-
16
|
75
|
-
when AeadId::AES_256_GCM
|
76
|
-
32
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def self.aead_id2aead_cipher(aead_id)
|
81
|
-
case aead_id
|
82
|
-
when AeadId::AES_128_GCM
|
83
|
-
:aes_128_gcm
|
84
|
-
when AeadId::AES_256_GCM
|
85
|
-
:aes_256_gcm
|
86
|
-
when AeadId::CHACHA20_POLY1305
|
87
|
-
:chacha20_poly1305
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|