rasn1 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/.gitignore +10 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +89 -0
- data/Rakefile +12 -0
- data/lib/rasn1.rb +32 -0
- data/lib/rasn1/model.rb +197 -0
- data/lib/rasn1/types.rb +37 -0
- data/lib/rasn1/types/base.rb +347 -0
- data/lib/rasn1/types/bit_string.rb +70 -0
- data/lib/rasn1/types/boolean.rb +36 -0
- data/lib/rasn1/types/choice.rb +97 -0
- data/lib/rasn1/types/constructed.rb +13 -0
- data/lib/rasn1/types/enumerated.rb +119 -0
- data/lib/rasn1/types/integer.rb +42 -0
- data/lib/rasn1/types/null.rb +19 -0
- data/lib/rasn1/types/object_id.rb +79 -0
- data/lib/rasn1/types/octet_string.rb +33 -0
- data/lib/rasn1/types/primitive.rb +12 -0
- data/lib/rasn1/types/sequence.rb +39 -0
- data/lib/rasn1/types/sequence_of.rb +85 -0
- data/lib/rasn1/types/set.rb +26 -0
- data/lib/rasn1/types/set_of.rb +11 -0
- data/lib/rasn1/types/set_spec.rb +61 -0
- data/lib/rasn1/types/utf8_string.rb +20 -0
- data/lib/rasn1/version.rb +3 -0
- data/rasn1.gemspec +29 -0
- metadata +140 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
module RASN1
|
2
|
+
module Types
|
3
|
+
|
4
|
+
# ASN.1 Octet String
|
5
|
+
#
|
6
|
+
# An OCTET STRINT may contain another primtive object:
|
7
|
+
# os = OctetString.new(:os)
|
8
|
+
# int = Integer.new(:int)
|
9
|
+
# int.value = 12
|
10
|
+
# os.value = int
|
11
|
+
# os.to_der # => DER string with INTEGER in OCTET STRING
|
12
|
+
# @author Sylvain Daubert
|
13
|
+
class OctetString < Primitive
|
14
|
+
TAG = 0x04
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def value_to_der
|
19
|
+
case @value
|
20
|
+
when Base
|
21
|
+
@value.to_der
|
22
|
+
else
|
23
|
+
@value.to_s
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def der_to_value(der, ber:false)
|
28
|
+
@value = der
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module RASN1
|
2
|
+
module Types
|
3
|
+
|
4
|
+
# ASN.1 sequence
|
5
|
+
#
|
6
|
+
# A sequence is a collection of another ASN.1 types.
|
7
|
+
#
|
8
|
+
# To encode this ASN.1 example:
|
9
|
+
# Record ::= SEQUENCE {
|
10
|
+
# id INTEGER,
|
11
|
+
# room [0] INTEGER OPTIONAL,
|
12
|
+
# house [1] IMPLICIT INTEGER DEFAULT 0
|
13
|
+
# }
|
14
|
+
# do:
|
15
|
+
# seq = RASN1::Types::Sequence.new(:record)
|
16
|
+
# seq.value = [
|
17
|
+
# RASN1::Types::Integer(:id),
|
18
|
+
# RASN1::Types::Integer(:id, explicit: 0, optional: true),
|
19
|
+
# RASN1::Types::Integer(:id, implicit: 1, default: 0)
|
20
|
+
# ]
|
21
|
+
# @author Sylvain Daubert
|
22
|
+
class Sequence < Constructed
|
23
|
+
TAG = 0x10
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def value_to_der
|
28
|
+
@value.map { |element| element.to_der }.join
|
29
|
+
end
|
30
|
+
|
31
|
+
def der_to_value(der, ber:false)
|
32
|
+
nb_bytes = 0
|
33
|
+
@value.each do |element|
|
34
|
+
nb_bytes += element.parse!(der[nb_bytes..-1])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module RASN1
|
2
|
+
module Types
|
3
|
+
|
4
|
+
# ASN.1 SEQUENCE OF
|
5
|
+
#
|
6
|
+
# A SEQUENCE OF is an array of one ASN.1 type.
|
7
|
+
#
|
8
|
+
# To encode this ASN.1 example:
|
9
|
+
# Integers ::= SEQUENCE OF INTEGER
|
10
|
+
# do:
|
11
|
+
# # Create a SEQUENCE OF INTEGER
|
12
|
+
# seqof = RASN1::Types::SequenceOf.new(:record, RASN1::Types::Integer)
|
13
|
+
# # Set integer values
|
14
|
+
# seqof.value = [1, 2, 3, 4]
|
15
|
+
#
|
16
|
+
# SEQUENCE OF may be used to create sequence of composed types. For example:
|
17
|
+
# composed_type = RASN1::Sequence.new(:comp)
|
18
|
+
# commposed_type.value = [RASN1::Types::Integer(:id),
|
19
|
+
# RASN1::Types::OctetString(:data)]
|
20
|
+
# seqof = RASN1::SequenceOf.new(:comp, composed_type)
|
21
|
+
# seqof.value << [0, 'data0']
|
22
|
+
# seqof.value << [1, 'data1']
|
23
|
+
# @author Sylvain Daubert
|
24
|
+
class SequenceOf < Constructed
|
25
|
+
TAG = Sequence::TAG
|
26
|
+
|
27
|
+
# @return [Class, Base]
|
28
|
+
attr_reader :type
|
29
|
+
|
30
|
+
# @param [Symbol, String] name name for this tag in grammar
|
31
|
+
# @param [Class, Base] type base type for sequence of
|
32
|
+
# @see Base#initialize
|
33
|
+
def initialize(name, type, options={})
|
34
|
+
super(name, options)
|
35
|
+
@type = type
|
36
|
+
@value = []
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def type_class
|
42
|
+
type.is_a?(Class) ? type : type.class
|
43
|
+
end
|
44
|
+
|
45
|
+
def composed_type?
|
46
|
+
[Sequence, Set].include? type_class
|
47
|
+
end
|
48
|
+
|
49
|
+
def value_to_der
|
50
|
+
if composed_type?
|
51
|
+
@value.map do |ary|
|
52
|
+
s = type_class.new(@type.name)
|
53
|
+
sval = []
|
54
|
+
@type.value.each_with_index do |type, i|
|
55
|
+
type2 = type.dup
|
56
|
+
type2.value = ary[i]
|
57
|
+
sval << type2
|
58
|
+
end
|
59
|
+
s.value = sval
|
60
|
+
s.to_der
|
61
|
+
end.join
|
62
|
+
else
|
63
|
+
@value.map { |v| t = type_class.new(:t, value: v).to_der }.join
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def der_to_value(der, ber:false)
|
68
|
+
@value = []
|
69
|
+
nb_bytes = 0
|
70
|
+
|
71
|
+
while nb_bytes < der.length
|
72
|
+
of_type = composed_type? ? type.dup : type_class.new(:t)
|
73
|
+
nb_bytes += of_type.parse!(der[nb_bytes, der.length])
|
74
|
+
value = if composed_type?
|
75
|
+
of_type.value.map { |obj| obj.value }
|
76
|
+
else
|
77
|
+
of_type.value
|
78
|
+
end
|
79
|
+
@value << value
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module RASN1
|
2
|
+
module Types
|
3
|
+
|
4
|
+
# ASN.1 set
|
5
|
+
#
|
6
|
+
# A set is a collection of another ASN.1 types.
|
7
|
+
#
|
8
|
+
# To encode this ASN.1 example:
|
9
|
+
# Record ::= SET {
|
10
|
+
# id INTEGER,
|
11
|
+
# room [0] INTEGER OPTIONAL,
|
12
|
+
# house [1] IMPLICIT INTEGER DEFAULT 0
|
13
|
+
# }
|
14
|
+
# do:
|
15
|
+
# set = RASN1::Types::Set.new(:record)
|
16
|
+
# set.value = [
|
17
|
+
# RASN1::Types::Integer(:id),
|
18
|
+
# RASN1::Types::Integer(:id, explicit: 0, optional: true),
|
19
|
+
# RASN1::Types::Integer(:id, implicit: 1, default: 0)
|
20
|
+
# ]
|
21
|
+
# @author Sylvain Daubert
|
22
|
+
class Set < Sequence
|
23
|
+
TAG = 0x11
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module RASN1
|
2
|
+
module Types
|
3
|
+
|
4
|
+
describe Set do
|
5
|
+
before(:each) do
|
6
|
+
@set = Set.new(:set)
|
7
|
+
@bool = Boolean.new(:bool, default: true)
|
8
|
+
@int = Integer.new(:int)
|
9
|
+
@bs = BitString.new(:bs)
|
10
|
+
@set.value = [@bool, @int, @bs]
|
11
|
+
|
12
|
+
@no_bool_der = binary("\x30\x09\x02\x01\x2A\x03\x04\x01\x01\x04\x06")
|
13
|
+
@der = binary("\x30\x0c\x01\x01\x00\x02\x01\x2A\x03\x04\x01\x01\x04\x06")
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.type' do
|
17
|
+
it 'gets ASN.1 type' do
|
18
|
+
expect(Set.type).to eq('SET')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#initialize' do
|
23
|
+
it 'creates an Set with default values' do
|
24
|
+
set = Set.new(:set)
|
25
|
+
expect(set).to be_constructed
|
26
|
+
expect(set).to_not be_optional
|
27
|
+
expect(set.asn1_class).to eq(:universal)
|
28
|
+
expect(set.default).to eq(nil)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#to_der' do
|
33
|
+
it 'generates a DER string' do
|
34
|
+
@int.value = 42
|
35
|
+
@bs.value = [1,4,6].pack('C3')
|
36
|
+
@bs.bit_length = 23
|
37
|
+
expect(@set.to_der).to eq(@no_bool_der)
|
38
|
+
|
39
|
+
@bool.value = false
|
40
|
+
expect(@set.to_der).to eq(@der)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#parse!' do
|
45
|
+
it 'parses DER string' do
|
46
|
+
@set.parse!(@der)
|
47
|
+
expect(@bool.value).to be(false)
|
48
|
+
expect(@int.value).to eq(42)
|
49
|
+
expect(@bs.value).to eq([1,4,6].pack('C3'))
|
50
|
+
expect(@bs.bit_length).to eq(23)
|
51
|
+
|
52
|
+
@set.parse!(@no_bool_der)
|
53
|
+
expect(@bool.value).to be(true)
|
54
|
+
expect(@int.value).to eq(42)
|
55
|
+
expect(@bs.value).to eq([1,4,6].pack('C3'))
|
56
|
+
expect(@bs.bit_length).to eq(23)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RASN1
|
2
|
+
module Types
|
3
|
+
|
4
|
+
# ASN.1 UTF8 String
|
5
|
+
# @author Sylvain Daubert
|
6
|
+
class Utf8String < OctetString
|
7
|
+
TAG = 12
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def value_to_der
|
12
|
+
@value.to_s.force_encoding('UTF-8').force_encoding('BINARY')
|
13
|
+
end
|
14
|
+
|
15
|
+
def der_to_value(der, ber:false)
|
16
|
+
@value = der.force_encoding('UTF-8')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/rasn1.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rasn1/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'rasn1'
|
8
|
+
spec.version = RASN1::VERSION
|
9
|
+
spec.authors = ['Sylvain Daubert']
|
10
|
+
spec.email = ['sylvain.daubert@laposte.net']
|
11
|
+
|
12
|
+
spec.summary = %q{Ruby ASN.1 library}
|
13
|
+
#spec.description = %q{TODO: Write a longer description or delete this line.}
|
14
|
+
spec.homepage = 'https://github.com/sdaubert/rasn1'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
#spec.bindir = 'exe'
|
20
|
+
#spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_dependency 'yard', '~>0.9'
|
24
|
+
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.13'
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
28
|
+
spec.add_development_dependency 'simplecov', '~> 0.14'
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rasn1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sylvain Daubert
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-08-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: yard
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.9'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.13'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.13'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.14'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.14'
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- sylvain.daubert@laposte.net
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- Gemfile
|
92
|
+
- LICENSE
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- lib/rasn1.rb
|
96
|
+
- lib/rasn1/model.rb
|
97
|
+
- lib/rasn1/types.rb
|
98
|
+
- lib/rasn1/types/base.rb
|
99
|
+
- lib/rasn1/types/bit_string.rb
|
100
|
+
- lib/rasn1/types/boolean.rb
|
101
|
+
- lib/rasn1/types/choice.rb
|
102
|
+
- lib/rasn1/types/constructed.rb
|
103
|
+
- lib/rasn1/types/enumerated.rb
|
104
|
+
- lib/rasn1/types/integer.rb
|
105
|
+
- lib/rasn1/types/null.rb
|
106
|
+
- lib/rasn1/types/object_id.rb
|
107
|
+
- lib/rasn1/types/octet_string.rb
|
108
|
+
- lib/rasn1/types/primitive.rb
|
109
|
+
- lib/rasn1/types/sequence.rb
|
110
|
+
- lib/rasn1/types/sequence_of.rb
|
111
|
+
- lib/rasn1/types/set.rb
|
112
|
+
- lib/rasn1/types/set_of.rb
|
113
|
+
- lib/rasn1/types/set_spec.rb
|
114
|
+
- lib/rasn1/types/utf8_string.rb
|
115
|
+
- lib/rasn1/version.rb
|
116
|
+
- rasn1.gemspec
|
117
|
+
homepage: https://github.com/sdaubert/rasn1
|
118
|
+
licenses: []
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.5.2
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: Ruby ASN.1 library
|
140
|
+
test_files: []
|