tls-map 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83caecd8dd0a4d170d686c141a7b39860f99f29f2bc4e436418eca7b877807ff
4
- data.tar.gz: 7a3a245f86067d8c9d59fb8f75b207e320c09d11b701624adf86842da27afc4e
3
+ metadata.gz: 41d9e4f95a9edfc3fbb1e8c72e3e15ab6d20c40621576b7829ce75c057141329
4
+ data.tar.gz: 71add869718efbad2b14e3da7ace2d5967013455daee5d310b89443d1a5d5a70
5
5
  SHA512:
6
- metadata.gz: fa1240ae951c33a26838ee04f15b55e03ec452cd9b03790394ebee99a142acc91b0bda3074f95bf97f495d3b553ef8363c17221d2c519772690ca5573954a80d
7
- data.tar.gz: cd72c3ff9281bfe37a7f866a33fc73340dbd70f37ee370cfd3a01a1742760d3f0f110a778ded5b03aca8b01873832f66ca24ebeef51ba3cab09d57c3e81b5377
6
+ metadata.gz: d03f9a2d71f71290c75bd5c2f8a296c7af7ab571f5ecc7cc1da7351ba65edf57a44b14aa697079b784ec0ed0df4df95a15be8a0bc9a6ec5d1f757a995809cd2c
7
+ data.tar.gz: 440522feebc7dbd057ec8abb9e1ad75b44567c861b97b2871f67e6836f7482db4d9ff5d4a4cf9ac081a51fe176a0b0ecbe2e818ccf40e1459fad6c60f3f17172
data/bin/tls-map CHANGED
@@ -11,26 +11,31 @@ require 'docopt'
11
11
  require 'paint'
12
12
 
13
13
  doc = <<~DOCOPT
14
- TLS map
14
+ TLS map #{TLSmap::VERSION}
15
15
 
16
16
  Usage:
17
17
  tls-map search <critera> <term> [-o <output> --force -e -a] [--no-color --debug]
18
18
  tls-map export <filename> <format> [--force] [--debug]
19
+ tls-map extract <filename> <format> [--no-color --debug]
19
20
  tls-map update [--debug]
20
21
  tls-map -h | --help
21
22
  tls-map --version
22
23
 
23
- Search options: (offline)
24
+ Search options: (offline) search and translate cipher names between SSL/TLS libraries
24
25
  <critera> The type of term. Accepted values: codepoint, iana, openssl, gnutls, nss.
25
26
  <term> The cipher algorithm name.
26
27
  -o, --output <output> Displayed fields. Accepted values: all, codepoint, iana, openssl, gnutls, nss. [default: all]
27
28
  -e, --extended (Online) Display additional information about the cipher (requires output = all or iana)
28
29
  -a, --acronym (Online) Display full acronym name (requires -e / --extended option)
29
30
 
30
- Export options: (offline)
31
+ Export options: (offline) export the list of all ciphers (mapping) in various formats
31
32
  <filename> The output file name to write to.
32
33
  <format> Supported formats: markdown (a markdown table), json_pretty (expanded JSON), json_compact (minified JSON), marshal (Ruby marshalized hash).
33
34
 
35
+ Extract options: (offline) extract ciphers from external tools output file
36
+ <filename> The external tool output file
37
+ <format> Supported formats: sslyze, sslscan2, testssl, ssllabs-scan (check the documentation for the expected file format)
38
+
34
39
  Update options: (online) DANGEROUS, will break database integrity, force option will be required
35
40
 
36
41
  Other options:
@@ -79,6 +84,13 @@ begin
79
84
  cli = TLSmap::CLI.new(args['--force'])
80
85
  cli.export(args['<filename>'], args['<format>'].to_sym)
81
86
  puts "#{args['<filename>']} exported"
