tttls1.3 0.2.12 → 0.2.16
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 +32 -0
- data/.rubocop.yml +2 -2
- data/Gemfile +3 -4
- data/README.md +4 -1
- data/example/helper.rb +3 -3
- data/example/https_client.rb +1 -1
- data/example/https_client_using_0rtt.rb +2 -2
- data/example/https_client_using_hrr.rb +1 -1
- data/example/https_client_using_hrr_and_ticket.rb +2 -2
- data/example/https_client_using_status_request.rb +2 -2
- data/example/https_client_using_ticket.rb +2 -2
- data/example/https_server.rb +2 -2
- data/interop/client_spec.rb +6 -6
- data/interop/server_spec.rb +6 -6
- data/lib/tttls1.3/client.rb +106 -65
- data/lib/tttls1.3/connection.rb +43 -30
- data/lib/tttls1.3/cryptograph/aead.rb +20 -7
- data/lib/tttls1.3/cryptograph.rb +1 -1
- data/lib/tttls1.3/message/alert.rb +2 -2
- data/lib/tttls1.3/message/client_hello.rb +1 -0
- data/lib/tttls1.3/message/compressed_certificate.rb +82 -0
- data/lib/tttls1.3/message/extension/alpn.rb +5 -2
- data/lib/tttls1.3/message/extension/compress_certificate.rb +58 -0
- data/lib/tttls1.3/message/extension/signature_algorithms.rb +15 -5
- data/lib/tttls1.3/message/extension/signature_algorithms_cert.rb +5 -4
- data/lib/tttls1.3/message/extension/supported_groups.rb +2 -2
- data/lib/tttls1.3/message/extensions.rb +31 -18
- data/lib/tttls1.3/message/record.rb +28 -16
- data/lib/tttls1.3/message.rb +23 -21
- data/lib/tttls1.3/server.rb +88 -37
- data/lib/tttls1.3/transcript.rb +3 -7
- data/lib/tttls1.3/version.rb +1 -1
- data/spec/client_spec.rb +28 -19
- data/spec/compress_certificate_spec.rb +54 -0
- data/spec/connection_spec.rb +22 -15
- data/spec/extensions_spec.rb +16 -0
- data/spec/fixtures/rsa_rsa.crt +15 -15
- data/spec/fixtures/rsa_rsa.key +25 -25
- data/spec/key_schedule_spec.rb +48 -25
- data/spec/record_spec.rb +2 -2
- data/spec/server_hello_spec.rb +1 -1
- data/spec/server_spec.rb +23 -11
- data/spec/signature_algorithms_cert_spec.rb +4 -0
- data/spec/signature_algorithms_spec.rb +4 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/transcript_spec.rb +34 -20
- data/tttls1.3.gemspec +0 -1
- metadata +11 -7
- data/.github/workflows/main.yml +0 -25
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7006bce3031f6232ae949b44eb31111562d581e359769952f48a537848d50418
         | 
| 4 | 
            +
              data.tar.gz: d332e823eb8c677ff534e46a87e96c039aad2d5538c0f823ac7eb365f372ca88
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ca37fd2570b905759da152932eb2e6f29c3e37f59135353b9e3cfbce0c683f7493fdd360f9a56c50f2ab252f0460728c09585d018d04b8668de4000b1567d249
         | 
| 7 | 
            +
              data.tar.gz: 6e37405f3034de1fe648f0882bbc9d9b65baeac8d1ef142fc776010b8480cd987a87060edf6ae85fd20327afc5327aacb23318e460f510259c99056aa76fb389
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            name: CI
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            on:
         | 
| 4 | 
            +
              push:
         | 
| 5 | 
            +
                branches:
         | 
| 6 | 
            +
                  - master
         | 
| 7 | 
            +
              pull_request:
         | 
| 8 | 
            +
                branches:
         | 
| 9 | 
            +
                  - '*'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            jobs:
         | 
| 12 | 
            +
              ci:
         | 
| 13 | 
            +
                runs-on: ubuntu-latest
         | 
| 14 | 
            +
                strategy:
         | 
| 15 | 
            +
                  matrix:
         | 
| 16 | 
            +
                    ruby-version: ['2.6.x', '2.7.x', '3.0.x']
         | 
| 17 | 
            +
                steps:
         | 
| 18 | 
            +
                  - uses: docker://thekuwayama/openssl:latest
         | 
