svcb_rr_patch 0.0.4 → 0.0.6

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +6 -5
  3. data/.rubocop.yml +1 -1
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -3
  6. data/README.md +11 -12
  7. data/lib/svcb_rr_patch/https.rb +1 -6
  8. data/lib/svcb_rr_patch/svc_params/alpn.rb +1 -1
  9. data/lib/svcb_rr_patch/svc_params/ech.rb +8 -45
  10. data/lib/svcb_rr_patch/svc_params/ipv4hint.rb +1 -1
  11. data/lib/svcb_rr_patch/svc_params/ipv6hint.rb +1 -1
  12. data/lib/svcb_rr_patch/svc_params/mandatory.rb +3 -9
  13. data/lib/svcb_rr_patch/svc_params/port.rb +1 -1
  14. data/lib/svcb_rr_patch/svc_params.rb +44 -22
  15. data/lib/svcb_rr_patch/svcb.rb +7 -9
  16. data/lib/svcb_rr_patch/version.rb +1 -1
  17. data/lib/svcb_rr_patch.rb +1 -0
  18. data/spec/alpn_spec.rb +1 -1
  19. data/spec/ipv4hint_spec.rb +1 -1
  20. data/spec/ipv6hint_spec.rb +1 -1
  21. data/spec/mandatory_spec.rb +8 -8
  22. data/spec/no_default_alpn_spec.rb +1 -1
  23. data/spec/port_spec.rb +1 -1
  24. data/spec/svc_params_spec.rb +4 -3
  25. data/svcb_rr_patch.gemspec +2 -1
  26. metadata +19 -12
  27. data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/extension.rb +0 -34
  28. data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_kem_id.rb +0 -22
  29. data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_public_key.rb +0 -20
  30. data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_symmetric_cipher_suite/hpke_aead_id.rb +0 -22
  31. data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_symmetric_cipher_suite/hpke_kdf_id.rb +0 -22
  32. data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_symmetric_cipher_suite.rb +0 -41
  33. data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config.rb +0 -77
  34. data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents.rb +0 -69
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 607172ae2b63afd7c66a3cfe87456873eb1f436c28f0380a52edeeb31d9f3902
4
- data.tar.gz: b8a3b83f4820b78fb3efcb27b675a3cf07a58f360fe7d3c3a93fdd7161ced077
3
+ metadata.gz: 7a695feb098bc9703ae3959c87c0b70ae5818f10b124c2e8ba538ba0e76d4cd0
4
+ data.tar.gz: 1f8dd380eddbc47c974563508fea1517110c4fd223ae631f9a2a782fd6f51e9c
5
5
  SHA512:
6
- metadata.gz: 7125f6c9205f872a12574801bf5026073cd4d028640afbaefdf2a2ee69f11cc832167d4612341c475605306705af0742bb724fc241f482c85af8fe1e8a4f61d1
7
- data.tar.gz: 9217eca73420740086db7877bd5ff05e024ece6f6ecda1ad0d6b30e50cb1966da733b32f3daab8518a1180d25c6a0de1a8c7dab4105e132e186ae21a956e419b
6
+ metadata.gz: 004cfdf5b89a512e9c48e4d10d2fca603c8b59f6e8564bd35544b6c0d8915f1c07404d2358f9bd32468ac5cf7f13a1859f0ab9e7ada4e24bb67cc1dbd0da60fa
7
+ data.tar.gz: b7be41bd51be17ec5737463157fdf1fae4de250dda739c3074bf21931fe97e3589a9b3724400f87a9082f0e7c6c3b5247510f739fad5edf76d9d4a183fb2c64b
@@ -3,7 +3,7 @@ name: CI
3
3
  on:
4
4
  push:
5
5
  branches:
6
- - master
6
+ - main
7
7
  pull_request:
8
8
  branches:
9
9
  - '*'
@@ -13,11 +13,12 @@ jobs:
13
13
  runs-on: ubuntu-latest
14
14
  strategy:
15
15
  matrix:
16
- ruby-version: ['2.7.x', '3.0.x']
16
+ ruby-version: ['2.7.x', '3.0.x', '3.1.x']
17
17
  steps:
18
- - name: Set up Ruby
19
- uses: actions/setup-ruby@v1
20
- - uses: actions/checkout@v1
18
+ - uses: actions/checkout@v3
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
21
22
  - name: Install dependencies
22
23
  run: |
23
24
  gem --version
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.6
2
+ TargetRubyVersion: 2.7
3
3
 
4
4
  Style/ConditionalAssignment:
5
5
  Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.1.2
data/Gemfile CHANGED
@@ -2,12 +2,13 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gem 'rake'
5
+ gem 'ech_config'
6
6
 
7
7
  group :test do
8
8
  gem 'byebug'
9
- gem 'rspec', '3.9.0'
10
- gem 'rubocop', '0.78.0'
9
+ gem 'rake'
10
+ gem 'rspec', '3.11'
11
+ gem 'rubocop', '1.35'
11
12
  end