87
+ elsif args['extract']
88
+ extractor = TLSmap::App::Extractor.new
89
+ ciphers = extractor.parse(args['<format>'], args['<filename>'])
90
+ ciphers.each do |k, v|
91
+ puts Paint[k, :blue] unless v.empty?
92
+ puts Paint[v.join("\n"), :white] unless v.empty?
93
+ end
82
94
  elsif args['update']
83
95
  cli = TLSmap::CLI.new
84
96
  cli.update
data/lib/tls_map.rb CHANGED
@@ -11,6 +11,7 @@ require 'tls_map/gnutls'
11
11
  require 'tls_map/nss'
12
12
  require 'tls_map/output'
13
13
  require 'tls_map/ciphersuiteinfo'
14
+ require 'tls_map/extractor'
14
15
 
15
16
  # TLS map module
16
17
  module TLSmap
@@ -36,13 +37,13 @@ module TLSmap
36
37
  end
37
38
 
38
39
  # Search for corresponding cipher algorithms in other libraries
39
- # @param critera [Symbol] The type of +term+.
40
- # Accepted values: +:codepoint+, +:iana+, +:openssl+, +:gnutls+, +:nss+.
40
+ # @param critera [Symbol] The type of `term`.
41
+ # Accepted values: `:codepoint`, `:iana`, `:openssl`, `:gnutls`, `:nss`.
41
42
  # @param term [String] The cipher algorithm name.
42
43
  # @param output [Symbol] The corresponding type to be included in the return value.
43
- # Accepted values: +:all+ (default), +:codepoint+, +:iana+, +:openssl+,
44
- # +:gnutls+, +:nss+.
45
- # @return [Hash] The corresponding type matching +term+.
44
+ # Accepted values: `:all` (default), `:codepoint`, `:iana`, `:openssl`,
45
+ # `:gnutls`, `:nss`.
46
+ # @return [Hash] The corresponding type matching `term`.
46
47
  def search(critera, term, output = :all)
47
48
  @tls_map.each do |alg|
48
49
  term = term.upcase if critera == :codepoint
@@ -10,11 +10,13 @@ require 'yaml'
10
10
  module TLSmap
11
11
  class App
12
12
  # Partial wrapper around ciphersuite.info API to get extra info about a cipher
13
+ #
13
14
  # Documentation:
14
- # - https://ciphersuite.info/blog/2019/04/05/how-to-use-our-api/
15
- # - https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md
16
- # - https://ciphersuite.info/api/
17
- # - https://github.com/hcrudolph/ciphersuite.info
15
+ #
16
+ # - https://ciphersuite.info/blog/2019/04/05/how-to-use-our-api/
17
+ # - https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md
18
+ # - https://ciphersuite.info/api/
19
+ # - https://github.com/hcrudolph/ciphersuite.info
18
20
  class Extended
19
21
  # Root URL of Cipher Suite Info
20
22
  ROOT = 'https://ciphersuite.info/'
@@ -57,8 +59,8 @@ module TLSmap
57
59
  # Retrieve advanced about a cipher on Cipher Suite Info API and enhanced it
58
60
  # @param iana_name [String] IANA cipher name
59
61
  # @return [Hash] Hash containing advanced information. The keys are the same as {DICO}. All valeus are string
60
- # except +vulns+ which is an array of hashes containing two keys: +:severity+ (integer) and +:description+
61
- # (string). Each hash in +vulns+ correspond to a vulnerability.
62
+ # except `vulns` which is an array of hashes containing two keys: `:severity` (integer) and `:description`
63
+ # (string). Each hash in `vulns` correspond to a vulnerability.
62
64
  def extend(iana_name) # rubocop:disable Metrics/MethodLength
63
65
  obj = Net::HTTP.get(URI("#{API_ROOT}cs/#{iana_name}/"))
64
66
  out = JSON.parse(obj)[iana_name]
@@ -99,7 +101,7 @@ module TLSmap
99
101
 
100
102
  # Translate cipher related acronyms
101
103
  # @param term [String] Acronym, eg. DSS
