svcb_rr_patch 0.0.5 → 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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +6 -5
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -0
- data/Gemfile +4 -3
- data/README.md +11 -38
- data/lib/svcb_rr_patch/https.rb +0 -5
- data/lib/svcb_rr_patch/svc_params/ech.rb +7 -44
- data/lib/svcb_rr_patch/svc_params.rb +75 -77
- data/lib/svcb_rr_patch/svcb.rb +4 -6
- data/lib/svcb_rr_patch/version.rb +1 -1
- data/lib/svcb_rr_patch.rb +1 -0
- data/spec/svc_params_spec.rb +0 -1
- data/svcb_rr_patch.gemspec +2 -1
- metadata +19 -12
- data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/extension.rb +0 -34
- data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_kem_id.rb +0 -22
- data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_public_key.rb +0 -20
- data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_symmetric_cipher_suite/hpke_aead_id.rb +0 -22
- data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_symmetric_cipher_suite/hpke_kdf_id.rb +0 -22
- data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config/hpke_symmetric_cipher_suite.rb +0 -41
- data/lib/svcb_rr_patch/svc_params/ech/echconfig_contents/hpke_key_config.rb +0 -77
- 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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7a695feb098bc9703ae3959c87c0b70ae5818f10b124c2e8ba538ba0e76d4cd0
|
|
4
|
+
data.tar.gz: 1f8dd380eddbc47c974563508fea1517110c4fd223ae631f9a2a782fd6f51e9c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 004cfdf5b89a512e9c48e4d10d2fca603c8b59f6e8564bd35544b6c0d8915f1c07404d2358f9bd32468ac5cf7f13a1859f0ab9e7ada4e24bb67cc1dbd0da60fa
|
|
7
|
+
data.tar.gz: b7be41bd51be17ec5737463157fdf1fae4de250dda739c3074bf21931fe97e3589a9b3724400f87a9082f0e7c6c3b5247510f739fad5edf76d9d4a183fb2c64b
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -3,7 +3,7 @@ name: CI
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
|
-
-
|
|
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
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
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
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.1.2
|
data/Gemfile
CHANGED
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://
|
|
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 `
|
|
11
|
+
`svcb_rr_patch` supports "ech" SvcParamKey that ECHConfig.version is `0xfe0b` ~ `0xfe0f`.
|
|
12
12
|
|
|
13
|
-
- https://
|
|
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
|
-
|
|
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,46 +26,19 @@ $ gem install svcb_rr_patch
|
|
|
26
26
|
|
|
27
27
|
You can resolve HTTPS resources.
|
|
28
28
|
|
|
29
|
-
```
|
|
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* "
|
|
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:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
{"alpn"=>#<SvcbRrPatch::SvcParams::Alpn:0x0000000000000003 @protocols=["http/1.1", "h2"]>,
|
|
43
|
-
"ipv4hint"=>#<SvcbRrPatch::SvcParams::Ipv4hint:0x0000000000000004 @addresses=[#<Resolv::IPv4 162.159.137.85>, #<Resolv::IPv4 162.159.138.85>]>,
|
|
44
|
-
"ech"=>
|
|
45
|
-
#<SvcbRrPatch::SvcParams::Ech:0x0000000000000005
|
|
46
|
-
@echconfiglist=
|
|
47
|
-
[#<SvcbRrPatch::SvcParams::Ech::ECHConfig:0x0000000000000006
|
|
48
|
-
@echconfig_contents=
|
|
49
|
-
#<SvcbRrPatch::SvcParams::Ech::ECHConfigContents:0x0000000000000007
|
|
50
|
-
@extensions=[],
|
|
51
|
-
@key_config=
|
|
52
|
-
#<SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig:0x0000000000000008
|
|
53
|
-
@cipher_suites=
|
|
54
|
-
[#<SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite:0x0000000000000009
|
|
55
|
-
@aead_id=#<SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite::HpkeAeadId:0x0000000000000010 @uint16=1>,
|
|
56
|
-
@kdf_id=#<SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite::HpkeKdfId:0x0000000000000011 @uint16=1>>],
|
|
57
|
-
@config_id=238,
|
|
58
|
-
@kem_id=#<SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkeKemId:0x0000000000000012 @uint16=32>,
|
|
59
|
-
@public_key=
|
|
60
|
-
#<SvcbRrPatch::SvcParams::Ech::ECHConfigContents::HpkeKeyConfig::HpkePublicKey:0x0000000000000013
|
|
61
|
-
@opaque="I\x19\xD0\xCFP\b>e\xDF\xE1Q\xE8+i\x89\x8AJ\xA2b'\xD0j\xB9+\xDE\xE2\xDE\xF8\xFA\xAD\xBBm">>,
|
|
62
|
-
@maximum_name_length=0,
|
|
63
|
-
@public_name="cloudflare-esni.com">,
|
|
64
|
-
@version="\xFE\r">]>,
|
|
65
|
-
"ipv6hint"=>#<SvcbRrPatch::SvcParams::Ipv6hint:0x0000000000000014 @addresses=[#<Resolv::IPv6 2606:4700:7::a29f:8955>, #<Resolv::IPv6 2606:4700:7::a29f:8a55>]>}>,
|
|
66
|
-
@svc_priority=1,
|
|
67
|
-
@target_name="",
|
|
68
|
-
@ttl=58>]
|
|
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"
|
|
69
42
|
```
|
|
70
43
|
|
|
71
44
|
|
data/lib/svcb_rr_patch/https.rb
CHANGED
|
@@ -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)
|
|
@@ -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
|
-
|
|
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://
|
|
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
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
|
|
@@ -27,94 +27,92 @@ module SvcbRrPatch::SvcParams
|
|
|
27
27
|
}.call.freeze
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
Dir[File.dirname(__FILE__)
|
|
30
|
+
Dir["#{File.dirname(__FILE__)}/svc_params/*.rb"].sort.each { |f| require f }
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# @return [String]
|
|
39
|
-
def encode
|
|
40
|
-
@hash
|
|
41
|
-
.map { |k, v| [PARAMETER_REGISTRY_INVERT[k], v] }
|
|
42
|
-
.sort { |lh, rh| lh.first <=> rh.first }
|
|
43
|
-
.map do |k, v|
|
|
44
|
-
[k].pack('n') + v.encode.then { |s| [s.length].pack('n') + s }
|
|
45
|
-
end
|
|
46
|
-
.join
|
|
47
|
-
end
|
|
32
|
+
class SvcbRrPatch::SvcParams::Hash
|
|
33
|
+
def initialize(hash)
|
|
34
|
+
@hash = hash
|
|
35
|
+
end
|
|
48
36
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
37
|
+
# @return [String]
|
|
38
|
+
def encode
|
|
39
|
+
@hash
|
|
40
|
+
.map { |k, v| [SvcbRrPatch::SvcParams::PARAMETER_REGISTRY_INVERT[k], v] }
|
|
41
|
+
.sort { |lh, rh| lh.first <=> rh.first }
|
|
42
|
+
.map do |k, v|
|
|
43
|
+
[k].pack('n') + v.encode.then { |s| [s.length].pack('n') + s }
|
|
44
|
+
end
|
|
45
|
+
.join
|
|
46
|
+
end
|
|
57
47
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
# @param octet [String]
|
|
49
|
+
#
|
|
50
|
+
# @return [Hash]
|
|
51
|
+
def self.decode(octet)
|
|
52
|
+
svc_params = {}
|
|
53
|
+
i = 0
|
|
54
|
+
while i < octet.length
|
|
55
|
+
raise ::Resolv::DNS::DecodeError if i + 4 > octet.length
|
|
63
56
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
57
|
+
k = octet.slice(i, 2).unpack1('n')
|
|
58
|
+
# SvcParamKeys SHALL appear in increasing numeric order.
|
|
59
|
+
raise ::Resolv::DNS::DecodeError unless svc_params.keys.find do |key|
|
|
60
|
+
SvcbRrPatch::SvcParams::PARAMETER_REGISTRY_INVERT[key] >= k
|
|
61
|
+
end.nil?
|
|
68
62
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
svc_param_values = decode_svc_params(svc_param_key, v)
|
|
74
|
-
svc_params.store(svc_param_key, svc_param_values)
|
|
75
|
-
end
|
|
76
|
-
raise ::Resolv::DNS::DecodeError if i != octet.length
|
|
63
|
+
i += 2
|
|
64
|
+
vlen = octet.slice(i, 2).unpack1('n')
|
|
65
|
+
i += 2
|
|
66
|
+
raise ::Resolv::DNS::DecodeError if i + vlen > octet.length
|
|
77
67
|
|
|
78
|
-
|
|
68
|
+
v = octet.slice(i, vlen)
|
|
69
|
+
i += vlen
|
|
70
|
+
# Values are in a format specific to the SvcParamKey.
|
|
71
|
+
svc_param_key = SvcbRrPatch::SvcParams::PARAMETER_REGISTRY[k]
|
|
72
|
+
svc_param_values = decode_svc_params(svc_param_key, v)
|
|
73
|
+
svc_params.store(svc_param_key, svc_param_values)
|
|
79
74
|
end
|
|
75
|
+
raise ::Resolv::DNS::DecodeError if i != octet.length
|
|
80
76
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def self.decode_svc_params(key, octet)
|
|
84
|
-
case key
|
|
85
|
-
when 'mandatory'
|
|
86
|
-
Mandatory.decode(octet)
|
|
87
|
-
when 'alpn'
|
|
88
|
-
Alpn.decode(octet)
|
|
89
|
-
when 'no-default-alpn'
|
|
90
|
-
NoDefaultAlpn.decode(octet)
|
|
91
|
-
when 'port'
|
|
92
|
-
Port.decode(octet)
|
|
93
|
-
when 'ipv4hint'
|
|
94
|
-
Ipv4hint.decode(octet)
|
|
95
|
-
when 'ech'
|
|
96
|
-
Ech.decode(octet)
|
|
97
|
-
when 'ipv6hint'
|
|
98
|
-
Ipv6hint.decode(octet)
|
|
99
|
-
else
|
|
100
|
-
octet
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
77
|
+
new(svc_params)
|
|
78
|
+
end
|
|
104
79
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
80
|
+
# :nodoc:
|
|
81
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
82
|
+
def self.decode_svc_params(key, octet)
|
|
83
|
+
case key
|
|
84
|
+
when 'mandatory'
|
|
85
|
+
SvcbRrPatch::SvcParams::Mandatory.decode(octet)
|
|
86
|
+
when 'alpn'
|
|
87
|
+
SvcbRrPatch::SvcParams::Alpn.decode(octet)
|
|
88
|
+
when 'no-default-alpn'
|
|
89
|
+
SvcbRrPatch::SvcParams::NoDefaultAlpn.decode(octet)
|
|
90
|
+
when 'port'
|
|
91
|
+
SvcbRrPatch::SvcParams::Port.decode(octet)
|
|
92
|
+
when 'ipv4hint'
|
|
93
|
+
SvcbRrPatch::SvcParams::Ipv4hint.decode(octet)
|
|
94
|
+
when 'ech'
|
|
95
|
+
SvcbRrPatch::SvcParams::Ech.decode(octet)
|
|
96
|
+
when 'ipv6hint'
|
|
97
|
+
SvcbRrPatch::SvcParams::Ipv6hint.decode(octet)
|
|
98
|
+
else
|
|
99
|
+
octet
|
|
108
100
|
end
|
|
101
|
+
end
|
|
102
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
109
103
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
104
|
+
# :nodoc:
|
|
105
|
+
def [](key)
|
|
106
|
+
@hash[key]
|
|
107
|
+
end
|
|
114
108
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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(' ')
|
|
119
117
|
end
|
|
120
118
|
end
|
data/lib/svcb_rr_patch/svcb.rb
CHANGED
|
@@ -11,28 +11,26 @@ class Resolv::DNS::Resource::IN::SVCB < Resolv::DNS::Resource
|
|
|
11
11
|
# @param svc_priority [Integer]
|
|
12
12
|
# @param target_name [String]
|
|
13
13
|
# @param svc_params [Hash]
|
|
14
|
+
# rubocop: disable Lint/MissingSuper
|
|
14
15
|
def initialize(svc_priority, target_name, svc_params)
|
|
15
|
-
# https://
|
|
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'))
|
data/lib/svcb_rr_patch.rb
CHANGED
data/spec/svc_params_spec.rb
CHANGED
data/svcb_rr_patch.gemspec
CHANGED
|
@@ -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.
|
|
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
|
+
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:
|
|
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.
|
|
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.
|
|
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
|