12
13
 
13
14
  gemspec
data/README.md CHANGED
@@ -6,16 +6,16 @@
6
6
 
7
7
  `svcb_rr_patch` is the patch that adds SVCB Resource Record and HTTPS Resource Record.
8
8
 
9
- - https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-06
9
+ - https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-06.html
10
10
 
11
- `svcb_rr_patch` supports "ech" SvcParamKey that ECHConfig.version is `0xfe0d`.
11
+ `svcb_rr_patch` supports "ech" SvcParamKey that ECHConfig.version is `0xfe0b` ~ `0xfe0f`.
12
12
 
13
- - https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-13#section-4
13
+ - https://author-tools.ietf.org/iddiff?url2=draft-ietf-tls-esni-11.txt#context-3
14
14
 
15
15
 
16
16
  ## Installation
17
17
 
18
- he gem is available at [rubygems.org](https://rubygems.org/gems/svcb_rr_patch). You can install it the following.
18
+ The gem is available at [rubygems.org](https://rubygems.org/gems/svcb_rr_patch). You can install it the following.
19
19
 
20
20
  ```sh-session
21
21
  $ gem install svcb_rr_patch
@@ -26,20 +26,19 @@ $ gem install svcb_rr_patch
26
26
 
27
27
  You can resolve HTTPS resources.
28
28
 
29
- ```sh-session
29
+ ```ruby
30
30
  $ irb
31
31
  irb(main):001:0> require 'svcb_rr_patch'
32
32
  => true
33
- irb(main):002:1* Resolv::DNS.new.getresources(
34
- irb(main):003:1* "blog.cloudflare.com",
33
+ irb(main):002:1* rr = Resolv::DNS.new.getresources(
34
+ irb(main):003:1* "crypto.cloudflare.com",
35
35
  irb(main):004:1* Resolv::DNS::Resource::IN::HTTPS
36
36
  irb(main):005:0> )
37
37
  =>
38
- [#<Resolv::DNS::Resource::IN::HTTPS:0x0000000000000001
39
- @svc_params={"alpn"=>h3,h3-29,h3-28,h3-27,h2, "ipv4hint"=>104.18.26.46,104.18.27.46, "ipv6hint"=>2606:4700::6812:1a2e,2606:4700::6812:1b2e},
40
- @svc_priority=1,
41
- @target_name="",
42
- @ttl=300>]
38
+ [#<Resolv::DNS::Resource::IN::HTTPS:0x0000000000000000
39
+ ...
40
+ irb(main):006:0> rr.first.svc_params.to_s
41
+ => "alpn=http/1.1,h2 ipv4hint=162.159.137.85,162.159.138.85 ech=AEb+DQBC4wAgACCaqAJAAhqN4e1k2RSa+rFgJCpJNOapZy5FdQZUN5ITXAAEAAEAAQATY2xvdWRmbGFyZS1lc25pLmNvbQAA ipv6hint=2606:4700:7::a29f:8955,2606:4700:7::a29f:8a55"
43
42
  ```
44
43
 
45
44
 
@@ -8,11 +8,6 @@ class Resolv::DNS::Resource::IN::HTTPS < Resolv::DNS::Resource::IN::SVCB
8
8
  ClassValue = IN::ClassValue
9
9
  ClassHash[[TypeValue, ClassValue]] = self
10
10
 
11
- def initialize(svc_priority, target_name, svc_params)
12
- # https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-06
13
- super(svc_priority, target_name, svc_params)
14
- end
15
-
16
11
  class << self
17
12
  # :nodoc:
18
13
  def decode_rdata(msg)
@@ -21,7 +16,7 @@ class Resolv::DNS::Resource::IN::HTTPS < Resolv::DNS::Resource::IN::SVCB
21
16
  return new(svc_priority, target_name, {}) if svc_priority.zero?
22
17
 
23
18
  # the SvcParams, consuming the remainder of the record
24
- svc_params = ::SvcbRrPatch::SvcParams.decode(msg.get_bytes)
19
+ svc_params = ::SvcbRrPatch::SvcParams::Hash.decode(msg.get_bytes)
25
20
  new(svc_priority, target_name, svc_params)
26
21
  end
27
22
  end
@@ -37,7 +37,7 @@ class SvcbRrPatch::SvcParams::Alpn
37
37
  end
38
38
 
39
39
  # :nodoc:
40
- def inspect
40
+ def to_s
41
41
  @protocols.join(',')
42
42
  end
43
43
  end
@@ -18,56 +18,19 @@ class SvcbRrPatch::SvcParams::Ech
18
18
  raise ::Resolv::DNS::DecodeError \
19
19
  unless octet.length == octet.slice(0, 2).unpack1('n') + 2
20
20
 
21
- echconfiglist = ECHConfig.decode_vectors(octet.slice(2..))
21
+ begin
22
+ echconfiglist = ::ECHConfig.decode_vectors(octet.slice(2..))
23
+ rescue ::ECHConfig::Error
24
+ raise ::Resolv::DNS::DecodeError
25
+ end
26
+
22
27
  new(echconfiglist)
23
28
  end
24
29
 
25
- # https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-06#section-9
30
+ # https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-06.html#section-9
26
31
  # In presentation format, the value is a single ECHConfigList encoded in
27
32
  # Base64.
28
- def inspect
33
+ def to_s
29
34
  Base64.strict_encode64(encode)
30
35
  end
31
36
  end
32
-
33
- require_relative 'ech/echconfig_contents'
34
-
35
- class SvcbRrPatch::SvcParams::Ech::ECHConfig
36
- attr_reader :version
37
- attr_reader :echconfigcontents
38
-
39
- ECHConfigContents = ::SvcbRrPatch::SvcParams::Ech::ECHConfigContents
40
-
41
- # @param version [String]
42
- # @param echconfig_contents [ECHConfigContents]
43
- def initialize(version, echconfig_contents)
44
- @version = version
45
- @echconfig_contents = echconfig_contents
46
- end
47
-
48
- # @return [String]
49
- def encode
50
- @version + @echconfig_contents.encode.then { |s| [s.length].pack('n') + s }
51
- end
52
-
53
- # @return [Array of ECHConfig]
54
- def self.decode_vectors(octet)
55
- i = 0
56
- echconfigs = []
57
- while i < octet.length
58
- raise ::Resolv::DNS::DecodeError if i + 4 > octet.length
59
-
60
- version = octet.slice(i, 2)
61
- length = octet.slice(i + 2, 2).unpack1('n')
62
- i += 4
63
- raise ::Resolv::DNS::DecodeError if i + length > octet.length
64
-
65
- echconfig_contents = ECHConfigContents.decode(octet.slice(i, length))
66
- i += length
67
- echconfigs << new(version, echconfig_contents)
68
- end
69
- raise ::Resolv::DNS::DecodeError if i != octet.length
70
-
71
- echconfigs
72
- end
73
- end
@@ -20,7 +20,7 @@ class SvcbRrPatch::SvcParams::Ipv4hint
20
20
  end
21
21
 
22
22
  # :nodoc:
23
- def inspect
23
+ def to_s
24
24
  @addresses.join(',')
25
25
  end
26
26
  end
@@ -20,7 +20,7 @@ class SvcbRrPatch::SvcParams::Ipv6hint
20
20
  end
21
21
 
22
22
  # :nodoc:
23
- def inspect
23
+ def to_s
24
24
  @addresses.join(',')
25
25
  end
26
26
  end
@@ -17,18 +17,12 @@ class SvcbRrPatch::SvcParams::Mandatory
17
17
  def self.decode(octet)
18
18
  keys = octet.scan(/.{1,2}/)
19
19
  .map { |s| s.unpack1('n') }
20
- .filter { |i| i < 7 || i >= 65280 && i < 65535 }
21
20
  new(keys)
22
21
  end
23
22
 
24
23
  # :nodoc:
25
- def inspect
26
- @keys.map do |i|
27
- if i < 7 || i >= 65280 && i < 65535
28
- SvcbRrPatch::SvcParams::PARAMETER_REGISTRY[i]
29
- else
30
- ''
31
- end
32
- end.join(',')
24
+ def to_s
25
+ @keys.map { |i| SvcbRrPatch::SvcParams::PARAMETER_REGISTRY[i] }
26
+ .join(',')
33
27
  end
34
28
  end
@@ -20,7 +20,7 @@ class SvcbRrPatch::SvcParams::Port
20
20
  end
21
21
 
22
22
  # :nodoc:
23
- def inspect
23
+ def to_s
24
24
  @port.to_s
25
25
  end
26
26
  end
@@ -12,23 +12,32 @@ module SvcbRrPatch::SvcParams
12
12
  ipv6hint
13
13
  ]
14
14
  # rubocop:disable Security/Eval
15
+ (8...65280).each do |nnnn|
16
+ eval "registry[nnnn] = \"undefine#{nnnn}\"", binding, __FILE__, __LINE__
17
+ end
15
18
  (65280...65535).each do |nnnn|
16
19
  eval "registry[nnnn] = \"key#{nnnn}\"", binding, __FILE__, __LINE__
17
20
  end
18
21
  # rubocop:enable Security/Eval
19
22
  registry
20
23
  }.call.freeze
