tttls1.3 0.2.17 → 0.2.19

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2b9bfcfb3b52aaf74864e31adc9f132ab9ce94f4610bcaaefd8c7a5048666e5
4
- data.tar.gz: 77ccec36eaeec3d0d569a8428209b14749d0d2d80ce33348ed1cdb6f5cbd6ec8
3
+ metadata.gz: 60aaa0dddc8e01d6ee1c89a81de02e7cd9e05e0169e11381ebb68aa919644f11
4
+ data.tar.gz: 974b5c89009c2a63a6d99a608b32463cb0b6dc4bb0ed9e915cd03cca45ce2ea9
5
5
  SHA512:
6
- metadata.gz: 29ffa56dd58069ec5096bc0a19d81d79ee71a34f57d2381f91a1039d33b9ec0ca5cd965904a586d2f342957c3a05e92167e2c249fc2aad0ea4bfe2cebf9dc30f
7
- data.tar.gz: a1cd0087f0d9ab6a2c7adf5245f9acca5756da7cd3084d1e2b79a601c6606b00680291be5fe7fcf442bdb9d90cdb22dc26a241bcf26ac754ff0476e889c3f092
6
+ metadata.gz: b9ab939f9010481de463c2fbf81dc230cdd653dac47286e1fd61f8820da796a09b0675837dc119ebd8f1ddd137383ccc87aec18edd4945312cb0923ebbe77e52
7
+ data.tar.gz: 74d0635bba0274cfaf9ed980d2f0cef3351ab1f820a17720424dececaeb86c6ea36d6f9c3d7b69c8e81b52c4790b1796ba59d02a95a30d4afe90bad35767d442
@@ -15,18 +15,23 @@ jobs:
15
15
  matrix:
16
16
  ruby-version: ['2.7.x', '3.0.x', '3.1.x']
17
17
  steps:
18
+ - uses: actions/checkout@v3
18
19
  - uses: docker://thekuwayama/openssl:latest
19
20
  - name: Set up Ruby
20
- uses: actions/setup-ruby@v1
21
- - uses: actions/checkout@v1
21
+ uses: ruby/setup-ruby@v1
22
+ with:
23
+ ruby-version: ${{ matrix.ruby }}
22
24
  - name: Install dependencies
23
25
  run: |
24
26
  gem --version
25
27
  gem install bundler
26
28
  bundle --version
27
29
  bundle install
28
- - name: Run test
29
- run: |
30
- bundle exec rake
31
- bundle exec rake interop:client
32
- bundle exec rake interop:server
30
+ - name: Run rubocop
31
+ run: bundle exec rake rubocop
32
+ - name: Run rspec
33
+ run: bundle exec rake spec
34
+ - name: Run interop client
35
+ run: bundle exec rake interop:client
36
+ - name: Run interop server
37
+ run: bundle exec rake interop:server
data/.gitignore CHANGED
@@ -14,3 +14,4 @@ Gemfile.lock
14
14
  /coverage/
15
15
  /spec/reports/
16
16
  /tmp/
17
+ .DS_Store
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.1.2
data/Gemfile CHANGED
@@ -6,10 +6,12 @@ gem 'logger'
6
6
  gem 'openssl'
7
7
  gem 'rake'
8
8
 
9
- group :test do
9
+ group :development do
10
10
  gem 'byebug'
11
+ gem 'http_parser.rb'
11
12
  gem 'rspec', '3.9.0'
12
13
  gem 'rubocop', '0.78.0'
14
+ gem 'webrick'
13
15
  end
14
16
 