102
- # @return [String] The long name of the acronym, eg. Digital Signature Standard or +nil+ if it's not found
104
+ # @return [String] The long name of the acronym, eg. Digital Signature Standard or `nil` if it's not found
103
105
  def translate_acronym(term)
104
106
  return @tech[term][:long_name] unless @tech[term].nil?
105
107
 
@@ -108,7 +110,7 @@ module TLSmap
108
110
 
109
111
  # Find vulnerabilities related to a technology
110
112
  # @param tech [String] The technology acronym, eg. CBC
111
- # @return [Array<Hash>] Array of vulnerabilities as described for {extend} return value in the +vulns+ key.
113
+ # @return [Array<Hash>] Array of vulnerabilities as described for {extend} return value in the `vulns` key.
112
114
  def find_vuln(tech)
113
115
  return @tech[tech][:vulnerabilities].map { |vuln| @vuln[vuln] } unless @tech[tech][:vulnerabilities].nil?
114
116
 
data/lib/tls_map/cli.rb CHANGED
@@ -9,7 +9,7 @@ module TLSmap
9
9
  class CLI < App
10
10
  INTEGRITY = '42e44f89550365da2bc8d33d87f88b65d85d6474e90f9edb65e0ea6c78f61a53' # sha2-256
11
11
 
12
- # Load and parse data from marshalized hash (+data/mapping.marshal+).
12
+ # Load and parse data from marshalized hash (`data/mapping.marshal`).
13
13
  # It must match the integrity check for security purpose.
14
14
  # @param force [Boolean] Force parsing even if intigrity check failed (DANGEROUS,
15
15
  # may result in command execution vulnerability)
@@ -31,7 +31,7 @@ module TLSmap
31
31
  end
32
32
 
33
33
  # Check if the password database exists
34
- # @return [Boolean] +true+ if the file exists
34
+ # @return [Boolean] `true` if the file exists
35
35
  def database_exists?
36
36
  exists = File.file?(@database_path)
37
37
  raise "Database does not exist: #{@database_path}" unless exists