24
+
25
+ PARAMETER_REGISTRY_INVERT = lambda {
26
+ Hash[(0..PARAMETER_REGISTRY.size - 1).zip(PARAMETER_REGISTRY)].invert
27
+ }.call.freeze
21
28
  end
22
29
 
23
- Dir[File.dirname(__FILE__) + '/svc_params/*.rb'].sort.each { |f| require f }
30
+ Dir["#{File.dirname(__FILE__)}/svc_params/*.rb"].sort.each { |f| require f }
24
31
 
25
- module SvcbRrPatch::SvcParams
26
- # @return [String]
27
- def self.encode(svc_params)
28
- h = Hash[(0..PARAMETER_REGISTRY.size - 1).zip(PARAMETER_REGISTRY)].invert
32
+ class SvcbRrPatch::SvcParams::Hash
33
+ def initialize(hash)
34
+ @hash = hash
35
+ end
29
36
 
30
- svc_params
31
- .map { |k, v| [h[k], v] }
37
+ # @return [String]
38
+ def encode
39
+ @hash
40
+ .map { |k, v| [SvcbRrPatch::SvcParams::PARAMETER_REGISTRY_INVERT[k], v] }
32
41
  .sort { |lh, rh| lh.first <=> rh.first }
33
42
  .map do |k, v|