15
17
  gemspec
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/tttls1.3.svg)](https://badge.fury.io/rb/tttls1.3)
4
4
  [![Actions Status](https://github.com/thekuwayama/tttls1.3/workflows/CI/badge.svg)](https://github.com/thekuwayama/tttls1.3/actions?workflow=CI)
5
- [![Maintainability](https://api.codeclimate.com/v1/badges/47f3c267d9cfd2c8e388/maintainability)](https://codeclimate.com/github/thekuwayama/tttls1.3/maintainability)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/b5ae1b3a43828142d2fa/maintainability)](https://codeclimate.com/github/thekuwayama/tttls1.3/maintainability)
6
6
 
7
7
  tttls1.3 is Ruby implementation of [TLS 1.3](https://tools.ietf.org/html/rfc8446) protocol.
8
8
 
@@ -92,9 +92,9 @@ tttls1.3 client is configurable using keyword arguments.
92
92
  | `:supported_groups` | Array of TTTLS13::NamedGroup constant | `SECP256R1`, `SECP384R1`, `SECP521R1` | List of named groups offered in ClientHello extensions. |
93
93
  | `:key_share_groups` | Array of TTTLS13::NamedGroup constant | nil | List of named groups offered in KeyShareClientHello. In default, KeyShareClientHello has only a KeyShareEntry of most preferred named group in `:supported_groups`. You can set this to send KeyShareClientHello that has multiple KeyShareEntry. |
94
94
  | `:alpn` | Array of String | nil | List of application protocols offered in ClientHello extensions. If not needed to be present, set nil. |
95
- | `:process_new_session_ticket` | Proc | nil | Proc that processes received NewSessionTicket. Its 3 arguments are TTTLS13::Message::NewSessionTicket, resumption master secret and cipher suite. If not needed to process NewSessionTicket, set nil. |
95
+ | `:process_new_session_ticket` | Proc | nil | Proc that processes received NewSessionTicket. Its 3 arguments are TTTLS13::Message::NewSessionTicket, resumption main secret and cipher suite. If not needed to process NewSessionTicket, set nil. |
96
96
  | `:ticket` | String | nil | The ticket for PSK. |
97
- | `:resumption_master_secret` | String | nil | The resumption master secret. |
97
+ | `:resumption_secret` | String | nil | The resumption main secret. |
98
98
  | `:psk_cipher_suite` | TTTLS13::CipherSuite constant | nil | The cipher suite for PSK. |
99
99
  | `:ticket_nonce` | String | nil | The ticket\_nonce for PSK. |
100
100
  | `:ticket_age_add` | String | nil | The ticket\_age\_add for PSK. |
@@ -104,6 +104,7 @@ tttls1.3 client is configurable using keyword arguments.
104
104
  | `:process_certificate_status` | Proc | `TTTLS13::Client.method(:softfail_check_certificate_status)` | Proc(or Method) that checks received OCSPResponse. Its 3 arguments are OpenSSL::OCSP::Response, end-entity certificate(OpenSSL::X509::Certificate) and certificates chain(Array of Certificate) used for verification and it returns Boolean. |
105
105
  | `:compress_certificate_algorithms` | Array of TTTLS13::Message::Extension::CertificateCompressionAlgorithm constant | `ZLIB` | The compression algorithms are supported for compressing the Certificate message. |
106
106
  | `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
107
+ | `:sslkeylogfile` | String | nil | If needed to log SSLKEYLOGFILE, set the file path. |
107
108
  | `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
108
109
 
109
110
 
@@ -123,6 +124,7 @@ tttls1.3 server is configurable using keyword arguments.
123
124
  | `:process_ocsp_response` | Proc | nil | Proc that gets OpenSSL::OCSP::Response. If not needed to staple OCSP::Response, set nil. |
124
125
  | `:compress_certificate_algorithms` | Array of TTTLS13::Message::Extension::CertificateCompressionAlgorithm constant | `ZLIB` | The compression algorithms are supported for compressing the Certificate message. |
125
126
  | `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
127
+ | `:sslkeylogfile` | String | nil | If needed to log SSLKEYLOGFILE, set the file path. |
126
128
  | `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
127
129
 
128
130
 
@@ -10,7 +10,8 @@ req = simple_http_request(hostname)
10
10
  socket = TCPSocket.new(hostname, port)
11
11
  settings = {
12
12
  ca_file: File.exist?(ca_file) ? ca_file : nil,
13
- alpn: ['http/1.1']
13
+ alpn: ['http/1.1'],
14
+ sslkeylogfile: '/tmp/sslkeylogfile.log'
14
15
  }
15
16
  client = TTTLS13::Client.new(socket, hostname, **settings)
16
17
  client.connect
@@ -15,7 +15,7 @@ process_new_session_ticket = lambda do |nst, rms, cs|
15
15
  return if Time.now.to_i - nst.timestamp > nst.ticket_lifetime
16
16
 
17
17
  settings_2nd[:ticket] = nst.ticket
18
- settings_2nd[:resumption_master_secret] = rms
18
+ settings_2nd[:resumption_main_secret] = rms
19
19
  settings_2nd[:psk_cipher_suite] = cs
20
20
  settings_2nd[:ticket_nonce] = nst.ticket_nonce
21
21
  settings_2nd[:ticket_age_add] = nst.ticket_age_add
@@ -16,7 +16,7 @@ process_new_session_ticket = lambda do |nst, rms, cs|
16
16
 
17
17
  settings_2nd[:key_share_groups] = [] # empty KeyShareClientHello.client_shares
18
18
  settings_2nd[:ticket] = nst.ticket
19
- settings_2nd[:resumption_master_secret] = rms
19
+ settings_2nd[:resumption_main_secret] = rms
20
20
  settings_2nd[:psk_cipher_suite] = cs
21
21
  settings_2nd[:ticket_nonce] = nst.ticket_nonce
22
22
  settings_2nd[:ticket_age_add] = nst.ticket_age_add
@@ -15,7 +15,7 @@ process_new_session_ticket = lambda do |nst, rms, cs|
15
15
  return if Time.now.to_i - nst.timestamp > nst.ticket_lifetime
16
16
 
17
17
  settings_2nd[:ticket] = nst.ticket
18
- settings_2nd[:resumption_master_secret] = rms
18
+ settings_2nd[:resumption_main_secret] = rms
19
19
  settings_2nd[:psk_cipher_suite] = cs
20
20
  settings_2nd[:ticket_nonce] = nst.ticket_nonce
21
21
  settings_2nd[:ticket_age_add] = nst.ticket_age_add
@@ -12,7 +12,8 @@ settings = {
12
12
  crt_file: __dir__ + '/../tmp/server.crt',
13
13
  chain_files: [__dir__ + '/../tmp/intermediate.crt'],
14
14
  key_file: __dir__ + '/../tmp/server.key',
15
- alpn: ['http/1.1']
15
+ alpn: ['http/1.1'],
16
+ sslkeylogfile: '/tmp/sslkeylogfile.log'
16
17
  }
17
18
 
18
19
  q = Queue.new
@@ -49,7 +50,7 @@ Etc.nprocessors.times do
49
50
  rescue Timeout::Error
50
51
  logger.warn 'Timeout'
51
52
  ensure
52
- s.close
53
+ s&.close
53
54
  end
54
55
  end
55
56
  end
@@ -1,10 +1,10 @@
1
1
  # encoding: ascii-8bit
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative 'helper'
4
+ require_relative 'spec_helper'
5
5
 
6
6
  FIXTURES_DIR = __dir__ + '/../spec/fixtures'
7
- PORT = 4433
7
+ PORT = 14433
8
8
 
9
9
  RSpec.describe Client do
10
10
  # normal [Boolean] Is this nominal scenarios?
@@ -173,6 +173,7 @@ RSpec.describe Client do
173
173
  + '-tls1_3 ' \
174
174
  + '-www ' \
175
175
  + '-quiet ' \
176
+ + "-accept #{PORT} " \
176
177
  + opt
177
178
  pid = spawn('docker run ' \
178
179
  + "--volume #{FIXTURES_DIR}:/tmp " \
@@ -1,7 +1,7 @@
1
1
  # encoding: ascii-8bit
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative 'helper'
4
+ require_relative 'spec_helper'
5
5
 
6
6
  FIXTURES_DIR = __dir__ + '/../spec/fixtures'
7
7
  PORT = 4433
@@ -187,8 +187,6 @@ RSpec.describe Server do
187
187
 
188
188
  let(:client) do
189
189
  ip = Socket.ip_address_list.find(&:ipv4_private?).ip_address
190
- wait_to_listen(ip, PORT)
191
-
192
190
  cmd = 'echo -n ping | openssl s_client ' \
193
191
  + "-connect local:#{PORT} " \
194
192
  + '-tls1_3 ' \
@@ -13,13 +13,20 @@ include TTTLS13::Error
13
13
  # rubocop: enable Style/MixinUsage
14
14
 
15
15
  def wait_to_listen(host, port)
16
- loop do
17
- s = TCPSocket.open(host, port) # check by TCP handshake
18
- rescue # rubocop: disable Style/RescueStandardError
19
- sleep(0.2)
16
+ 10.times do
17
+ soc = TCPSocket.open(host, port)
18
+ ctx = OpenSSL::SSL::SSLContext.new
19
+ ctx.max_version = OpenSSL::SSL::TLS1_3_VERSION
20
+ ssl = OpenSSL::SSL::SSLSocket.new(soc, ctx)
21
+ ssl.sync_close = true
22
+ ssl.connect
23
+ rescue => e # rubocop: disable Style/RescueStandardError
24
+ p e
25
+ soc&.close
26
+ sleep(0.5)
20
27
  next
21
28
  else
22
- s.close
29
+ ssl.close
23
30
  break
24
31
  end
25
32
  end
@@ -58,7 +58,9 @@ module TTTLS13
58
58
  alpn: nil,
59
59
  process_new_session_ticket: nil,
60
60
  ticket: nil,
61
+ # @deprecated Please use `resumption_secret` instead
61
62
  resumption_master_secret: nil,
63
+ resumption_secret: nil,
62
64
  psk_cipher_suite: nil,
63
65
  ticket_nonce: nil,
64
66
  ticket_age_add: nil,
@@ -68,6 +70,7 @@ module TTTLS13
68
70
  process_certificate_status: nil,
69
71
  compress_certificate_algorithms: DEFALUT_CH_COMPRESS_CERTIFICATE_ALGORITHMS,
70
72
  compatibility_mode: true,
73
+ sslkeylogfile: nil,
71
74
  loglevel: Logger::WARN
72
75
  }.freeze
73
76
  private_constant :DEFAULT_CLIENT_SETTINGS
@@ -83,6 +86,15 @@ module TTTLS13
83
86
  @endpoint = :client
84
87
  @hostname = hostname
85
88
  @settings = DEFAULT_CLIENT_SETTINGS.merge(settings)
89
+ # NOTE: backward compatibility
90
+ if @settings[:resumption_secret].nil? &&
91
+ !@settings[:resumption_master_secret].nil?
92
+ @settings[:resumption_secret] =
93
+ @settings.delete(:resumption_master_secret) \
94
+ end
95
+ raise Error::ConfigError if @settings[:resumption_secret] !=
96
+ @settings[:resumption_master_secret]
97
+
86
98
  logger.level = @settings[:loglevel]
87
99
 
88
100
  @early_data = ''
@@ -136,7 +148,7 @@ module TTTLS13
136
148
  priv_keys = {} # Hash of NamedGroup => OpenSSL::PKey::$Object
137
149
  if use_psk?
138
150
  psk = gen_psk_from_nst(
139
- @settings[:resumption_master_secret],
151
+ @settings[:resumption_secret],
140
152
  @settings[:ticket_nonce],
141
153
  CipherSuite.digest(@settings[:psk_cipher_suite])
142
154
  )
@@ -151,6 +163,15 @@ module TTTLS13
151
163
  hs_wcipher = nil # TTTLS13::Cryptograph::$Object
152
164
  hs_rcipher = nil # TTTLS13::Cryptograph::$Object
153
165
  e_wcipher = nil # TTTLS13::Cryptograph::$Object
166
+ sslkeylogfile = nil # TTTLS13::SslKeyLogFile::Writer
167
+ unless @settings[:sslkeylogfile].nil?
168
+ begin
169
+ sslkeylogfile = SslKeyLogFile::Writer.new(@settings[:sslkeylogfile])
170
+ rescue SystemCallError => e
171
+ msg = "\"#{@settings[:sslkeylogfile]}\" file can NOT open: #{e}"
172
+ logger.warn(msg)
173
+ end
174
+ end
154
175
 
155
176
  @state = ClientState::START
156
177
  loop do
@@ -169,6 +190,10 @@ module TTTLS13
169
190
  key_schedule.early_data_write_key,
170
191
  key_schedule.early_data_write_iv
171
192
  )
193
+ sslkeylogfile&.write_client_early_traffic_secret(
194
+ transcript[CH].first.random,
195
+ key_schedule.client_early_traffic_secret
196
+ )
172
197
  send_early_data(e_wcipher)
173
198
  end
174
199
 
@@ -276,11 +301,19 @@ module TTTLS13
276
301
  key_schedule.client_handshake_write_key,
277
302
  key_schedule.client_handshake_write_iv
278
303
  )
304
+ sslkeylogfile&.write_client_handshake_traffic_secret(
305
+ transcript[CH].first.random,
306
+ key_schedule.client_handshake_traffic_secret
307
+ )
279
308
  hs_rcipher = gen_cipher(
280
309
  @cipher_suite,
281
310
  key_schedule.server_handshake_write_key,
282
311
  key_schedule.server_handshake_write_iv
283
312
  )
313
+ sslkeylogfile&.write_server_handshake_traffic_secret(
314
+ transcript[CH].first.random,
315
+ key_schedule.server_handshake_traffic_secret
316
+ )
284
317
  @state = ClientState::WAIT_EE
285
318
  when ClientState::WAIT_EE
286
319
  logger.debug('ClientState::WAIT_EE')
@@ -388,13 +421,21 @@ module TTTLS13
388
421
  key_schedule.client_application_write_key,
389
422
  key_schedule.client_application_write_iv
390
423
  )
424
+ sslkeylogfile&.write_client_traffic_secret_0(
425
+ transcript[CH].first.random,
426
+ key_schedule.client_application_traffic_secret
427
+ )
391
428
  @ap_rcipher = gen_cipher(
392
429
  @cipher_suite,
393
430
  key_schedule.server_application_write_key,
394
431
  key_schedule.server_application_write_iv
395
432
  )
396
- @exporter_master_secret = key_schedule.exporter_master_secret
397
- @resumption_master_secret = key_schedule.resumption_master_secret
433
+ sslkeylogfile&.write_server_traffic_secret_0(
434
+ transcript[CH].first.random,
435
+ key_schedule.server_application_traffic_secret
436
+ )
437
+ @exporter_secret = key_schedule.exporter_secret
438
+ @resumption_secret = key_schedule.resumption_secret
398
439
  @state = ClientState::CONNECTED
399
440
  when ClientState::CONNECTED
400
441
  logger.debug('ClientState::CONNECTED')
@@ -402,6 +443,7 @@ module TTTLS13
402
443
  break
403
444
  end
404
445
  end
446
+ sslkeylogfile&.close
405
447
  end
406
448
  # rubocop: enable Metrics/AbcSize
407
449
  # rubocop: enable Metrics/BlockLength
@@ -513,7 +555,7 @@ module TTTLS13
513
555
  # @return [Boolean]
514
556
  def use_psk?
515
557
  !@settings[:ticket].nil? &&
516
- !@settings[:resumption_master_secret].nil? &&
558
+ !@settings[:resumption_secret].nil? &&
517
559
  !@settings[:psk_cipher_suite].nil? &&
518
560
  !@settings[:ticket_nonce].nil? &&
519
561
  !@settings[:ticket_age_add].nil? &&
@@ -537,14 +579,14 @@ module TTTLS13
537
579
  send_record(ap_record)
538
580
  end
539
581
 
540
- # @param resumption_master_secret [String]
582
+ # @param resumption_secret [String]
541
583
  # @param ticket_nonce [String]
542
584
  # @param digest [String] name of digest algorithm
543
585
  #
544
586
  # @return [String]
545
- def gen_psk_from_nst(resumption_master_secret, ticket_nonce, digest)
587
+ def gen_psk_from_nst(resumption_secret, ticket_nonce, digest)
546
588
  hash_len = OpenSSL::Digest.new(digest).digest_length
547
- KeySchedule.hkdf_expand_label(resumption_master_secret, 'resumption',
589
+ KeySchedule.hkdf_expand_label(resumption_secret, 'resumption',
548
590
  ticket_nonce, hash_len, digest)
549
591
  end
550
592
 
@@ -918,7 +960,7 @@ module TTTLS13
918
960
  def process_new_session_ticket(nst)
919
961
  super(nst)
920
962
 
921
- rms = @resumption_master_secret
963
+ rms = @resumption_secret
922
964
  cs = @cipher_suite
923
965
  @settings[:process_new_session_ticket]&.call(nst, rms, cs)
924
966
  end
@@ -25,7 +25,7 @@ module TTTLS13
25
25
  @send_record_size = Message::DEFAULT_RECORD_SIZE_LIMIT
26
26
  @recv_record_size = Message::DEFAULT_RECORD_SIZE_LIMIT
27
27
  @alpn = nil # String
28
- @exporter_master_secret = nil # String
28
+ @exporter_secret = nil # String
29
29
  end
30
30
 
31
31
  # @raise [TTTLS13::Error::ConfigError]
@@ -109,15 +109,15 @@ module TTTLS13
109
109
  #
110
110
  # @return [String, nil]
111
111
  def exporter(label, context, key_length)
112
- return nil if @exporter_master_secret.nil? || @cipher_suite.nil?
112
+ return nil if @exporter_secret.nil? || @cipher_suite.nil?
113
113
 
114
114
  digest = CipherSuite.digest(@cipher_suite)
115
- do_exporter(@exporter_master_secret, digest, label, context, key_length)
115
+ do_exporter(@exporter_secret, digest, label, context, key_length)
116
116
  end
117
117
 
118
118
  private
119
119
 
120
- # @param secret [String] (early_)exporter_master_secret
120
+ # @param secret [String] (early_)exporter_secret
121
121
  # @param digest [String] name of digest algorithm
122
122
  # @param label [String]
123
123
  # @param context [String]
@@ -517,10 +517,8 @@ module TTTLS13
517
517
  #
518
518
  # @return [Array of TTTLS13::Message::Extension::SignatureAlgorithms]
519
519
  def do_select_signature_algorithms(signature_algorithms, crt)
520
- spki = OpenSSL::Netscape::SPKI.new
521
- spki.public_key = crt.public_key
522
- pka = OpenSSL::ASN1.decode(spki.to_der)
523
- .value.first.value.first.value.first.value.first.value
520
+ pka = OpenSSL::ASN1.decode(crt.public_key.to_der)
521
+ .value.first.value.first.value
524
522
  signature_algorithms.select do |sa|
525
523
  case sa
526
524
  when SignatureScheme::ECDSA_SECP256R1_SHA256,
@@ -61,8 +61,15 @@ module TTTLS13
61
61
  self.class.hkdf_expand_label(secret, 'iv', '', @iv_len, @digest)
62
62
  end
63
63
 
64
+ # @deprecated Please use `early_exporter_secret` instead
65
+ #
64
66
  # @return [String]
65
67
  def early_exporter_master_secret
68
+ early_exporter_secret
69
+ end
70
+
71
+ # @return [String]
72
+ def early_exporter_secret
66
73
  hash = OpenSSL::Digest.digest(@digest, '')
67
74
  derive_secret(early_secret, 'e exp master', hash)
68
75
  end
@@ -126,22 +133,36 @@ module TTTLS13
126
133
  self.class.hkdf_expand_label(secret, 'iv', '', @iv_len, @digest)
127
134
  end
128
135
 
136
+ # @deprecated Please use `main_salt` instead
137
+ #
129
138
  # @return [String]
130
139
  def master_salt
140
+ main_salt
141
+ end
142
+
143
+ # @return [String]
144
+ def main_salt
131
145
  hash = OpenSSL::Digest.digest(@digest, '')
132
146
  derive_secret(handshake_secret, 'derived', hash)
133
147
  end
134
148
 
149
+ # @deprecated Please use `main_secret` instead
150
+ #
135
151
  # @return [String]
136
152
  def master_secret
153
+ main_secret
154
+ end
155
+
156
+ # @return [String]
157
+ def main_secret
137
158
  ikm = "\x00" * @hash_len
138
- hkdf_extract(ikm, master_salt)
159
+ hkdf_extract(ikm, main_salt)
139
160
  end
140
161
 
141
162
  # @return [String]
142
163
  def client_application_traffic_secret
143
164
  hash = @transcript.hash(@digest, SF)
144
- derive_secret(master_secret, 'c ap traffic', hash)
165
+ derive_secret(main_secret, 'c ap traffic', hash)
145
166
  end
146
167
 
147
168
  # @return [String]
@@ -159,7 +180,7 @@ module TTTLS13
159
180
  # @return [String]
160
181
  def server_application_traffic_secret
161
182
  hash = @transcript.hash(@digest, SF)
162
- derive_secret(master_secret, 's ap traffic', hash)
183
+ derive_secret(main_secret, 's ap traffic', hash)
163
184
  end
164
185
 
165
186
  # @return [String]
@@ -174,16 +195,30 @@ module TTTLS13
174
195
  self.class.hkdf_expand_label(secret, 'iv', '', @iv_len, @digest)
175
196
  end
176
197
 
198
+ # @deprecated Please use `exporter_secret` instead
199
+ #
177
200
  # @return [String]
178
201
  def exporter_master_secret
202
+ exporter_secret
203
+ end
204
+
205
+ # @return [String]
206
+ def exporter_secret
179
207
  hash = @transcript.hash(@digest, SF)
180
- derive_secret(master_secret, 'exp master', hash)
208
+ derive_secret(main_secret, 'exp master', hash)
181
209
  end
182
210
 
211
+ # @deprecated Please use `resumption_secret` instead
212
+ #
183
213
  # @return [String]
184
214
  def resumption_master_secret
215
+ resumption_secret
216
+ end
217
+
218
+ # @return [String]
219
+ def resumption_secret
185
220
  hash = @transcript.hash(@digest, CF)
186
- derive_secret(master_secret, 'res master', hash)
221
+ derive_secret(main_secret, 'res master', hash)
187
222
  end
188
223
 
189
224
  # @param ikm [String]
@@ -91,8 +91,7 @@ module TTTLS13
91
91
  priv_keys = {}
92
92
  kse = groups.map do |group|
93
93
  curve = NamedGroup.curve_name(group)
94
- ec = OpenSSL::PKey::EC.new(curve)
95
- ec.generate_key!
94
+ ec = OpenSSL::PKey::EC.generate(curve)
96
95
  # store private key to do the key-exchange
97
96
  priv_keys.store(group, ec)
98
97
  KeyShareEntry.new(
@@ -115,8 +114,7 @@ module TTTLS13
115
114
  # @return [OpenSSL::PKey::EC.$Object]
116
115
  def self.gen_sh_key_share(group)
117
116
  curve = NamedGroup.curve_name(group)
118
- ec = OpenSSL::PKey::EC.new(curve)
119
- ec.generate_key!
117
+ ec = OpenSSL::PKey::EC.generate(curve)
120
118
 
121
119
  key_share = KeyShare.new(
122
120
  msg_type: HandshakeType::SERVER_HELLO,
@@ -60,6 +60,7 @@ module TTTLS13
60
60
  process_ocsp_response: nil,
61
61
  compress_certificate_algorithms: DEFAULT_SP_COMPRESS_CERTIFICATE_ALGORITHMS,
62
62
  compatibility_mode: true,
63
+ sslkeylogfile: nil,
63
64
  loglevel: Logger::WARN
64
65
  }.freeze
65
66
  private_constant :DEFAULT_SERVER_SETTINGS
@@ -148,6 +149,15 @@ module TTTLS13
148
149
  priv_key = nil # OpenSSL::PKey::$Object
149
150
  hs_wcipher = nil # TTTLS13::Cryptograph::$Object
150
151
  hs_rcipher = nil # TTTLS13::Cryptograph::$Object
152
+ sslkeylogfile = nil # TTTLS13::SslKeyLogFile::Writer
153
+ unless @settings[:sslkeylogfile].nil?
154
+ begin
155
+ sslkeylogfile = SslKeyLogFile::Writer.new(@settings[:sslkeylogfile])
156
+ rescue SystemCallError => e
157
+ msg = "\"#{@settings[:sslkeylogfile]}\" file can NOT open: #{e}"
158
+ logger.warn(msg)
159
+ end
160
+ end
151
161
 
152
162
  @state = ServerState::START
153
163
  loop do
@@ -220,7 +230,7 @@ module TTTLS13
220
230
  # generate shared secret
221
231
  ke = ch.extensions[Message::ExtensionType::KEY_SHARE]
222
232
  &.key_share_entry
223
- &.find { |e| e.group == @named_group }
233
+ &.find { |kse| kse.group == @named_group }
224
234
  &.key_exchange
225
235
  shared_secret = gen_shared_secret(ke, priv_key, @named_group)
226
236
  key_schedule = KeySchedule.new(
@@ -234,11 +244,19 @@ module TTTLS13
234
244
  key_schedule.server_handshake_write_key,
235
245
  key_schedule.server_handshake_write_iv
236
246
  )
247
+ sslkeylogfile&.write_server_handshake_traffic_secret(
248
+ transcript[CH].first.random,
249
+ key_schedule.server_handshake_traffic_secret
250
+ )
237
251
  hs_rcipher = gen_cipher(
238
252
  @cipher_suite,
239
253
  key_schedule.client_handshake_write_key,
240
254
  key_schedule.client_handshake_write_iv
241
255
  )
256
+ sslkeylogfile&.write_client_handshake_traffic_secret(
257
+ transcript[CH].first.random,
258
+ key_schedule.client_handshake_traffic_secret
259
+ )
242
260
  @state = ServerState::WAIT_FLIGHT2
243
261
  when ServerState::WAIT_EOED
244
262
  logger.debug('ServerState::WAIT_EOED')
@@ -292,12 +310,20 @@ module TTTLS13
292
310
  key_schedule.server_application_write_key,
293
311
  key_schedule.server_application_write_iv
294
312
  )
313
+ sslkeylogfile&.write_server_traffic_secret_0(
314
+ transcript[CH].first.random,
315
+ key_schedule.server_application_traffic_secret
316
+ )
295
317
  @ap_rcipher = gen_cipher(
296
318
  @cipher_suite,
297
319
  key_schedule.client_application_write_key,
298
320
  key_schedule.client_application_write_iv
299
321
  )
300
- @exporter_master_secret = key_schedule.exporter_master_secret
322
+ sslkeylogfile&.write_client_traffic_secret_0(
323
+ transcript[CH].first.random,
324
+ key_schedule.client_application_traffic_secret
325
+ )
326
+ @exporter_secret = key_schedule.exporter_secret
301
327
  @state = ServerState::CONNECTED
302
328
  when ServerState::CONNECTED
303
329
  logger.debug('ServerState::CONNECTED')
@@ -305,6 +331,7 @@ module TTTLS13
305
331
  break
306
332
  end
307
333
  end
334
+ sslkeylogfile&.close
308
335
  end
309
336
  # rubocop: enable Metrics/AbcSize
310
337
  # rubocop: enable Metrics/BlockLength
@@ -0,0 +1,87 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ module TTTLS13
5
+ module SslKeyLogFile
6
+ module Label
7
+ CLIENT_EARLY_TRAFFIC_SECRET = 'CLIENT_EARLY_TRAFFIC_SECRET'
8
+ CLIENT_HANDSHAKE_TRAFFIC_SECRET = 'CLIENT_HANDSHAKE_TRAFFIC_SECRET'
9
+ SERVER_HANDSHAKE_TRAFFIC_SECRET = 'SERVER_HANDSHAKE_TRAFFIC_SECRET'
10
+ CLIENT_TRAFFIC_SECRET_0 = 'CLIENT_TRAFFIC_SECRET_0'
11
+ SERVER_TRAFFIC_SECRET_0 = 'SERVER_TRAFFIC_SECRET_0'
12
+ end
13
+
14
+ class Writer
15
+ # @param path [String]
16
+ #
17
+ # @raise [SystemCallError]
18
+ def initialize(path)
19
+ @file = File.new(path, 'a+')
20
+ end
21
+
22
+ # @param client_random [String]
23
+ # @param secret [String]
24
+ def write_client_early_traffic_secret(client_random, secret)
25
+ write_key_log(
26
+ Label::CLIENT_EARLY_TRAFFIC_SECRET,
27
+ client_random,
28
+ secret
29
+ )
30
+ end
31
+
32
+ # @param client_random [String]
33
+ # @param secret [String]
34
+ def write_client_handshake_traffic_secret(client_random, secret)
35
+ write_key_log(
36
+ Label::CLIENT_HANDSHAKE_TRAFFIC_SECRET,
37
+ client_random,
38
+ secret
39
+ )
40
+ end
41
+
42
+ # @param client_random [String]
43
+ # @param secret [String]
44
+ def write_server_handshake_traffic_secret(client_random, secret)
45
+ write_key_log(
46
+ Label::SERVER_HANDSHAKE_TRAFFIC_SECRET,
47
+ client_random,
48
+ secret
49
+ )
50
+ end
51
+
52
+ # @param client_random [String]
53
+ # @param secret [String]
54
+ def write_client_traffic_secret_0(client_random, secret)
55
+ write_key_log(
56
+ Label::CLIENT_TRAFFIC_SECRET_0,
57
+ client_random,
58
+ secret
59
+ )
60
+ end
61
+
62
+ # @param client_random [String]
63
+ # @param secret [String]
64
+ def write_server_traffic_secret_0(client_random, secret)
65
+ write_key_log(
66
+ Label::SERVER_TRAFFIC_SECRET_0,
67
+ client_random,
68
+ secret
69
+ )
70
+ end
71
+
72
+ def close
73
+ @file&.close
74
+ end
75
+
76
+ private
77
+
78
+ # @param label [TTTLS13::SslKeyLogFile::Label]
79
+ # @param client_random [String]
80
+ # @param secret [String]
81
+ def write_key_log(label, client_random, secret)
82
+ s = "#{label} #{client_random.unpack1('H*')} #{secret.unpack1('H*')}\n"
83
+ @file&.print(s)
84
+ end
85
+ end
86
+ end
87
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTTLS13
4
- VERSION = '0.2.17'
4
+ VERSION = '0.2.19'
5
5
  end
data/lib/tttls1.3.rb CHANGED
@@ -17,6 +17,7 @@ require 'tttls1.3/transcript'
17
17
  require 'tttls1.3/key_schedule'
18
18
  require 'tttls1.3/message'
19
19
  require 'tttls1.3/sequence_number'
20
+ require 'tttls1.3/sslkeylogfile'
20
21
  require 'tttls1.3/connection'
21
22
  require 'tttls1.3/client'
22
23
  require 'tttls1.3/server'
@@ -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
@@ -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
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.17
4
+ version: 0.2.19
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-14 00:00:00.000000000 Z
11
+ date: 2023-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -63,6 +63,7 @@ files:
63
63
  - ".gitignore"
64
64
  - ".rspec"
65
65
  - ".rubocop.yml"
66
+ - ".ruby-version"
66
67
  - Gemfile
67
68
  - LICENSE.txt
68
69
  - README.md
@@ -77,8 +78,8 @@ files:
77
78
  - example/https_client_using_ticket.rb
78
79
  - example/https_server.rb
79
80
  - interop/client_spec.rb
80
- - interop/helper.rb
81
81
  - interop/server_spec.rb
82
+ - interop/spec_helper.rb
82
83
  - lib/tttls1.3.rb
83
84
  - lib/tttls1.3/cipher_suites.rb
84
85
  - lib/tttls1.3/client.rb
@@ -123,6 +124,7 @@ files:
123
124
  - lib/tttls1.3/sequence_number.rb
124
125
  - lib/tttls1.3/server.rb
125
126
  - lib/tttls1.3/signature_scheme.rb
127
+ - lib/tttls1.3/sslkeylogfile.rb
126
128
  - lib/tttls1.3/transcript.rb
127
129
  - lib/tttls1.3/utils.rb
128
130
  - lib/tttls1.3/version.rb
@@ -198,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
198
200
  - !ruby/object:Gem::Version
199
201
  version: '0'
200
202
  requirements: []
201
- rubygems_version: 3.2.22
203
+ rubygems_version: 3.3.7
202
204
  signing_key:
203
205
  specification_version: 4
204
206
  summary: TLS 1.3 implementation in Ruby (Tiny Trial TLS1.3 aka tttls1.3)