@@ -0,0 +1,255 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ruby internal
4
+ require 'json'
5
+ # Project internal
6
+ require 'tls_map/cli'
7
+ # External
8
+ require 'rexml/document'
9
+
10
+ module TLSmap
11
+ class App
12
+ # External tools output data extractor
13
+ #
14
+ # Output files from [SSLyze][1] (JSON), [sslscan2][2] (XML), [testssl.sh][3] (JSON), [ssllabs-scan][4] (JSON)
15
+ #
16
+ # [1]:https://github.com/nabla-c0d3/sslyze
17
+ # [2]:https://github.com/rbsec/sslscan
18
+ # [3]:https://github.com/drwetter/testssl.sh
19
+ # [4]:https://github.com/ssllabs/ssllabs-scan
20
+ #
21
+ # Example of commands:
22
+ #
23
+ # - `sslyze --json_out=example.org.json example.org`
24
+ # - `sslscan2 --show-cipher-ids --xml=example.org.xml example.org`
25
+ # - `--show-cipher-ids` is mandatory else ciphers are not saved to the output
26
+ # - `testssl --jsonfile-pretty example.org.json --mapping no-openssl --cipher-per-proto example.org`
27
+ # - json-pretty is the only supported format, default json or csv, html won't work
28
+ # - `ssllabs-scan --quiet example.org > example.org.json`
29
+ # - The default output is the only supported format, using `-json-flat` won't work
30
+ class Extractor
31
+ # Get the list of ciphers extracted from the tool output file
32
+ # @return [Array<String>] Cipher array (IANA names)
33
+ attr_reader :ciphers
34
+
35
+ # Initialize {TLSmap::App::Extractor} instance
36
+ def initialize
37
+ @ciphers = []
38
+ end
39
+
40
+ # Return only the SSL 2.0 ciphers
41
+ # @return [Array<String>] Cipher array (IANA names)
42
+ def ssl20
43
+ @ciphers['SSL2.0']
44
+ end
45
+
46
+ # Return only the SSL 3.0 ciphers
47
+ # @return [Array<String>] Cipher array (IANA names)
48
+ def ssl30
49
+ @ciphers['SSL3.0']
50
+ end
51
+
52
+ # Return only the TLS 1.0 ciphers
53
+ # @return [Array<String>] Cipher array (IANA names)
54
+ def tls10
55
+ @ciphers['TLS1.0']
56
+ end
57
+
58
+ # Return only the TLS 1.1 ciphers
59
+ # @return [Array<String>] Cipher array (IANA names)
60
+ def tls11
61
+ @ciphers['TLS1.1']
62
+ end
63
+
64
+ # Return only the TLS 1.2 ciphers
65
+ # @return [Array<String>] Cipher array (IANA names)
66
+ def tls12
67
+ @ciphers['TLS1.2']
68
+ end
69
+
70
+ # Return only the TLS 1.3 ciphers
71
+ # @return [Array<String>] Cipher array (IANA names)
72
+ def tls13
73
+ @ciphers['TLS1.3']
74
+ end
75
+
76
+ # Extract the ciphers from the tool output file
77
+ # @param tool [String] Possible values: `sslyze`, `sslscan2`, `testssl`, `ssllabs-scan`
78
+ # @param file [String] Path of the tool output file, beware of the format expected. See {TLSmap::App::Extractor}
79
+ # @return [Array<String>] Cipher array (IANA names)
80
+ def parse(tool, file)
81
+ # Convert string to class
82
+ @ciphers = Object.const_get("TLSmap::App::Extractor::#{normalize(tool)}").parse(file)
83
+ end
84
+
85
+ # Convert cmdline tool name to Class name
86
+ def normalize(tool)
87
+ tool.split('-').map(&:capitalize).join
88
+ end
89
+
90
+ protected :normalize
91
+
92
+ # Parsing SSLyze
93
+ class Sslyze
94
+ class << self
95
+ # Extract the ciphers from the sslyze output file
96
+ # @param file [String] Path of the sslyze output file, beware of the format expected.
97
+ # See {TLSmap::App::Extractor}
98
+ # @return [Array<String>] Cipher array (IANA names)
99
+ def parse(file)
100
+ data = JSON.load_file(file)
101
+ extract_cipher(data)
102
+ end
103
+
104
+ # Extract the ciphers from the sslyze output file
105
+ # @param json_data [Hash] Ruby hash of the parsed JSON
106
+ # @return [Array<String>] Cipher array (IANA names)
107
+ def extract_cipher(json_data)
108
+ ciphers = json_data['server_scan_results'][0]['scan_commands_results']
109
+ raw = {
110
+ 'SSL2.0' => ciphers['ssl_2_0_cipher_suites']['accepted_cipher_suites'],
111
+ 'SSL3.0' => ciphers['ssl_3_0_cipher_suites']['accepted_cipher_suites'],
112
+ 'TLS1.0' => ciphers['tls_1_0_cipher_suites']['accepted_cipher_suites'],
113
+ 'TLS1.1' => ciphers['tls_1_1_cipher_suites']['accepted_cipher_suites'],
114
+ 'TLS1.2' => ciphers['tls_1_2_cipher_suites']['accepted_cipher_suites'],
115
+ 'TLS1.3' => ciphers['tls_1_3_cipher_suites']['accepted_cipher_suites']
116
+ }
117
+ raw.transform_values { |v| v.empty? ? v : v.map { |x| x['cipher_suite']['name'] } }
118
+ end
119
+
120
+ protected :extract_cipher
121
+ end
122
+ end
123
+
124
+ # Parsing sslscan2
125
+ class Sslscan2
126
+ class << self
127
+ # Extract the ciphers from the sslscan2 output file
128
+ # @param file [String] Path of the sslscan2 output file, beware of the format expected.
129
+ # See {TLSmap::App::Extractor}
130
+ # @return [Array<String>] Cipher array (IANA names)
131
+ def parse(file, online = false)
132
+ doc = REXML::Document.new(File.new(file))
133
+ extract_cipher(doc, online)
134
+ end
135
+
136
+ # Extract the ciphers from the sslscan2 output file
137
+ # @param xml_doc [REXML::Document] XML document as returned by `REXML::Document`
138
+ # @param online By default use the offline mode with {TLSmap::CLI} for better performance.
139
+ # Online mode will use {TLSmap::App} and fetch upstream resources to get latest updates but is a lot slower.
140
+ # @return [Array<String>] Cipher array (IANA names)
141
+ def extract_cipher(xml_doc, online = false) # rubocop:disable Metrics/MethodLength
142
+ raw = {
143
+ 'SSL2.0' => [], 'SSL3.0' => [],
144
+ 'TLS1.0' => [], 'TLS1.1' => [], 'TLS1.2' => [], 'TLS1.3' => []
145
+ }
146
+ tm = online ? TLSmap::App.new : TLSmap::CLI.new
147
+ xml_doc.root.each_element('//cipher') do |node|
148
+ sslv = node.attributes['sslversion'].gsub('v', '')
149
+ cipher = tm.search(:codepoint, node.attributes['id'][2..], :iana)[:iana]
150
+ raw[sslv].push(cipher)
151
+ end
152
+ raw
153
+ end
154
+
155
+ protected :extract_cipher
156
+ end
157
+ end
158
+
159
+ # Parsing testssl.sh
160
+ class Testssl
161
+ class << self
162
+ # Extract the ciphers from the testssl output file
163
+ # @param file [String] Path of the testssl output file, beware of the format expected.
164
+ # See {TLSmap::App::Extractor}
165
+ # @return [Array<String>] Cipher array (IANA names)
166
+ def parse(file)
167
+ data = JSON.load_file(file)
168
+ extract_cipher(data)
169
+ end
170
+
171
+ # Extract the ciphers from the testssl output file
172
+ # @param json_data [Hash] Ruby hash of the parsed JSON
173
+ # @return [Array<String>] Cipher array (IANA names)
174
+ def extract_cipher(json_data)
175
+ cipher = json_data['scanResult'][0]['cipherTests']
176
+ raw = {
177
+ 'SSL2.0' => [], 'SSL3.0' => [],
178
+ 'TLS1.0' => [], 'TLS1.1' => [], 'TLS1.2' => [], 'TLS1.3' => []
179
+ }
180
+ cipher.each do |node|
181
+ raw[id2prot(node['id'])].push(finding2cipher(node['finding']))
182
+ end
183
+ raw
184
+ end
185
+
186
+ # Convert testssl protocol id to protocol name in TLSmap format
187
+ # @param id [String] testssl protocol id
188
+ # @return [String] protocol name in TLSmap format
189
+ def id2prot(id)
190
+ prot = {
191
+ 'ssl2' => 'SSL2.0', 'ssl3' => 'SSL3.0', 'tls1' => 'TLS1.0',
192
+ 'tls1_1' => 'TLS1.1', 'tls1_2' => 'TLS1.2', 'tls1_3' => 'TLS1.3'
193
+ }
194
+ protv = id.match(/cipher-(\w+)_x\w+/).captures[0]
195
+ prot[protv]
196
+ end
197
+
198
+ # Extract the cipher name from testssl finding
199
+ # @param finding [String] testssl finding
200
+ # @return [String] cipher name (IANA names)
201
+ def finding2cipher(finding)
202
+ /\s(\w+_\w+)\s/.match(finding).captures[0]
203
+ end
204
+
205
+ protected :extract_cipher, :id2prot, :finding2cipher
206
+ end
207
+ end
208
+
209
+ # Parsing ssllabs-scan
210
+ class SsllabsScan
211
+ class << self
212
+ # Extract the ciphers from the ssllabs-scan output file
213
+ # @param file [String] Path of the ssllabs-scan output file, beware of the format expected.
214
+ # See {TLSmap::App::Extractor}
215
+ # @return [Array<String>] Cipher array (IANA names)
216
+ def parse(file)
217
+ data = JSON.load_file(file)
218
+ extract_cipher(data)
219
+ end
220
+
221
+ # Extract the ciphers from the ssllabs-scan output file
222
+ # @param json_data [Hash] Ruby hash of the parsed JSON
223
+ # @return [Array<String>] Cipher array (IANA names)
224
+ def extract_cipher(json_data) # rubocop:disable Metrics/MethodLength
225
+ raw = {
226
+ 'SSL2.0' => [], 'SSL3.0' => [],
227
+ 'TLS1.0' => [], 'TLS1.1' => [], 'TLS1.2' => [], 'TLS1.3' => []
228
+ }
229
+ json_data[0]['endpoints'].each do |endpoint|
230
+ endpoint['details']['suites'].each do |suite|
231
+ suite['list'].each do |cipher|
232
+ raw[id2prot(suite['protocol'])].push(cipher['name'])
233
+ end
234
+ end
235
+ end
236
+ raw.transform_values(&:uniq)
237
+ end
238
+
239
+ # Convert ssllabs-scan protocol id to protocol name in TLSmap format
240
+ # @param id [String] ssllabs-scan protocol id
241
+ # @return [String] protocol name in TLSmap format
242
+ def id2prot(id)
243
+ prot = {
244
+ 512 => 'SSL2.0', 768 => 'SSL3.0', 769 => 'TLS1.0',
245
+ 770 => 'TLS1.1', 771 => 'TLS1.2', 772 => 'TLS1.3'
246
+ }
247
+ prot[id]
248
+ end
249
+
250
+ protected :extract_cipher, :id2prot
251
+ end
252
+ end
253
+ end
254
+ end
255
+ end
@@ -35,9 +35,9 @@ module TLSmap
35
35
 