34
43
  [k].pack('n') + v.encode.then { |s| [s.length].pack('n') + s }
@@ -38,19 +47,18 @@ module SvcbRrPatch::SvcParams
38
47
 
39
48
  # @param octet [String]
40
49
  #
41
- # @return [Hash] Integer => SvcbRrPatch::$Object
42
- # rubocop:disable Metrics/AbcSize
50
+ # @return [Hash]
43
51
  def self.decode(octet)
44
52
  svc_params = {}
45
53
  i = 0
46
- h = Hash[(0..PARAMETER_REGISTRY.size - 1).zip(PARAMETER_REGISTRY)].invert
47
54
  while i < octet.length
48
55
  raise ::Resolv::DNS::DecodeError if i + 4 > octet.length
49
56
 
50
57
  k = octet.slice(i, 2).unpack1('n')
51
58
  # SvcParamKeys SHALL appear in increasing numeric order.
52
- raise ::Resolv::DNS::DecodeError \
53
- unless svc_params.keys.find { |already| h[already] >= k }.nil?
59
+ raise ::Resolv::DNS::DecodeError unless svc_params.keys.find do |key|
60
+ SvcbRrPatch::SvcParams::PARAMETER_REGISTRY_INVERT[key] >= k
61
+ end.nil?
54
62
 
55
63
  i += 2
56
64
  vlen = octet.slice(i, 2).unpack1('n')
@@ -60,37 +68,51 @@ module SvcbRrPatch::SvcParams
60
68
  v = octet.slice(i, vlen)
61
69
  i += vlen
62
70
  # Values are in a format specific to the SvcParamKey.
63
- svc_param_key = PARAMETER_REGISTRY[k]
71
+ svc_param_key = SvcbRrPatch::SvcParams::PARAMETER_REGISTRY[k]
64
72
  svc_param_values = decode_svc_params(svc_param_key, v)
65
73
  svc_params.store(svc_param_key, svc_param_values)
66
74
  end
67
75
  raise ::Resolv::DNS::DecodeError if i != octet.length
68
76
 
69
- svc_params
77
+ new(svc_params)
70
78
  end
71
- # rubocop:enable Metrics/AbcSize
72
79
 
73
80
  # :nodoc:
74
81
  # rubocop:disable Metrics/CyclomaticComplexity
75
82
  def self.decode_svc_params(key, octet)
76
83
  case key
77
84
  when 'mandatory'
78
- Mandatory.decode(octet)
85
+ SvcbRrPatch::SvcParams::Mandatory.decode(octet)
79
86
  when 'alpn'
80
- Alpn.decode(octet)
87
+ SvcbRrPatch::SvcParams::Alpn.decode(octet)
81
88
  when 'no-default-alpn'
82
- NoDefaultAlpn.decode(octet)
89
+ SvcbRrPatch::SvcParams::NoDefaultAlpn.decode(octet)
83
90
  when 'port'
84
- Port.decode(octet)
91
+ SvcbRrPatch::SvcParams::Port.decode(octet)
85
92
  when 'ipv4hint'
86
- Ipv4hint.decode(octet)
93
+ SvcbRrPatch::SvcParams::Ipv4hint.decode(octet)
87
94
  when 'ech'
88
- Ech.decode(octet)
95
+ SvcbRrPatch::SvcParams::Ech.decode(octet)
89
96
  when 'ipv6hint'
90
- Ipv6hint.decode(octet)
97
+ SvcbRrPatch::SvcParams::Ipv6hint.decode(octet)
91
98
  else
92
99
  octet
93
100
  end
94
101
  end
95
102
  # rubocop:enable Metrics/CyclomaticComplexity
103
+
104
+ # :nodoc:
105
+ def [](key)
106
+ @hash[key]
107
+ end
108
+
109
+ # :nodoc:
110
+ def keys
111
+ @hash.keys
112
+ end
113
+
114
+ # :nodoc:
115
+ def to_s
116
+ @hash.map { |k, v| "#{k}=#{v}" }.join(' ')
117
+ end
96
118
  end
@@ -10,34 +10,32 @@ class Resolv::DNS::Resource::IN::SVCB < Resolv::DNS::Resource
10
10
 
11
11
  # @param svc_priority [Integer]
12
12
  # @param target_name [String]