| 19 | 
            +
                  - name: Set up Ruby
         | 
| 20 | 
            +
                    uses: actions/setup-ruby@v1
         | 
| 21 | 
            +
                  - uses: actions/checkout@v1
         | 
| 22 | 
            +
                  - name: Install dependencies
         | 
| 23 | 
            +
                    run: |
         | 
| 24 | 
            +
                      gem --version
         | 
| 25 | 
            +
                      gem install bundler
         | 
| 26 | 
            +
                      bundle --version
         | 
| 27 | 
            +
                      bundle install
         | 
| 28 | 
            +
                  - name: Run test
         | 
| 29 | 
            +
                    run: |
         | 
| 30 | 
            +
                      bundle exec rake
         | 
| 31 | 
            +
                      bundle exec rake interop:client
         | 
| 32 | 
            +
                      bundle exec rake interop:server
         | 
    
        data/.rubocop.yml
    CHANGED
    
    | @@ -16,7 +16,7 @@ Metrics/AbcSize: | |
| 16 16 | 
             
            Metrics/MethodLength:
         | 
| 17 17 | 
             
              Max: 30
         | 
| 18 18 |  | 
| 19 | 
            -
            Naming/ | 
| 19 | 
            +
            Naming/MethodParameterName:
         | 
| 20 20 | 
             
              MinNameLength: 1
         | 
| 21 21 |  | 
| 22 22 | 
             
            Metrics/BlockLength:
         | 
| @@ -25,6 +25,6 @@ Metrics/BlockLength: | |
| 25 25 | 
             
                - 'spec/*.rb'
         | 
| 26 26 | 
             
                - 'interop/*.rb'
         | 
| 27 27 |  | 
| 28 | 
            -
             | 
| 28 | 
            +
            Layout/LineLength:
         | 
| 29 29 | 
             
              Exclude:
         | 
| 30 30 | 
             
                - 'tttls1.3.gemspec'
         | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            # tttls1.3
         | 
