tttls1.3 0.3.0 → 0.3.2
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 +2 -2
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -1
- data/Gemfile +1 -0
- data/README.md +2 -2
- data/example/README.md +1 -1
- data/example/helper.rb +22 -0
- data/example/https_client.rb +4 -4
- data/example/https_client_using_0rtt.rb +6 -5
- data/example/https_client_using_ech.rb +5 -6
- data/example/https_client_using_grease_ech.rb +3 -5
- data/example/https_client_using_grease_psk.rb +8 -16
- data/example/https_client_using_hrr.rb +5 -4
- data/example/https_client_using_hrr_and_ech.rb +6 -6
- data/example/https_client_using_hrr_and_ticket.rb +5 -4
- data/example/https_client_using_status_request.rb +4 -5
- data/example/https_client_using_ticket.rb +5 -4
- 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 +410 -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 +12 -10
- 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/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_spec.rb +39 -0
- data/spec/{connection_spec.rb → endpoint_spec.rb} +41 -49
- data/spec/server_spec.rb +12 -12
- data/tttls1.3.gemspec +1 -1
- metadata +8 -7
- data/lib/tttls1.3/hpke.rb +0 -91
data/spec/ech_spec.rb
CHANGED
@@ -78,4 +78,43 @@ RSpec.describe ECHClientHello do
|
|
78
78
|
expect(extension.confirmation).to eq "\x00" * 8
|
79
79
|
end
|
80
80
|
end
|
81
|
+
|
82
|
+
context 'EncodedClientHelloInner length' do
|
83
|
+
let(:server_name) do
|
84
|
+
'localhost'
|
85
|
+
end
|
86
|
+
|
87
|
+
let(:client) do
|
88
|
+
Client.new(nil, server_name)
|
89
|
+
end
|
90
|
+
|
91
|
+
let(:maximum_name_length) do
|
92
|
+
0
|
93
|
+
end
|
94
|
+
|
95
|
+
let(:encoded) do
|
96
|
+
extensions, = client.send(:gen_ch_extensions)
|
97
|
+
inner_ech = Message::Extension::ECHClientHello.new_inner
|
98
|
+
Message::ClientHello.new(
|
99
|
+
legacy_session_id: '',
|
100
|
+
cipher_suites: CipherSuites.new(DEFAULT_CH_CIPHER_SUITES),
|
101
|
+
extensions: extensions.merge(
|
102
|
+
Message::ExtensionType::ENCRYPTED_CLIENT_HELLO => inner_ech
|
103
|
+
)
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
let(:padding_encoded_ch_inner) do
|
108
|
+
Ech.padding_encoded_ch_inner(
|
109
|
+
encoded.serialize[4..],
|
110
|
+
server_name.length,
|
111
|
+
maximum_name_length
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should be equal placeholder_encoded_ch_inner_len' do
|
116
|
+
expect(Ech.placeholder_encoded_ch_inner_len)
|
117
|
+
.to eq padding_encoded_ch_inner.length
|
118
|
+
end
|
119
|
+
end
|
81
120
|
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/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/tttls1.3.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.description = spec.summary
|
14
14
|
spec.homepage = 'https://github.com/thekuwayama/tttls1.3'
|
15
15
|
spec.license = 'MIT'
|
16
|
-
spec.required_ruby_version = '>=
|
16
|
+
spec.required_ruby_version = '>=3.1'
|
17
17
|
|
18
18
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
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.2
|
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-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -119,8 +119,9 @@ files:
|
|
119
119
|
- lib/tttls1.3/cryptograph.rb
|
120
120
|
- lib/tttls1.3/cryptograph/aead.rb
|
121
121
|
- lib/tttls1.3/cryptograph/passer.rb
|
122
|
+
- lib/tttls1.3/ech.rb
|
123
|
+
- lib/tttls1.3/endpoint.rb
|
122
124
|
- lib/tttls1.3/error.rb
|
123
|
-
- lib/tttls1.3/hpke.rb
|
124
125
|
- lib/tttls1.3/key_schedule.rb
|
125
126
|
- lib/tttls1.3/logging.rb
|
126
127
|
- lib/tttls1.3/message.rb
|
@@ -173,12 +174,12 @@ files:
|
|
173
174
|
- spec/client_hello_spec.rb
|
174
175
|
- spec/client_spec.rb
|
175
176
|
- spec/compress_certificate_spec.rb
|
176
|
-
- spec/connection_spec.rb
|
177
177
|
- spec/cookie_spec.rb
|
178
178
|
- spec/early_data_indication_spec.rb
|
179
179
|
- spec/ech_spec.rb
|
180
180
|
- spec/encrypted_extensions_spec.rb
|
181
181
|
- spec/end_of_early_data_spec.rb
|
182
|
+
- spec/endpoint_spec.rb
|
182
183
|
- spec/error_spec.rb
|
183
184
|
- spec/extensions_spec.rb
|
184
185
|
- spec/finished_spec.rb
|
@@ -228,14 +229,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
228
229
|
requirements:
|
229
230
|
- - ">="
|
230
231
|
- !ruby/object:Gem::Version
|
231
|
-
version: '
|
232
|
+
version: '3.1'
|
232
233
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
233
234
|
requirements:
|
234
235
|
- - ">="
|
235
236
|
- !ruby/object:Gem::Version
|
236
237
|
version: '0'
|
237
238
|
requirements: []
|
238
|
-
rubygems_version: 3.3
|
239
|
+
rubygems_version: 3.5.3
|
239
240
|
signing_key:
|
240
241
|
specification_version: 4
|
241
242
|
summary: TLS 1.3 implementation in Ruby (Tiny Trial TLS1.3 aka tttls1.3)
|
@@ -251,12 +252,12 @@ test_files:
|
|
251
252
|
- spec/client_hello_spec.rb
|
252
253
|
- spec/client_spec.rb
|
253
254
|
- spec/compress_certificate_spec.rb
|
254
|
-
- spec/connection_spec.rb
|
255
255
|
- spec/cookie_spec.rb
|
256
256
|
- spec/early_data_indication_spec.rb
|
257
257
|
- spec/ech_spec.rb
|
258
258
|
- spec/encrypted_extensions_spec.rb
|
259
259
|
- spec/end_of_early_data_spec.rb
|
260
|
+
- spec/endpoint_spec.rb
|
260
261
|
- spec/error_spec.rb
|
261
262
|
- spec/extensions_spec.rb
|
262
263
|
- 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
|