13
- # @param svc_params [Map]
13
+ # @param svc_params [Hash]
14
+ # rubocop: disable Lint/MissingSuper
14
15
  def initialize(svc_priority, target_name, svc_params)
15
- # https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-06
16
+ # https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-06.html
16
17
  @svc_priority = svc_priority
17
18
  @target_name = target_name
18
19
  @svc_params = svc_params
19
20
  end
21
+ # rubocop: enable Lint/MissingSuper
20
22
 
21
23
  ##
22
24
  # SvcPriority
23
25
 
24
- attr_reader :svc_priority
26
+ attr_reader :svc_priority, :target_name, :svc_params
25
27
 
26
28
  ##
27
29
  # TargetName
28
30
 
29
- attr_reader :target_name
30
-
31
31
  ##
32
32
  # SvcParams
33
33
 
34
- attr_reader :svc_params
35
-
36
34
  # :nodoc:
37
35
  def encode_rdata(msg)
38
36
  msg.put_bytes([@svc_priority].pack('n'))
39
37
  msg.put_string(@target_name)
40
- msg.put_string(::SvcbRrPatch::SvcParams.encode(@svc_params))
38
+ msg.put_string(@svc_params.encode)
41
39
  end
42
40
 
43
41
  class << self
@@ -48,7 +46,7 @@ class Resolv::DNS::Resource::IN::SVCB < Resolv::DNS::Resource
48
46
  return new(svc_priority, target_name, {}) if svc_priority.zero?
49
47
 
50
48
  # the SvcParams, consuming the remainder of the record
51
- svc_params = ::SvcbRrPatch::SvcParams.decode(msg.get_bytes)
49
+ svc_params = ::SvcbRrPatch::SvcParams::Hash.decode(msg.get_bytes)
52
50
  new(svc_priority, target_name, svc_params)
53
51
  end
54
52
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SvcbRrPatch
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.6'
5
5
  end
data/lib/svcb_rr_patch.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'base64'
4
+ require 'ech_config'
4
5
  require 'resolv'
5
6
 
6
7
  require 'svcb_rr_patch/version'
data/spec/alpn_spec.rb CHANGED
@@ -25,7 +25,7 @@ RSpec.describe SvcbRrPatch::SvcParams::Alpn do
25
25
 
26
26
  it 'could encode' do
27
27
  expect(alpn.encode).to eq octet
28
- expect(alpn.inspect).to eq 'h3-29,h3-28,h3-27,h2'
28
+ expect(alpn.to_s).to eq 'h3-29,h3-28,h3-27,h2'
29
29
  end
30
30
  end
31
31
  end
@@ -33,7 +33,7 @@ RSpec.describe SvcbRrPatch::SvcParams::Ipv4hint do
33
33
 
34
34
  it 'could encode' do
35
35
  expect(ipv4hint.encode).to eq octet
36
- expect(ipv4hint.inspect).to eq '192.0.2.1,192.0.2.2'
36
+ expect(ipv4hint.to_s).to eq '192.0.2.1,192.0.2.2'
37
37
  end
38
38
  end
39
39
  end
@@ -36,7 +36,7 @@ RSpec.describe SvcbRrPatch::SvcParams::Ipv6hint do
36
36
 
37
37
  it 'could encode' do
38
38
  expect(ipv6hint.encode).to eq octet
39
- expect(ipv6hint.inspect).to eq '2001:db8::1,2001:db8::2'
39
+ expect(ipv6hint.to_s).to eq '2001:db8::1,2001:db8::2'
40
40
  end
41
41
  end
42
42
  end
@@ -5,16 +5,16 @@ require_relative 'spec_helper'
5
5
 
6
6
  RSpec.describe SvcbRrPatch::SvcParams::Mandatory do
7
7
  let(:octet) do
8
- "\x00\x05\x00\x06\xff\xa4"
8
+ "\x00\x05\x00\x06\x00\x08\xff\xa4"
9
9
  end
10
10
 
11
11
  let(:keys) do
12
- h = Hash[
13
- (0..SvcbRrPatch::SvcParams::PARAMETER_REGISTRY.size - 1)
14
- .zip(SvcbRrPatch::SvcParams::PARAMETER_REGISTRY)
15
- ].invert
16
-
17
- [h['ech'], h['ipv6hint'], h['key65444']]
12
+ [
13
+ SvcbRrPatch::SvcParams::PARAMETER_REGISTRY_INVERT['ech'],
14
+ SvcbRrPatch::SvcParams::PARAMETER_REGISTRY_INVERT['ipv6hint'],
15
+ SvcbRrPatch::SvcParams::PARAMETER_REGISTRY_INVERT['undefine8'],
16
+ SvcbRrPatch::SvcParams::PARAMETER_REGISTRY_INVERT['key65444']
17
+ ]
18
18
  end
19
19
 
20
20
  context '#decode' do
@@ -34,7 +34,7 @@ RSpec.describe SvcbRrPatch::SvcParams::Mandatory do
34
34
 
35
35
  it 'could encode' do