36
36
  # Export the mapping to a file, supporting various formats.
37
37
  # @param filename [String] The output file name to write to.
38
- # @param format [Symbol] Supported formats: +:markdown+ (a markdown table),
39
- # +:json_pretty+ (expanded JSON), +:json_compact+ (minified JSON),
40
- # +:marshal+ (Ruby marshalized hash).
38
+ # @param format [Symbol] Supported formats: `:markdown` (a markdown table),
39
+ # `:json_pretty` (expanded JSON), `:json_compact` (minified JSON),
40
+ # `:marshal` (Ruby marshalized hash).
41
41
  def export(filename, format)
42
42
  case format
43
43
  when :markdown then output_markdown(filename)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TLSmap
4
- VERSION = '1.1.0'
4
+ VERSION = '1.2.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tls-map
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre ZANNI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-25 00:00:00.000000000 Z
11
+ date: 2021-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docopt
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rexml
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.2'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +100,48 @@ dependencies:
86
100
  - - "~>"
87
101
  - !ruby/object:Gem::Version
88
102
  version: '4.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: minitest
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '5.12'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '5.12'
117
+ - !ruby/object:Gem::Dependency
118
+ name: minitest-skip
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: rake
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '13.0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '13.0'
89
145
  - !ruby/object:Gem::Dependency
90
146
  name: redcarpet
91
147
  requirement: !ruby/object:Gem::Requirement
@@ -147,6 +203,7 @@ files:
147
203
  - lib/tls_map.rb
148
204
  - lib/tls_map/ciphersuiteinfo.rb
149
205
  - lib/tls_map/cli.rb
206
+ - lib/tls_map/extractor.rb
150
207
  - lib/tls_map/gnutls.rb
151
208
  - lib/tls_map/iana.rb
152
209
  - lib/tls_map/nss.rb