rasn1 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,12 @@
1
+ module RASN1
2
+ module Types
3
+
4
+ # @abstract This class SHOULD be used as base class for all ASN.1 primitive
5
+ # types.
6
+ # @author Sylvain Daubert
7
+ class Primitive < Base
8
+ # Primitive value
9
+ ASN1_PC = 0x00
10
+ end
11
+ end
12
+ end
@@ -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,11 @@
1
+ module RASN1
2
+ module Types
3
+
4
+ # ASN.1 SET OF
5
+ # @author Sylvain Daubert
6
+ class SetOf < SequenceOf
7
+ TAG = Set::TAG
8
+ end
9
+ end
10
+ end
11
+
@@ -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
@@ -0,0 +1,3 @@
1
+ module RASN1
2
+ VERSION = "0.1.0"
3
+ 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: []