36
36
  expect(mandatory.encode).to eq octet
37
- expect(mandatory.inspect).to eq 'ech,ipv6hint,key65444'
37
+ expect(mandatory.to_s).to eq 'ech,ipv6hint,undefine8,key65444'
38
38
  end
39
39
  end
40
40
  end
@@ -30,7 +30,7 @@ RSpec.describe SvcbRrPatch::SvcParams::NoDefaultAlpn do
30
30
  expect(no_default_alpn)
31
31
  .to be_a(SvcbRrPatch::SvcParams::NoDefaultAlpn)
32
32
  expect(no_default_alpn.encode).to eq octet
33
- expect(no_default_alpn.inspect).to eq 'h3-29,h3-28,h3-27,h2'
33
+ expect(no_default_alpn.to_s).to eq 'h3-29,h3-28,h3-27,h2'
34
34
  end
35
35
  end
36
36
  end
data/spec/port_spec.rb CHANGED
@@ -25,7 +25,7 @@ RSpec.describe SvcbRrPatch::SvcParams::Port do
25
25
 
26
26
  it 'could encode' do
27
27
  expect(port.encode).to eq octet
28
- expect(port.inspect).to eq '443'
28
+ expect(port.to_s).to eq '443'
29
29
  end
30
30
  end
31
31
  end
@@ -45,7 +45,7 @@ RSpec.describe SvcbRrPatch::SvcParams do
45
45
 
46
46
  context '#decode' do
47
47
  let(:svc_params) do
48
- SvcbRrPatch::SvcParams.decode(octet)
48
+ SvcbRrPatch::SvcParams::Hash.decode(octet)
49
49
  end
50
50
 
51
51
  it 'could decode' do
@@ -60,16 +60,17 @@ RSpec.describe SvcbRrPatch::SvcParams do
60
60
 
61
61
  context '#encode' do
62
62
  let(:svc_params) do
