tls-map 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 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