| 2 2 |  | 
| 3 3 | 
             
            [](https://badge.fury.io/rb/tttls1.3)
         | 
| 4 | 
            -
            [](https://github.com/thekuwayama/tttls1.3/actions?workflow=CI)
         | 
| 5 5 | 
             
            [](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.
         | 
| @@ -102,6 +102,7 @@ tttls1.3 client is configurable using keyword arguments. | |
| 102 102 | 
             
            | `:record_size_limit` | Integer | nil | The record\_size\_limit offerd in ClientHello extensions. If not needed to be present, set nil. |
         | 
| 103 103 | 
             
            | `:check_certificate_status` | Boolean | false | If needed to check certificate status, set true. |
         | 
| 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 | 
            +
            | `:compress_certificate_algorithms` | Array of TTTLS13::Message::Extension::CertificateCompressionAlgorithm constant | `ZLIB` | The compression algorithms are supported for compressing the Certificate message. |
         | 
| 105 106 | 
             
            | `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
         | 
| 106 107 | 
             
            | `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
         | 
| 107 108 |  | 
| @@ -119,6 +120,8 @@ tttls1.3 server is configurable using keyword arguments. | |
| 119 120 | 
             
            | `:signature_algorithms` | Array of TTTLS13::SignatureScheme constant | `ECDSA_SECP256R1_SHA256`, `ECDSA_SECP384R1_SHA384`, `ECDSA_SECP521R1_SHA512`, `RSA_PSS_RSAE_SHA256`, `RSA_PSS_RSAE_SHA384`, `RSA_PSS_RSAE_SHA512`, `RSA_PKCS1_SHA256`, `RSA_PKCS1_SHA384`, `RSA_PKCS1_SHA512` | List of supported signature algorithms. |
         | 
| 120 121 | 
             
            | `:supported_groups` | Array of TTTLS13::NamedGroup constant | `SECP256R1`, `SECP384R1`, `SECP521R1` | List of supported named groups. |
         | 
| 121 122 | 
             
            | `:alpn` | Array of String | nil | List of supported application protocols. If not needed to check this extension, set nil. |
         | 
| 123 | 
            +
            | `:process_ocsp_response` | Proc | nil | Proc that gets OpenSSL::OCSP::Response. If not needed to staple OCSP::Response, set nil. |
         | 
| 124 | 
            +
            | `:compress_certificate_algorithms` | Array of TTTLS13::Message::Extension::CertificateCompressionAlgorithm constant | `ZLIB` | The compression algorithms are supported for compressing the Certificate message. |
         | 
| 122 125 | 
             
            | `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
         | 
| 123 126 | 
             
            | `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
         | 
| 124 127 |  | 
    
        data/example/helper.rb
    CHANGED
    
    | @@ -36,7 +36,7 @@ def recv_http_response(client) | |
| 36 36 | 
             
              parser = HTTP::Parser.new
         | 
| 37 37 | 
             
              buf = nil
         | 
| 38 38 |  | 
| 39 | 
            -
              parser.on_headers_complete =  | 
| 39 | 
            +
              parser.on_headers_complete = lambda do |headers|
         | 
| 40 40 | 
             
                buf =
         | 
| 41 41 | 
             
                  [
         | 
| 42 42 | 
             
                    'HTTP/' + parser.http_version.join('.'),
         | 
| @@ -47,11 +47,11 @@ def recv_http_response(client) | |
| 47 47 | 
             
                  + WEBrick::CRLF
         | 
| 48 48 | 
             
              end
         | 
| 49 49 |  | 
| 50 | 
            -
              parser.on_body =  | 
| 50 | 
            +
              parser.on_body = lambda do |chunk|
         | 
| 51 51 | 
             
                buf += chunk
         | 
| 52 52 | 
             
              end
         | 
| 53 53 |  | 
| 54 | 
            -
              parser.on_message_complete =  | 
| 54 | 
            +
              parser.on_message_complete = lambda do
         | 
| 55 55 | 
             
                client.close
         | 
| 56 56 | 
             
              end
         | 
| 57 57 |  | 
    
        data/example/https_client.rb
    CHANGED
    
    
| @@ -11,7 +11,7 @@ settings_2nd = { | |
| 11 11 | 
             
              ca_file: File.exist?(ca_file) ? ca_file : nil,
         | 
| 12 12 | 
             
              alpn: ['http/1.1']
         | 
| 13 13 | 
             
            }
         | 
| 14 | 
            -
            process_new_session_ticket =  | 
| 14 | 
            +
            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
         | 
| @@ -36,7 +36,7 @@ succeed_early_data = false | |
| 36 36 | 
             
              settings_2nd
         | 
| 37 37 | 
             
            ].each_with_index do |settings, i|
         | 
| 38 38 | 
             
              socket = TCPSocket.new(hostname, port)
         | 
| 39 | 
            -
              client = TTTLS13::Client.new(socket, hostname, settings)
         | 
| 39 | 
            +
              client = TTTLS13::Client.new(socket, hostname, **settings)
         | 
| 40 40 |  | 
| 41 41 | 
             
              # send message using early data; 0-RTT
         | 
| 42 42 | 
             
              client.early_data(req) if i == 1 && settings.include?(:ticket)
         | 
| @@ -13,7 +13,7 @@ settings = { | |
| 13 13 | 
             
              key_share_groups: [], # empty KeyShareClientHello.client_shares
         | 
| 14 14 | 
             
              alpn: ['http/1.1']
         | 
| 15 15 | 
             
            }
         | 
| 16 | 
            -
            client = TTTLS13::Client.new(socket, hostname, settings)
         | 
| 16 | 
            +
            client = TTTLS13::Client.new(socket, hostname, **settings)
         | 
| 17 17 | 
             
            client.connect
         | 
| 18 18 | 
             
            client.write(req)
         | 
| 19 19 | 
             
            print recv_http_response(client)
         | 
| @@ -11,7 +11,7 @@ settings_2nd = { | |
| 11 11 | 
             
              ca_file: File.exist?(ca_file) ? ca_file : nil,
         | 
| 12 12 | 
             
              alpn: ['http/1.1']
         | 
| 13 13 | 
             
            }
         | 
| 14 | 
            -
            process_new_session_ticket =  | 
| 14 | 
            +
            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[:key_share_groups] = [] # empty KeyShareClientHello.client_shares
         | 
| @@ -35,7 +35,7 @@ settings_1st = { | |
| 35 35 | 
             
              settings_2nd
         | 
| 36 36 | 
             
            ].each do |settings|
         | 
| 37 37 | 
             
              socket = TCPSocket.new(hostname, port)
         | 
| 38 | 
            -
              client = TTTLS13::Client.new(socket, hostname, settings)
         | 
| 38 | 
            +
              client = TTTLS13::Client.new(socket, hostname, **settings)
         | 
| 39 39 | 
             
              client.connect
         | 
| 40 40 | 
             
              client.write(req)
         | 
| 41 41 | 
             
              print recv_http_response(client)
         | 
| @@ -7,7 +7,7 @@ hostname, port = (ARGV[0] || 'localhost:4433').split(':') | |
| 7 7 | 
             
            ca_file = __dir__ + '/../tmp/ca.crt'
         | 
| 8 8 | 
             
            req = simple_http_request(hostname)
         | 
| 9 9 |  | 
| 10 | 
            -
            process_certificate_status =  | 
| 10 | 
            +
            process_certificate_status = lambda do |res, cert, chain|
         | 
| 11 11 | 
             
              puts 'stapled OCSPResponse: '
         | 
| 12 12 | 
             
              puts res.basic.status.pretty_inspect unless res.nil?
         | 
| 13 13 | 
             
              puts '-' * 10
         | 
| @@ -22,7 +22,7 @@ settings = { | |
| 22 22 | 
             
              check_certificate_status: true,
         | 
| 23 23 | 
             
              process_certificate_status: process_certificate_status
         | 
| 24 24 | 
             
            }
         | 
| 25 | 
            -
            client = TTTLS13::Client.new(socket, hostname, settings)
         | 
| 25 | 
            +
            client = TTTLS13::Client.new(socket, hostname, **settings)
         | 
| 26 26 | 
             
            client.connect
         | 
| 27 27 | 
             
            client.write(req)
         | 
| 28 28 |  | 
| @@ -11,7 +11,7 @@ settings_2nd = { | |
| 11 11 | 
             
              ca_file: File.exist?(ca_file) ? ca_file : nil,
         | 
| 12 12 | 
             
              alpn: ['http/1.1']
         | 
| 13 13 | 
             
            }
         | 
| 14 | 
            -
            process_new_session_ticket =  | 
| 14 | 
            +
            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
         | 
| @@ -34,7 +34,7 @@ settings_1st = { | |
| 34 34 | 
             
              settings_2nd
         | 
| 35 35 | 
             
            ].each do |settings|
         | 
| 36 36 | 
             
              socket = TCPSocket.new(hostname, port)
         | 
| 37 | 
            -
              client = TTTLS13::Client.new(socket, hostname, settings)
         | 
| 37 | 
            +
              client = TTTLS13::Client.new(socket, hostname, **settings)
         | 
| 38 38 | 
             
              client.connect
         | 
| 39 39 | 
             
              client.write(req)
         | 
| 40 40 | 
             
              print recv_http_response(client)
         | 
    
        data/example/https_server.rb
    CHANGED
    
    | @@ -23,10 +23,10 @@ Etc.nprocessors.times do | |
| 23 23 | 
             
                loop do
         | 
| 24 24 | 
             
                  s = q.pop
         | 
| 25 25 | 
             
                  Timeout.timeout(1) do
         | 
| 26 | 
            -
                    server = TTTLS13::Server.new(s, settings)
         | 
| 26 | 
            +
                    server = TTTLS13::Server.new(s, **settings)
         | 
| 27 27 | 
             
                    parser = HTTP::Parser.new
         | 
| 28 28 |  | 
| 29 | 
            -
                    parser.on_message_complete =  | 
| 29 | 
            +
                    parser.on_message_complete = lambda do
         | 
| 30 30 | 
             
                      if !parser.http_method.nil?
         | 
| 31 31 | 
             
                        logger.info 'Receive Request'
         | 
| 32 32 | 
             
                        server.write(simple_http_response('TEST'))
         | 
    
        data/interop/client_spec.rb
    CHANGED
    
    | @@ -7,14 +7,13 @@ FIXTURES_DIR = __dir__ + '/../spec/fixtures' | |
| 7 7 | 
             
            PORT = 4433
         | 
| 8 8 |  | 
| 9 9 | 
             
            RSpec.describe Client do
         | 
| 10 | 
            -
              # testcases
         | 
| 11 10 | 
             
              # normal [Boolean] Is this nominal scenarios?
         | 
| 12 11 | 
             
              # opt [String] openssl s_server options
         | 
| 13 12 | 
             
              # crt [String] server crt file path
         | 
| 14 13 | 
             
              # key [String] server key file path
         | 
| 15 14 | 
             
              # settings [Hash] TTTLS13::Server settings
         | 
| 16 | 
            -
               | 
| 17 | 
            -
             | 
| 15 | 
            +
              # rubocop: disable Layout/LineLength
         | 
| 16 | 
            +
              testcases = [
         | 
| 18 17 | 
             
                [
         | 
| 19 18 | 
             
                  true,
         | 
| 20 19 | 
             
                  '-ciphersuites TLS_AES_256_GCM_SHA384',
         | 
| @@ -163,8 +162,9 @@ RSpec.describe Client do | |
| 163 162 | 
             
                  'rsa_rsa.key',
         | 
| 164 163 | 
             
                  compatibility_mode: false
         | 
| 165 164 | 
             
                ]
         | 
| 166 | 
            -
             | 
| 167 | 
            -
               | 
| 165 | 
            +
              ]
         | 
| 166 | 
            +
              # rubocop: enable Layout/LineLength
         | 
| 167 | 
            +
              testcases.each do |normal, opt, crt, key, settings|
         | 
| 168 168 | 
             
                context 'client interop' do
         | 
| 169 169 | 
             
                  before do
         | 
| 170 170 | 
             
                    cmd = 'openssl s_server ' \
         | 
| @@ -187,7 +187,7 @@ RSpec.describe Client do | |
| 187 187 | 
             
                    hostname = 'localhost'
         | 
| 188 188 | 
             
                    @socket = TCPSocket.new(hostname, PORT)
         | 
| 189 189 | 
             
                    settings[:ca_file] = FIXTURES_DIR + '/rsa_ca.crt'
         | 
| 190 | 
            -
                    Client.new(@socket, hostname, settings)
         | 
| 190 | 
            +
                    Client.new(@socket, hostname, **settings)
         | 
| 191 191 | 
             
                  end
         | 
| 192 192 |  | 
| 193 193 | 
             
                  after do
         | 
    
        data/interop/server_spec.rb
    CHANGED
    
    | @@ -9,14 +9,13 @@ PORT = 4433 | |
| 9 9 | 
             
            tcpserver = TCPServer.open(PORT)
         | 
| 10 10 |  | 
| 11 11 | 
             
            RSpec.describe Server do
         | 
| 12 | 
            -
              # testcases
         | 
| 13 12 | 
             
              # normal [Boolean] Is this nominal scenarios?
         | 
| 14 13 | 
             
              # opt [String] openssl s_client options
         | 
| 15 14 | 
             
              # crt [String] server crt file path
         | 
| 16 15 | 
             
              # key [String] server key file path
         | 
| 17 16 | 
             
              # settings [Hash] TTTLS13::Client settins
         | 
| 18 | 
            -
               | 
| 19 | 
            -
             | 
| 17 | 
            +
              # rubocop: disable Layout/LineLength
         | 
| 18 | 
            +
              testcases = [
         | 
| 20 19 | 
             
                [
         | 
| 21 20 | 
             
                  true,
         | 
| 22 21 | 
             
                  '-groups P-256:P-384:P-521 -ciphersuites TLS_AES_256_GCM_SHA384',
         | 
| @@ -172,8 +171,9 @@ RSpec.describe Server do | |
| 172 171 | 
             
                  FIXTURES_DIR + '/rsa_rsa.key',
         | 
| 173 172 | 
             
                  compatibility_mode: false
         | 
| 174 173 | 
             
                ]
         | 
| 175 | 
            -
             | 
| 176 | 
            -
               | 
| 174 | 
            +
              ]
         | 
| 175 | 
            +
              # rubocop: enable Layout/LineLength
         | 
| 176 | 
            +
              testcases.each do |normal, opt, crt, key, settings|
         | 
| 177 177 | 
             
                context 'server interop' do
         | 
| 178 178 | 
             
                  let(:server) do
         | 
| 179 179 | 
             
                    loop do
         | 
| @@ -182,7 +182,7 @@ RSpec.describe Server do | |
| 182 182 | 
             
                    end
         | 
| 183 183 | 
             
                    settings[:crt_file] = crt
         | 
| 184 184 | 
             
                    settings[:key_file] = key
         | 
| 185 | 
            -
                    Server.new(@socket, settings)
         | 
| 185 | 
            +
                    Server.new(@socket, **settings)
         | 
| 186 186 | 
             
                  end
         | 
| 187 187 |  | 
| 188 188 | 
             
                  let(:client) do
         |