63
- {
63
+ h = {
64
64
  'alpn' => alpn,
65
65
  'ipv4hint' => ipv4hint,
66
66
  'ipv6hint' => ipv6hint,
67
67
  'key65333' => key65333
68
68
  }
69
+ SvcbRrPatch::SvcParams::Hash.new(h)
69
70
  end
70
71
 
71
72
  it 'could encode' do
72
- expect(SvcbRrPatch::SvcParams.encode(svc_params)).to eq octet
73
+ expect(svc_params.encode).to eq octet
73
74
  end
74
75
  end
75
76
  end
@@ -14,11 +14,12 @@ Gem::Specification.new do |spec|
14
14
  spec.description = spec.summary
15
15
  spec.homepage = 'https://github.com/thekuwayama/svcb_rr_patch'
16
16
  spec.license = 'MIT'
17
- spec.required_ruby_version = '>=2.6.0'
17
+ spec.required_ruby_version = '>=2.7.0'
18
18
 
19
19
  spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
20
20
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
21
  spec.require_paths = ['lib']
22
22
 
23
23
  spec.add_development_dependency 'bundler'
24
+ spec.add_dependency 'ech_config'
24
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svcb_rr_patch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - thekuwayama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-12 00:00:00.000000000 Z
11
+ date: 2023-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ech_config
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description: the patch that adds SVCB Resource Record and HTTPS Resource Record
28
42
  email:
29
43
  - thekuwayama@gmail.com
@@ -34,6 +48,7 @@ files:
34
48
  - ".github/workflows/ci.yml"
35
49
  - ".gitignore"
36
50
  - ".rubocop.yml"
51
+ - ".ruby-version"
37
52
  - Gemfile
38
53
  - LICENSE.txt
39
54
  - README.md
@@ -43,14 +58,6 @@ files:
43
58
  - lib/svcb_rr_patch/svc_params.rb
44
59
  - lib/svcb_rr_patch/svc_params/alpn.rb
45
60
  - lib/svcb_rr_patch/svc_params/ech.rb
46
- - lib/svcb_rr_patch/svc_params/ech/echconfig_contents.rb
47
- - lib/svcb_rr_patch/svc_params/ech/echconfig_contents/extension.rb
48
- - lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config.rb
49
- - lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_kem_id.rb
50
- - lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_public_key.rb
51
- - lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_symmetric_cipher_suite.rb
52
- - lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_symmetric_cipher_suite/hpke_aead_id.rb
53
- - lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_symmetric_cipher_suite/hpke_kdf_id.rb
54
61
  - lib/svcb_rr_patch/svc_params/ipv4hint.rb
55
62
  - lib/svcb_rr_patch/svc_params/ipv6hint.rb
56
63
  - lib/svcb_rr_patch/svc_params/mandatory.rb
@@ -79,14 +86,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
86
  requirements:
80
87
  - - ">="
81
88
  - !ruby/object:Gem::Version
82
- version: 2.6.0
89
+ version: 2.7.0
83
90
  required_rubygems_version: !ruby/object:Gem::Requirement
84
91
  requirements:
85
92
  - - ">="
86
93
  - !ruby/object:Gem::Version
87
94
  version: '0'
88
95
  requirements: []
89
- rubygems_version: 3.2.22
96
+ rubygems_version: 3.3.7
90
97
  signing_key:
91
98
  specification_version: 4
92
99
  summary: the patch that adds SVCB Resource Record and HTTPS Resource Record
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents::Extension
4
- attr_reader :octet
5
-
6
- # @param octet [String]
7
- def initialize(octet)
8
- @octet = octet # TODO
9
- end
10
-
11
- # @return [String]
12
- def encode
13
- @octet # TODO
14
- end
15
-
16
- # @return [Array of Extension]
17
- def self.decode_vectors(octet)
18
- i = 0
19
- extensions = []
20
- while i < octet.length
21
- raise ::Resolv::DNS::DecodeError if i + 4 > octet.length
22
-
23
- ex_len = octet.slice(i + 2, 2)
24
- i += 4
25
- raise ::Resolv::DNS::DecodeError if i + ex_len > octet.length
26
-
27
- extensions << new(octet.slice(i, ex_len)) # TODO
28
- i += ex_len
29
- end
30
- raise ::Resolv::DNS::DecodeError if i != octet.length
31
-
32
- extensions
33
- end
34
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkeKemId
4
- attr_reader :uint16
5
-
6
- # @param uint16 [Integer]
7
- def initialize(uint16)
8
- @uint16 = uint16
9
- end
10
-
11
- # @return [String]
12
- def encode
13
- [@uint16].pack('n')
14
- end
15
-
16
- # :nodoc
17
- def self.decode(octet)
18
- raise ::Resolv::DNS::DecodeError if octet.length != 2
19
-
20
- new(octet.unpack1('n'))
21
- end
22
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkePublicKey # rubocop:disable Layout/LineLength
4
- attr_reader :opaque
5
-
6
- # @param opaque [String]
7
- def initialize(opaque)
8
- @opaque = opaque
9
- end
10
-
11
- # @return [String]
12
- def encode
13
- @opaque.then { |s| [s.length].pack('n') + s }
14
- end
15
-
16
- # :nodoc
17
- def self.decode(octet)
18
- new(octet)
19
- end
20
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite::HpkeAeadId # rubocop:disable Layout/LineLength
4
- attr_reader :uint16
5
-
6
- # @param uint16 [Integer]
7
- def initialize(uint16)
8
- @uint16 = uint16
9
- end
10
-
11
- # @return [String]
12
- def encode
13
- [@uint16].pack('n')
14
- end
15
-
16
- # :nodoc
17
- def self.decode(octet)
18
- raise ::Resolv::DNS::DecodeError if octet.length != 2
19
-
20
- new(octet.unpack1('n'))
21
- end
22
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite::HpkeKdfId # rubocop:disable Layout/LineLength
4
- attr_reader :uint16
5
-
6
- # @param uint16 [Integer]
7
- def initialize(uint16)
8
- @uint16 = uint16
9
- end
10
-
11
- # @return [String]
12
- def encode
13
- [@uint16].pack('n')
14
- end
15
-
16
- # :nodoc
17
- def self.decode(octet)
18
- raise ::Resolv::DNS::DecodeError if octet.length != 2
19
-
20
- new(octet.unpack1('n'))
21
- end
22
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite # rubocop:disable Layout/LineLength
4
- # define class
5
- end
6
-
7
- Dir[File.dirname(__FILE__) + '/hpke_symmetric_cipher_suite/*.rb']
8
- .sort.each { |f| require f }
9
-
10
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite # rubocop:disable Layout/LineLength
11
- attr_reader :kdf_id
12
- attr_reader :aead_id
13
-
14
- # @param kdf_id [HpkeKdfId]
15
- # @param aead_id [HpkeAeadId]
16
- def initialize(kdf_id, aead_id)
17
- @kdf_id = kdf_id
18
- @aead_id = aead_id
19
- end
20
-
21
- # @return [String]
22
- def encode
23
- @kdf_id.encode + @aead_id.encode
24
- end
25
-
26
- # @return [Array of HpkeSymmetricCipherSuite]
27
- def self.decode_vectors(octet)
28
- i = 0
29
- cipher_suites = []
30
- while i < octet.length
31
- raise ::Resolv::DNS::DecodeError if i + 4 > octet.length
32
-
33
- kdf_id = HpkeKdfId.decode(octet.slice(i, 2))
34
- aead_id = HpkeAeadId.decode(octet.slice(i + 2, 2))
35
- i += 4
36
- cipher_suites << new(kdf_id, aead_id)
37
- end
38
-
39
- cipher_suites
40
- end
41
- end
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig
4
- # define class
5
- end
6
-
7
- Dir[File.dirname(__FILE__) + '/hpke_key_config/*.rb']
8
- .sort.each { |f| require f }
9
-
10
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig
11
- attr_reader :config_id
12
- attr_reader :kem_id
13
- attr_reader :public_key
14
- attr_reader :cipher_suites
15
-
16
- # @param config_id [Integer]
17
- # @param kem_id [HpkeKemId]
18
- # @param public_key [HpkePublicKey]
19
- # @param cipher_suites [Array of HpkeSymmetricCipherSuite]
20
- def initialize(config_id,
21
- kem_id,
22
- public_key,
23
- cipher_suites)
24
- @config_id = config_id
25
- @kem_id = kem_id
26
- @public_key = public_key
27
- @cipher_suites = cipher_suites
28
- end
29
-
30
- # @return [String]
31
- def encode
32
- [@config_id].pack('C') \
33
- + @kem_id.encode \
34
- + @public_key.encode \
35
- + @cipher_suites.map(&:encode).join.then { |s| [s.length].pack('n') + s }
36
- end
37
-
38
- # :nodoc
39
- # rubocop:disable Metrics/AbcSize
40
- # rubocop:disable Metrics/CyclomaticComplexity
41
- def self.decode(octet)
42
- raise ::Resolv::DNS::DecodeError if octet.empty?
43
-
44
- config_id = octet.slice(0, 1).unpack1('C')
45
- i = 1
46
- raise ::Resolv::DNS::DecodeError if i + 2 > octet.length
47
-
48
- kem_id = HpkeKemId.decode(octet.slice(i, 2))
49
- i += 2
50
- raise ::Resolv::DNS::DecodeError if i + 2 > octet.length
51
-
52
- pk_len = octet.slice(i, 2).unpack1('n')
53
- i += 2
54
- raise ::Resolv::DNS::DecodeError if i + pk_len > octet.length
55
-
56
- public_key = HpkePublicKey.decode(octet.slice(i, pk_len))
57
- i += pk_len
58
- raise ::Resolv::DNS::DecodeError if i + 2 > octet.length
59
-
60
- cs_len = octet.slice(i, 2).unpack1('n')
61
- i += 2
62
- raise ::Resolv::DNS::DecodeError if i + 2 > octet.length
63
-
64
- cs_bin = octet.slice(i, cs_len)
65
- i += cs_len
66
- cipher_suites = HpkeSymmetricCipherSuite.decode_vectors(cs_bin)
67
- hpke_key_config = new(
68
- config_id,
69
- kem_id,
70
- public_key,
71
- cipher_suites
72
- )
73
- [hpke_key_config, octet[i..]]
74
- end
75
- # rubocop:enable Metrics/AbcSize
76
- # rubocop:enable Metrics/CyclomaticComplexity
77
- end
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents
4
- # define class
5
- end
6
-
7
- Dir[File.dirname(__FILE__) + '/echconfig_contents/*.rb']
8
- .sort.each { |f| require f }
9
-
10
- class SvcbRrPatch::SvcParams::Ech::ECHConfigContents
11
- attr_reader :key_config
12
- attr_reader :maximum_name_length
13
- attr_reader :public_name
14
- attr_reader :extensions
15
-
16
- # @param key_config [HpkeKeyConfig]
17
- # @param maximum_name_length [Integer]
18
- # @param public_name [String]
19
- # @param extensions [Array of Extension]
20
- def initialize(key_config,
21
- maximum_name_length,
22
- public_name,
23
- extensions)
24
- @key_config = key_config
25
- @maximum_name_length = maximum_name_length
26
- @public_name = public_name
27
- @extensions = extensions
28
- end
29
-
30
- # @return [String]
31
- def encode
32
- @key_config.encode \
33
- + [@maximum_name_length].pack('C') \
34
- + @public_name.then { |s| [s.length].pack('C') + s } \
35
- + @extensions.map(&:encode).join.then { |s| [s.length].pack('n') + s }
36
- end
37
-
38
- # :nodoc
39
- # rubocop:disable Metrics/AbcSize
40
- def self.decode(octet)
41
- key_config, octet = HpkeKeyConfig.decode(octet)
42
- raise ::Resolv::DNS::DecodeError if octet.length < 2
43
-
44
- maximum_name_length = octet.slice(0, 1).unpack1('C')
45
- pn_len = octet.slice(1, 1).unpack1('C')
46
- i = 2
47
- raise ::Resolv::DNS::DecodeError if i + pn_len > octet.length
48
-
49
- public_name = octet.slice(i, pn_len)
50
- i += pn_len
51
- raise ::Resolv::DNS::DecodeError if i + 2 > octet.length
52
-
53
- ex_len = octet.slice(i, 2).unpack1('n')
54
- i += 2
55
- raise ::Resolv::DNS::DecodeError if i + ex_len > octet.length
56
-
57
- extensions = Extension.decode_vectors(octet.slice(i, ex_len))
58
- i += ex_len
59
- raise ::Resolv::DNS::DecodeError if i != octet.length
60
-
61
- new(
62
- key_config,
63
- maximum_name_length,
64
- public_name,
65
- extensions
66
- )
67
- end
68
- # rubocop:enable Metrics/AbcSize
69
- end