derparse 0.1.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 +7 -0
- data/.editorconfig +23 -0
- data/.gitignore +6 -0
- data/.yardopts +1 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/CONTRIBUTING.md +10 -0
- data/LICENCE +674 -0
- data/README.md +141 -0
- data/derparse.gemspec +35 -0
- data/lib/derparse.rb +53 -0
- data/lib/derparse/node.rb +142 -0
- data/lib/derparse/node/integer.rb +15 -0
- data/lib/derparse/node/null.rb +13 -0
- data/lib/derparse/node/octet_string.rb +13 -0
- data/lib/derparse/node/sequence.rb +21 -0
- metadata +188 -0
data/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Ever wanted to do terrible, terrible things with DER-encoded ASN.1 data
|
|
2
|
+
structures? Now you can!
|
|
3
|
+
|
|
4
|
+
While there are plenty of DER parsers out there, they tend to suffer from the
|
|
5
|
+
misguided assumption that the data they're parsing is actually valid. Wild
|
|
6
|
+
idea, it'll never catch on. In contrast, `derparse` makes the opposite
|
|
7
|
+
assumption -- that everything is awful. This means that it makes an attempt to
|
|
8
|
+
parse incomplete and, to a limited degree, corrupted DER-encoded data
|
|
9
|
+
structures.
|
|
10
|
+
|
|
11
|
+
Why would you *ever* want this, you might ask? It's a niche requirement,
|
|
12
|
+
undoubtedly, and if you're asking the question, that's a good indication that
|
|
13
|
+
`derparse` probably isn't what you're looking for -- `OpenSSL::ASN1` does a
|
|
14
|
+
good job of parsing well-formed DER data.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Installation
|
|
18
|
+
|
|
19
|
+
It's a gem:
|
|
20
|
+
|
|
21
|
+
gem install derparse
|
|
22
|
+
|
|
23
|
+
There's also the wonders of [the Gemfile](http://bundler.io):
|
|
24
|
+
|
|
25
|
+
gem 'derparse'
|
|
26
|
+
|
|
27
|
+
If you're the sturdy type that likes to run from git:
|
|
28
|
+
|
|
29
|
+
rake install
|
|
30
|
+
|
|
31
|
+
Or, if you've eschewed the convenience of Rubygems entirely, then you
|
|
32
|
+
presumably know what to do already.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# Usage
|
|
36
|
+
|
|
37
|
+
Instantiate a new `DerParse` object, giving it the DER-encoded data you want
|
|
38
|
+
to parse:
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
p = DerParse.new("0\x81\x80\x02\x01\x2a\x04\x44\x65\x72\x50\x61\x72\x73\x65\x02\x01\x45\x6e\x69\x63\x65")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
{DerParse} has a number of instance methods to help you examine and work with
|
|
45
|
+
the parsed ASN.1 data. For example, you can get a string description of the
|
|
46
|
+
data and its structure:
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
p.to_s # => "long, multi-line string of something something"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
which means, of course, that you can print it to screen:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
puts p
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
If you want to process the data, you can use `#traverse` to walk
|
|
59
|
+
through every element of the DER, which will yield a {`DerParse::Node`}
|
|
60
|
+
for each ASN.1 object that is encountered, along with info about the
|
|
61
|
+
parser state.
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
p.traverse do |node, depth, offset|
|
|
65
|
+
puts "Parsing depth: #{depth} Offset: #{offset}"
|
|
66
|
+
puts "Header length: #{node.header_length} Data length: #{node.data_length}"
|
|
67
|
+
puts "Tag number: #{node.tag} Tag class: #{node.tag_class} Constructed: #{node.constructed?}"
|
|
68
|
+
puts "Value: #{node.value}"
|
|
69
|
+
puts "INCOMPLETE!" unless node.complete?
|
|
70
|
+
end
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
There are a whole bunch of methods which {`DerParse::Node`} has to help you
|
|
74
|
+
query what sort of ASN.1 object you're dealing with. It also handles a string
|
|
75
|
+
in which there are multiple ASN.1 objects encoded sequentially.
|
|
76
|
+
|
|
77
|
+
It's is particularly important to note the {`DerParse::Node#complete?`} method.
|
|
78
|
+
Because `DerParse` tries to give you as much data as it can, even if the DER is
|
|
79
|
+
incomplete or corrupt, it needs to let you know when the data it's passing back
|
|
80
|
+
is known to not be "correct", in a strict sense. What counts as an
|
|
81
|
+
"incomplete" value, and what impact it has on the value of a given node, can
|
|
82
|
+
get complicated. For full details, see the documentation for
|
|
83
|
+
{DerParse#traverse}.
|
|
84
|
+
|
|
85
|
+
If you call `#traverse` without a block, it'll return an iterator, which allows
|
|
86
|
+
you to be more flexible with your iteration, like constructing complicated handlers
|
|
87
|
+
for parsed DER structures.
|
|
88
|
+
|
|
89
|
+
Finally, you can try {`DerParse#to_a`}. This attempts to turn a DER blob into
|
|
90
|
+
a collection of Ruby objects. It handles many common ASN.1 data types,
|
|
91
|
+
including integers, octet and bit strings, sequences and sets (turns them into
|
|
92
|
+
arrays), and so on. If it hits an ASN.1 type it can't handle, it'll give up
|
|
93
|
+
and raise {`DerParse::IncompatibleDataTypeError`}.
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# Compatibility and Coverage
|
|
97
|
+
|
|
98
|
+
The parts of ASN.1 that `DerParse` best supports are those which I've needed
|
|
99
|
+
for my own purposes -- mainly sequences, integers, octet strings, and to a
|
|
100
|
+
lesser extent OIDs. In particular, it's important to note that `DerParse` is
|
|
101
|
+
for ***DER*** structures, so any BER-specific things like indefinite lengths
|
|
102
|
+
are not, and probably will not, be supported. Support for additional ASN.1
|
|
103
|
+
types are welcomed via a well-tested PR.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# Security
|
|
107
|
+
|
|
108
|
+
ASN.1 has a long and glorious history of being difficult to parse safely.
|
|
109
|
+
While parsing in a memory-safe language reduces the attack surface, I don't
|
|
110
|
+
recommend unconstrained parsing of arbitrary input using `DerParse`.
|
|
111
|
+
Reasonable care has been taken to not produce any absolute bone-headed bugs,
|
|
112
|
+
but this code has not been intensively vetted for potential security issues.
|
|
113
|
+
|
|
114
|
+
That being said, `DerParse` is intended to be secure, and everyone wants it to
|
|
115
|
+
be secure. If you *do* find anything in `DerParse` that is security sensitive,
|
|
116
|
+
please e-mail [`mpalmer@hezmatt.org`](mailto:mpalmer@hezmatt.org).
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# Contributing
|
|
120
|
+
|
|
121
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# Licence
|
|
125
|
+
|
|
126
|
+
Unless otherwise stated, everything in this repo is covered by the following
|
|
127
|
+
copyright notice:
|
|
128
|
+
|
|
129
|
+
Copyright (C) 2020 Matt Palmer <matt@hezmatt.org>
|
|
130
|
+
|
|
131
|
+
This program is free software: you can redistribute it and/or modify it
|
|
132
|
+
under the terms of the GNU General Public License version 3, as
|
|
133
|
+
published by the Free Software Foundation.
|
|
134
|
+
|
|
135
|
+
This program is distributed in the hope that it will be useful,
|
|
136
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
137
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
138
|
+
GNU General Public License for more details.
|
|
139
|
+
|
|
140
|
+
You should have received a copy of the GNU General Public License
|
|
141
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/derparse.gemspec
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'git-version-bump'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
nil
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
Gem::Specification.new do |s|
|
|
8
|
+
s.name = "derparse"
|
|
9
|
+
|
|
10
|
+
s.version = GVB.version rescue "0.0.0.1.NOGVB"
|
|
11
|
+
s.date = GVB.date rescue Time.now.strftime("%Y-%m-%d")
|
|
12
|
+
|
|
13
|
+
s.platform = Gem::Platform::RUBY
|
|
14
|
+
|
|
15
|
+
s.summary = "DER parsing classes and routines"
|
|
16
|
+
|
|
17
|
+
s.authors = ["Matt Palmer"]
|
|
18
|
+
s.email = ["theshed+derparse@hezmatt.org"]
|
|
19
|
+
s.homepage = "http://github.com/mpalmer/derparse"
|
|
20
|
+
|
|
21
|
+
s.files = `git ls-files -z`.split("\0").reject { |f| f =~ /^(G|spec|Rakefile)/ }
|
|
22
|
+
|
|
23
|
+
s.required_ruby_version = ">= 2.5.0"
|
|
24
|
+
|
|
25
|
+
s.add_development_dependency 'bundler'
|
|
26
|
+
s.add_development_dependency 'github-release'
|
|
27
|
+
s.add_development_dependency 'guard-rspec'
|
|
28
|
+
s.add_development_dependency 'rake', '~> 10.4', '>= 10.4.2'
|
|
29
|
+
# Needed for guard
|
|
30
|
+
s.add_development_dependency 'rb-inotify', '~> 0.9'
|
|
31
|
+
s.add_development_dependency 'redcarpet'
|
|
32
|
+
s.add_development_dependency 'rspec'
|
|
33
|
+
s.add_development_dependency 'simplecov'
|
|
34
|
+
s.add_development_dependency 'yard'
|
|
35
|
+
end
|
data/lib/derparse.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
class DerParse
|
|
2
|
+
class Error < StandardError; end
|
|
3
|
+
class IncompatibleDatatypeError < StandardError; end
|
|
4
|
+
|
|
5
|
+
class Bug < Exception; end
|
|
6
|
+
|
|
7
|
+
def initialize(s)
|
|
8
|
+
if s.respond_to?(:to_str)
|
|
9
|
+
@s = s.to_str
|
|
10
|
+
else
|
|
11
|
+
raise ArgumentError,
|
|
12
|
+
"Must provide string to parse"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def traverse(&blk)
|
|
17
|
+
if blk
|
|
18
|
+
node(@s, 0, 0, &blk)
|
|
19
|
+
self
|
|
20
|
+
else
|
|
21
|
+
to_enum(:traverse)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def to_a
|
|
26
|
+
[].tap do |v|
|
|
27
|
+
r = @s
|
|
28
|
+
|
|
29
|
+
until r.empty?
|
|
30
|
+
n = DerParse::Node.factory(r)
|
|
31
|
+
v << n.value
|
|
32
|
+
r = n.rest
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def node(der, depth, offset, &blk)
|
|
40
|
+
node = DerParse::Node.factory(der, depth: depth, offset: offset)
|
|
41
|
+
yield node
|
|
42
|
+
|
|
43
|
+
if node.constructed?
|
|
44
|
+
node(node.data, depth + 1, offset + node.header_length, &blk)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
unless node.rest.empty?
|
|
48
|
+
node(node.rest, depth, offset + node.der_length, &blk)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
require_relative "./derparse/node"
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require "derparse"
|
|
2
|
+
|
|
3
|
+
class DerParse
|
|
4
|
+
class Node
|
|
5
|
+
def self.factory(der, *args)
|
|
6
|
+
klass_name = DerParse::Node.constants.find do |const|
|
|
7
|
+
DerParse::Node.const_get(const).handles?(der)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
klass = klass_name.nil? ? DerParse::Node : const_get(klass_name)
|
|
11
|
+
|
|
12
|
+
klass.new(der, *args)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :tag, :tag_class, :tag_length, :length_length, :data_length, :data, :depth, :offset, :rest
|
|
16
|
+
|
|
17
|
+
def initialize(der, depth: 0, offset: 0)
|
|
18
|
+
@depth, @offset = depth, offset
|
|
19
|
+
@tag = @tag_class = @constructed = @tag_length = @data_length = @length_length, @data = nil
|
|
20
|
+
@complete = true
|
|
21
|
+
|
|
22
|
+
begin
|
|
23
|
+
r = parse_type(der)
|
|
24
|
+
r = parse_length(r)
|
|
25
|
+
@rest = parse_data(r)
|
|
26
|
+
rescue IncompleteDer
|
|
27
|
+
@complete = false
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def der_length
|
|
32
|
+
if data_length.nil? || header_length.nil?
|
|
33
|
+
nil
|
|
34
|
+
else
|
|
35
|
+
data_length + header_length
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def header_length
|
|
40
|
+
if tag_length.nil? || length_length.nil?
|
|
41
|
+
nil
|
|
42
|
+
else
|
|
43
|
+
tag_length + length_length
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def constructed?
|
|
48
|
+
@constructed
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def primitive?
|
|
52
|
+
!constructed?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def complete?
|
|
56
|
+
@complete
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def value
|
|
60
|
+
raise IncompatibleDatatypeError
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
class IncompleteDer < Error; end
|
|
66
|
+
private_constant :IncompleteDer
|
|
67
|
+
|
|
68
|
+
def parse_type(s)
|
|
69
|
+
if s.empty? || s.nil?
|
|
70
|
+
# This *technically* shouldn't be possible
|
|
71
|
+
#:nocov:
|
|
72
|
+
raise Bug, "parse_type(#{s.inspect})"
|
|
73
|
+
#:nocov:
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
t0, s = ss(s)
|
|
77
|
+
|
|
78
|
+
@tag_class = (t0 & 0xc0) >> 6
|
|
79
|
+
@constructed = ((t0 & 0x20) >> 5) == 1
|
|
80
|
+
@tag = t0 & 0x1f
|
|
81
|
+
tl = 1
|
|
82
|
+
|
|
83
|
+
=begin
|
|
84
|
+
# As-yet unneeded big-tag support
|
|
85
|
+
if tag == 0x1f
|
|
86
|
+
tag = 0
|
|
87
|
+
more = true
|
|
88
|
+
|
|
89
|
+
while more
|
|
90
|
+
c = ss(s)
|
|
91
|
+
tag = tag * 128 + c & 0x7f
|
|
92
|
+
more = (c & 0x80) == 0x80
|
|
93
|
+
tl += 1
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
=end
|
|
97
|
+
|
|
98
|
+
@tag_length = tl
|
|
99
|
+
|
|
100
|
+
s
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def parse_length(s)
|
|
104
|
+
l0, s = ss(s)
|
|
105
|
+
|
|
106
|
+
if (l0 & 0x80) == 0
|
|
107
|
+
@data_length = l0
|
|
108
|
+
@length_length = 1
|
|
109
|
+
else
|
|
110
|
+
ll = l0 & 0x7f
|
|
111
|
+
@length_length = ll + 1
|
|
112
|
+
@data_length = ll.times.inject(0) { |a, _| c, s = ss(s); a * 256 + c }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
s
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def parse_data(s)
|
|
119
|
+
if s.length < @data_length
|
|
120
|
+
@data = s
|
|
121
|
+
raise IncompleteDer
|
|
122
|
+
else
|
|
123
|
+
@data = s[0, @data_length]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
s[@data_length..]
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def ss(s)
|
|
130
|
+
raise IncompleteDer if s.empty?
|
|
131
|
+
|
|
132
|
+
c, r = s.unpack("Ca*")
|
|
133
|
+
# Make sure that we always return a string as the second element
|
|
134
|
+
[c, r || ""]
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
require_relative "./node/integer"
|
|
140
|
+
require_relative "./node/octet_string"
|
|
141
|
+
require_relative "./node/null"
|
|
142
|
+
require_relative "./node/sequence"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class DerParse
|
|
2
|
+
class Node
|
|
3
|
+
class Integer < Node
|
|
4
|
+
def self.handles?(der)
|
|
5
|
+
der[0] == "\x02"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def value
|
|
9
|
+
sign = (@data[0].ord & 0x80) >> 7
|
|
10
|
+
|
|
11
|
+
@data.split(//).inject(0) { |a, c| sign *= 256; a * 256 + c.ord } - sign
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class DerParse
|
|
2
|
+
class Node
|
|
3
|
+
class Sequence < Node
|
|
4
|
+
def self.handles?(der)
|
|
5
|
+
der[0] == "\x30"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def value
|
|
9
|
+
[].tap do |v|
|
|
10
|
+
r = @data
|
|
11
|
+
|
|
12
|
+
until r == ""
|
|
13
|
+
n = DerParse::Node.factory(r)
|
|
14
|
+
v << n.value
|
|
15
|
+
r = n.rest
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: derparse
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Matt Palmer
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2020-05-08 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: github-release
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: guard-rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rake
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '10.4'
|
|
62
|
+
- - ">="
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: 10.4.2
|
|
65
|
+
type: :development
|
|
66
|
+
prerelease: false
|
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - "~>"
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '10.4'
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: 10.4.2
|
|
75
|
+
- !ruby/object:Gem::Dependency
|
|
76
|
+
name: rb-inotify
|
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0.9'
|
|
82
|
+
type: :development
|
|
83
|
+
prerelease: false
|
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0.9'
|
|
89
|
+
- !ruby/object:Gem::Dependency
|
|
90
|
+
name: redcarpet
|
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
96
|
+
type: :development
|
|
97
|
+
prerelease: false
|
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
- !ruby/object:Gem::Dependency
|
|
104
|
+
name: rspec
|
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
type: :development
|
|
111
|
+
prerelease: false
|
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0'
|
|
117
|
+
- !ruby/object:Gem::Dependency
|
|
118
|
+
name: simplecov
|
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - ">="
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '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'
|
|
131
|
+
- !ruby/object:Gem::Dependency
|
|
132
|
+
name: yard
|
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - ">="
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '0'
|
|
138
|
+
type: :development
|
|
139
|
+
prerelease: false
|
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - ">="
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '0'
|
|
145
|
+
description:
|
|
146
|
+
email:
|
|
147
|
+
- theshed+derparse@hezmatt.org
|
|
148
|
+
executables: []
|
|
149
|
+
extensions: []
|
|
150
|
+
extra_rdoc_files: []
|
|
151
|
+
files:
|
|
152
|
+
- ".editorconfig"
|
|
153
|
+
- ".gitignore"
|
|
154
|
+
- ".yardopts"
|
|
155
|
+
- CODE_OF_CONDUCT.md
|
|
156
|
+
- CONTRIBUTING.md
|
|
157
|
+
- LICENCE
|
|
158
|
+
- README.md
|
|
159
|
+
- derparse.gemspec
|
|
160
|
+
- lib/derparse.rb
|
|
161
|
+
- lib/derparse/node.rb
|
|
162
|
+
- lib/derparse/node/integer.rb
|
|
163
|
+
- lib/derparse/node/null.rb
|
|
164
|
+
- lib/derparse/node/octet_string.rb
|
|
165
|
+
- lib/derparse/node/sequence.rb
|
|
166
|
+
homepage: http://github.com/mpalmer/derparse
|
|
167
|
+
licenses: []
|
|
168
|
+
metadata: {}
|
|
169
|
+
post_install_message:
|
|
170
|
+
rdoc_options: []
|
|
171
|
+
require_paths:
|
|
172
|
+
- lib
|
|
173
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
174
|
+
requirements:
|
|
175
|
+
- - ">="
|
|
176
|
+
- !ruby/object:Gem::Version
|
|
177
|
+
version: 2.5.0
|
|
178
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
179
|
+
requirements:
|
|
180
|
+
- - ">="
|
|
181
|
+
- !ruby/object:Gem::Version
|
|
182
|
+
version: '0'
|
|
183
|
+
requirements: []
|
|
184
|
+
rubygems_version: 3.0.3
|
|
185
|
+
signing_key:
|
|
186
|
+
specification_version: 4
|
|
187
|
+
summary: DER parsing classes and routines
|
|
188
|
+
test_files: []
|