krypt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +82 -0
  3. data/lib/krypt.rb +49 -0
  4. data/lib/krypt/asn1.rb +3 -0
  5. data/lib/krypt/asn1/common.rb +96 -0
  6. data/lib/krypt/asn1/template.rb +257 -0
  7. data/lib/krypt/codec.rb +57 -0
  8. data/lib/krypt/codec/base64.rb +140 -0
  9. data/lib/krypt/codec/base_codec.rb +36 -0
  10. data/lib/krypt/codec/hex.rb +122 -0
  11. data/lib/krypt/digest.rb +112 -0
  12. data/lib/krypt/hmac.rb +69 -0
  13. data/lib/krypt/pkcs5.rb +1 -0
  14. data/lib/krypt/pkcs5/pbkdf2.rb +41 -0
  15. data/lib/krypt/provider.rb +35 -0
  16. data/lib/krypt/x509.rb +3 -0
  17. data/lib/krypt/x509/certificate.rb +36 -0
  18. data/lib/krypt/x509/common.rb +41 -0
  19. data/lib/krypt/x509/crl.rb +33 -0
  20. data/lib/krypt_missing.rb +32 -0
  21. data/spec/krypt-core/MEMO.txt +85 -0
  22. data/spec/krypt-core/asn1/asn1_bit_string_spec.rb +475 -0
  23. data/spec/krypt-core/asn1/asn1_boolean_spec.rb +392 -0
  24. data/spec/krypt-core/asn1/asn1_constants_spec.rb +71 -0
  25. data/spec/krypt-core/asn1/asn1_data_spec.rb +1153 -0
  26. data/spec/krypt-core/asn1/asn1_end_of_contents_spec.rb +133 -0
  27. data/spec/krypt-core/asn1/asn1_enumerated_spec.rb +458 -0
  28. data/spec/krypt-core/asn1/asn1_generalized_time_spec.rb +492 -0
  29. data/spec/krypt-core/asn1/asn1_integer_spec.rb +557 -0
  30. data/spec/krypt-core/asn1/asn1_null_spec.rb +360 -0
  31. data/spec/krypt-core/asn1/asn1_object_id_spec.rb +495 -0
  32. data/spec/krypt-core/asn1/asn1_octet_string_spec.rb +456 -0
  33. data/spec/krypt-core/asn1/asn1_parser_spec.rb +503 -0
  34. data/spec/krypt-core/asn1/asn1_pem_spec.rb +282 -0
  35. data/spec/krypt-core/asn1/asn1_sequence_spec.rb +637 -0
  36. data/spec/krypt-core/asn1/asn1_set_spec.rb +795 -0
  37. data/spec/krypt-core/asn1/asn1_utc_time_spec.rb +495 -0
  38. data/spec/krypt-core/asn1/asn1_utf8_string_spec.rb +404 -0
  39. data/spec/krypt-core/asn1/resources.rb +53 -0
  40. data/spec/krypt-core/base64/base64_spec.rb +97 -0
  41. data/spec/krypt-core/digest/digest_spec.rb +707 -0
  42. data/spec/krypt-core/hex/hex_spec.rb +102 -0
  43. data/spec/krypt-core/pem/pem_decode_spec.rb +235 -0
  44. data/spec/krypt-core/resources.rb +1 -0
  45. data/spec/krypt-core/template/template_choice_parse_spec.rb +289 -0
  46. data/spec/krypt-core/template/template_dsl_spec.rb +351 -0
  47. data/spec/krypt-core/template/template_seq_of_parse_spec.rb +64 -0
  48. data/spec/krypt-core/template/template_seq_parse_spec.rb +1241 -0
  49. data/spec/krypt/codec/base64_decoder_spec.rb +94 -0
  50. data/spec/krypt/codec/base64_encoder_spec.rb +94 -0
  51. data/spec/krypt/codec/base64_mixed_spec.rb +16 -0
  52. data/spec/krypt/codec/hex_decoder_spec.rb +94 -0
  53. data/spec/krypt/codec/hex_encoder_spec.rb +94 -0
  54. data/spec/krypt/codec/hex_mixed_spec.rb +17 -0
  55. data/spec/krypt/codec/identity_shared.rb +119 -0
  56. data/spec/krypt/hmac/hmac_spec.rb +311 -0
  57. data/spec/krypt/pkcs5/pbkdf2_spec.rb +79 -0
  58. data/spec/krypt/provider/provider_spec.rb +83 -0
  59. data/spec/res/ca-bundle.crt +11758 -0
  60. data/spec/res/certificate.cer +0 -0
  61. data/spec/res/certificate.pem +20 -0
  62. data/spec/res/multiple_certs.pem +60 -0
  63. data/spec/resources.rb +66 -0
  64. data/test/helper.rb +8 -0
  65. data/test/res/certificate.cer +0 -0
  66. data/test/resources.rb +48 -0
  67. data/test/scratch.rb +28 -0
  68. data/test/test_krypt_asn1.rb +119 -0
  69. data/test/test_krypt_parser.rb +331 -0
  70. metadata +134 -0
@@ -0,0 +1,351 @@
1
+ # encoding: US-ASCII
2
+
3
+ require 'rspec'
4
+ require 'krypt'
5
+ require_relative '../resources'
6
+
7
+
8
+ shared_examples_for "a primitive declaration" do |func|
9
+ let(:asn1error) { Krypt::ASN1::ASN1Error }
10
+ subject do
11
+ n = name
12
+ o = opts
13
+ c = Class.new do
14
+ include Krypt::ASN1::Template::Sequence
15
+ send(func, n, o)
16
+ end
17
+ c.new
18
+ end
19
+
20
+ context "rejects declaration with no name" do
21
+ let(:name) { nil }
22
+ let(:opts) { nil }
23
+ specify { -> { subject }.should raise_error ArgumentError }
24
+ end
25
+
26
+ context "declararation with no options" do
27
+ let(:name) { :test }
28
+ let(:opts) { nil }
29
+ specify { subject.should respond_to name }
30
+ end
31
+
32
+ context "declaration with options" do
33
+ let(:name) { :test }
34
+
35
+ context "allows to mark as optional" do
36
+ let(:opts) { {optional: true} }
37
+ specify { subject.should respond_to name }
38
+ end
39
+
40
+ context "allows to set a tag" do
41
+ let(:opts) { {tag: 42} }
42
+ specify { subject.should respond_to name }
43
+ end
44
+
45
+ context "allows to set tagging" do
46
+ let(:opts) { {tagging: :EXPLICIT} }
47
+ specify { subject.should respond_to name }
48
+ end
49
+
50
+ context "allows to set tagging" do
51
+ let(:opts) { {tagging: :EXPLICIT} }
52
+ specify { subject.should respond_to name }
53
+ end
54
+
55
+ context "allows to set arbitrary default value" do
56
+ let(:opts) { {default: Object.new} }
57
+ specify { subject.should respond_to name }
58
+ end
59
+
60
+ context "allows to set optional, tag, tagging and default at once" do
61
+ let(:opts) { {optional: true, tag: 42, tagging: :IMPLICIT, default: Object.new} }
62
+ specify { subject.should respond_to name }
63
+ end
64
+ end
65
+ end
66
+
67
+ shared_examples_for "a typed declaration" do |func|
68
+ let(:template) do
69
+ Class.new do
70
+ include Krypt::ASN1::Template::Sequence
71
+ asn1_integer :version
72
+ end
73
+ end
74
+
75
+ subject do
76
+ n = name
77
+ t = type
78
+ o = opts
79
+ c = Class.new do
80
+ include Krypt::ASN1::Template::Sequence
81
+ send(func, n, t, o)
82
+ end
83
+ c.new
84
+ end
85
+
86
+ context "rejects declaration with no name" do
87
+ let(:name) { nil }
88
+ let(:type) { template }
89
+ let(:opts) { nil }
90
+ specify { -> { subject }.should raise_error ArgumentError }
91
+ end
92
+
93
+ context "rejects declaration with no type" do
94
+ let(:name) { :test }
95
+ let(:type) { nil }
96
+ let(:opts) { nil }
97
+ specify { -> { subject }.should raise_error ArgumentError }
98
+ end
99
+
100
+ context "declararation with no options" do
101
+ let(:name) { :test }
102
+ let(:type) { template }
103
+ let(:opts) { nil }
104
+ specify { subject.should respond_to name }
105
+ end
106
+
107
+ context "declaration with options" do
108
+ let(:name) { :test }
109
+ let(:type) { template }
110
+
111
+ context "allows to mark as optional" do
112
+ let(:opts) { {optional: true} }
113
+ specify { subject.should respond_to name }
114
+ end
115
+
116
+ context "allows to set a tag" do
117
+ let(:opts) { {tag: 42} }
118
+ specify { subject.should respond_to name }
119
+ end
120
+
121
+ context "allows to set tagging" do
122
+ let(:opts) { {tagging: :EXPLICIT} }
123
+ specify { subject.should respond_to name }
124
+ end
125
+
126
+ context "allows to set tagging" do
127
+ let(:opts) { {tagging: :EXPLICIT} }
128
+ specify { subject.should respond_to name }
129
+ end
130
+
131
+ context "allows to set arbitrary default value" do
132
+ let(:opts) { {default: Object.new} }
133
+ specify { subject.should respond_to name }
134
+ end
135
+
136
+ context "allows to set optional, tag, tagging and default at once" do
137
+ let(:opts) { {optional: true, tag: 42, tagging: :IMPLICIT, default: Object.new} }
138
+ specify { subject.should respond_to name }
139
+ end
140
+ end
141
+ end
142
+
143
+ shared_examples_for "Krypt::ASN1::Template" do
144
+ context "inclusion enables a set of DSL class methods" do
145
+ context("asn1_boolean") { it_behaves_like "a primitive declaration", :asn1_boolean }
146
+ context("asn1_integer") { it_behaves_like "a primitive declaration", :asn1_integer }
147
+ context("asn1_bit_string") { it_behaves_like "a primitive declaration", :asn1_bit_string }
148
+ context("asn1_octet_string") { it_behaves_like "a primitive declaration", :asn1_octet_string }
149
+ context("asn1_null") { it_behaves_like "a primitive declaration", :asn1_null }
150
+ context("asn1_object_id") { it_behaves_like "a primitive declaration", :asn1_object_id }
151
+ context("asn1_enumerated") { it_behaves_like "a primitive declaration", :asn1_enumerated }
152
+ context("asn1_utf8_string") { it_behaves_like "a primitive declaration", :asn1_utf8_string }
153
+ context("asn1_numeric_string") { it_behaves_like "a primitive declaration", :asn1_numeric_string }
154
+ context("asn1_printable_string") { it_behaves_like "a primitive declaration", :asn1_printable_string }
155
+ context("asn1_t61_string") { it_behaves_like "a primitive declaration", :asn1_t61_string }
156
+ context("asn1_videotex_string") { it_behaves_like "a primitive declaration", :asn1_videotex_string }
157
+ context("asn1_ia5_string") { it_behaves_like "a primitive declaration", :asn1_ia5_string }
158
+ context("asn1_utc_time") { it_behaves_like "a primitive declaration", :asn1_utc_time }
159
+ context("asn1_generalized_time") { it_behaves_like "a primitive declaration", :asn1_generalized_time }
160
+ context("asn1_graphic_string") { it_behaves_like "a primitive declaration", :asn1_graphic_string }
161
+ context("asn1_iso64_string") { it_behaves_like "a primitive declaration", :asn1_iso64_string }
162
+ context("asn1_general_string") { it_behaves_like "a primitive declaration", :asn1_general_string }
163
+ context("asn1_universal_string") { it_behaves_like "a primitive declaration", :asn1_universal_string }
164
+ context("asn1_bmp_string") { it_behaves_like "a primitive declaration", :asn1_bmp_string }
165
+ context("asn1_any") { it_behaves_like "a primitive declaration", :asn1_any }
166
+
167
+ context("asn1_template") { it_behaves_like "a typed declaration", :asn1_template }
168
+ context("asn1_sequence_of") { it_behaves_like "a typed declaration", :asn1_sequence_of }
169
+ context("asn1_set_of") { it_behaves_like "a typed declaration", :asn1_set_of }
170
+ end
171
+ end
172
+
173
+ shared_examples_for "constructed type constructor" do |type|
174
+ let (:template) do
175
+ Class.new do
176
+ include type
177
+ asn1_integer :a
178
+ end
179
+ end
180
+
181
+ it "takes no-args" do
182
+ template.new.should be_an_instance_of template
183
+ end
184
+
185
+ it "takes a block and yields the new instance" do
186
+ template.new do |o|
187
+ o.should be_an_instance_of template
188
+ end
189
+ end
190
+
191
+ it "allows assignment to its fields once instantiated" do
192
+ o = template.new
193
+ o.a = 42
194
+ o.a.should == 42
195
+ end
196
+
197
+ it "allows assignment to its fields inside the block" do
198
+ obj = template.new do |o|
199
+ o.a = 42
200
+ end
201
+ obj.a.should == 42
202
+ end
203
+ end
204
+
205
+ shared_examples_for "DER-based equality with <=>" do |type|
206
+ let(:template) do
207
+ t = type
208
+ Class.new do
209
+ include t
210
+ asn1_integer :a
211
+ end
212
+ end
213
+
214
+ let(:tag) do
215
+ if type == Krypt::ASN1::Template::Sequence
216
+ "\x30"
217
+ elsif type == Krypt::ASN1::Template::Set
218
+ "\x31"
219
+ else
220
+ raise "only Set or Sequence"
221
+ end
222
+ end
223
+
224
+ context "determines equality based on the encoding" do
225
+ let(:der) { "#{tag}\x03\x02\x01\x01" }
226
+ let(:v1) { template.parse_der(der) }
227
+ let(:v2) { template.parse_der(der) }
228
+ specify { v1.should == v2 && v1.eql?(v2).should == false }
229
+ end
230
+
231
+ context "finds a value encoded and reparsed to be equal to itself" do
232
+ let(:v1) { template.parse_der("#{tag}\x03\x02\x01\x01") }
233
+ specify { v1.should == (template.parse_der(v1.to_der)) }
234
+ end
235
+
236
+ context "when equal in terms of DER but not BER" do
237
+ let(:v1) { template.parse_der("#{tag}\x83\x00\x00\x03\x02\x01\x01") }
238
+ let(:v2) { template.parse_der("#{tag}\x03\x02\x01\x01") }
239
+ specify { v1.should_not == v2 }
240
+ end
241
+ end
242
+
243
+ shared_examples_for "accepting fields with special name" do |type, name|
244
+ let(:template) do
245
+ t = type
246
+ n = name
247
+ Class.new do
248
+ include t
249
+ asn1_integer name
250
+ end
251
+ end
252
+
253
+ let(:tag) do
254
+ if type == Krypt::ASN1::Template::Sequence
255
+ "\x30"
256
+ elsif type == Krypt::ASN1::Template::Set
257
+ "\x31"
258
+ else
259
+ raise "only Set or Sequence"
260
+ end
261
+ end
262
+
263
+ context "allows getting the value from a fresh instance" do
264
+ subject { template.new }
265
+ specify { subject.send(name).should be_nil }
266
+ end
267
+
268
+ context "allows getting the value from a parsed instance" do
269
+ subject { template.parse_der("#{tag}\x03\x02\x01\x01") }
270
+ specify { subject.send(name).should eq(1) }
271
+ end
272
+
273
+ context "allows setting the value on a fresh instance" do
274
+ subject { template.new }
275
+ specify { subject.send("#{name}=".to_sym, 2).should eq(2) }
276
+ end
277
+
278
+ context "allows setting the value on a parsed instance" do
279
+ subject { template.parse_der("#{tag}\x03\x02\x01\x01") }
280
+ specify do
281
+ obj = subject
282
+ obj.send(name).should eq(1)
283
+ obj.send("#{name}=".to_sym, 2).should eq(2)
284
+ obj.send(name).should eq(2)
285
+ end
286
+ end
287
+ end
288
+
289
+ describe "Krypt::ASN1::Template::Sequence" do
290
+ it_behaves_like "Krypt::ASN1::Template"
291
+ it_behaves_like "constructed type constructor", Krypt::ASN1::Template::Sequence
292
+ it_behaves_like "DER-based equality with <=>", Krypt::ASN1::Template::Sequence
293
+ it_behaves_like "accepting fields with special name", Krypt::ASN1::Template::Sequence, :tag
294
+ it_behaves_like "accepting fields with special name", Krypt::ASN1::Template::Sequence, :type
295
+ end
296
+
297
+ describe "Krypt::ASN1::Template::Set" do
298
+ it_behaves_like "Krypt::ASN1::Template"
299
+ it_behaves_like "constructed type constructor", Krypt::ASN1::Template::Set
300
+ it_behaves_like "DER-based equality with <=>", Krypt::ASN1::Template::Set
301
+ it_behaves_like "accepting fields with special name", Krypt::ASN1::Template::Set, :tag
302
+ it_behaves_like "accepting fields with special name", Krypt::ASN1::Template::Set, :type
303
+ end
304
+
305
+ describe "Krypt::ASN1::Template::Choice" do
306
+ let (:template) do
307
+ Class.new do
308
+ include Krypt::ASN1::Template::Choice
309
+ asn1_integer
310
+ asn1_boolean
311
+ end
312
+ end
313
+
314
+ describe "#new" do
315
+ it "takes no-args" do
316
+ template.new.should be_an_instance_of template
317
+ end
318
+
319
+ it "takes a block and yields the new instance" do
320
+ template.new do |o|
321
+ o.should be_an_instance_of template
322
+ end
323
+ end
324
+
325
+ it "allows assignment to 'value' once instantiated" do
326
+ o = template.new
327
+ o.value = 42
328
+ o.value.should == 42
329
+ end
330
+
331
+ it "allows assignment to 'type' once instantiated" do
332
+ o = template.new
333
+ o.type = Krypt::ASN1::INTEGER
334
+ o.type.should == Krypt::ASN1::INTEGER
335
+ end
336
+
337
+ it "allows assignment to 'tag' once instantiated" do
338
+ o = template.new
339
+ o.tag = Krypt::ASN1::INTEGER
340
+ o.tag.should == Krypt::ASN1::INTEGER
341
+ end
342
+
343
+ it "allows assignment to 'value' inside the block" do
344
+ obj = template.new do |o|
345
+ o.value = 42
346
+ end
347
+ obj.value.should == 42
348
+ end
349
+ end
350
+ end
351
+
@@ -0,0 +1,64 @@
1
+ # encoding: US-ASCII
2
+
3
+ require 'rspec'
4
+ require 'krypt'
5
+ require_relative '../resources'
6
+
7
+ describe "Krypt::ASN1::Template::SequenceOf" do
8
+ SEQ_OF = Krypt::ASN1::Template::SequenceOf
9
+ let(:asn1error) { Krypt::ASN1::ASN1Error }
10
+
11
+ context "extracted from parse_der" do
12
+ subject { template.parse_der(der) }
13
+ let(:template) do
14
+ t = type
15
+ Class.new do
16
+ include SEQ_OF
17
+ asn1_type t
18
+ end
19
+ end
20
+
21
+ context "primitive contents" do
22
+ let(:type) { Krypt::ASN1::Integer }
23
+ let(:der) { "\x30\x06\x02\x01\x01\x02\x01\x01" }
24
+ its(:value) { should be_an_instance_of Array }
25
+ it { subject.value.size.should == 2 }
26
+ it { subject.value.all? { |v| v.instance_of?(Krypt::ASN1::Integer) && v.value == 1 }.should == true }
27
+ its(:to_der) { should == der }
28
+ end
29
+
30
+ context "template contents" do
31
+ context "SEQUENCE" do
32
+ let(:type) do
33
+ Class.new do
34
+ include Krypt::ASN1::Template::Sequence
35
+ asn1_boolean :a
36
+ end
37
+ end
38
+ let(:der) { "\x30\x0A\x30\x03\x01\x01\xFF\x30\x03\x01\x01\xFF" }
39
+ its(:value) { should be_an_instance_of Array }
40
+ it { subject.value.size.should == 2 }
41
+ it { subject.value.all? { |v| v.instance_of?(type) && v.a == true }.should == true }
42
+ its(:to_der) { should == der }
43
+ end
44
+
45
+ context "nested" do
46
+ let(:type) do
47
+ Class.new do
48
+ include SEQ_OF
49
+ asn1_type Krypt::ASN1::Integer
50
+ end
51
+ end
52
+ let(:der) { "\x30\x0D\x30\x06\x02\x01\x01\x02\x01\x01\x30\x03\x02\x01\x02" }
53
+ its(:value) { should be_an_instance_of Array }
54
+ it { subject.value.size.should == 2 }
55
+ it { subject.value[0].value.size.should == 2 }
56
+ it { subject.value[0].value.all? { |v| v.instance_of?(Krypt::ASN1::Integer) && v.value == 1 }.should == true }
57
+ it { subject.value[1].value.size.should == 1 }
58
+ it { subject.value[1].value.all? { |v| v.instance_of?(Krypt::ASN1::Integer) && v.value == 2 }.should == true }
59
+ its(:to_der) { should == der }
60
+ end
61
+ end
62
+ end
63
+ end
64
+
@@ -0,0 +1,1241 @@
1
+ # encoding: US-ASCII
2
+
3
+ require 'rspec'
4
+ require 'krypt'
5
+ require_relative '../resources'
6
+
7
+
8
+ describe "Krypt::ASN1::Template::Sequence" do
9
+ SEQ = Krypt::ASN1::Template::Sequence
10
+ let(:asn1error) { Krypt::ASN1::ASN1Error }
11
+
12
+ context "extracted from parse_der" do
13
+ subject { template.parse_der(der) }
14
+
15
+ context "single field" do
16
+ let(:template) do
17
+ Class.new do
18
+ include SEQ
19
+ asn1_integer :version
20
+ end
21
+ end
22
+ context "accepts correct encoding" do
23
+ let(:der) { "\x30\x03\x02\x01\x01" }
24
+ its(:version) { should == 1 }
25
+ it { subject.should be_an_instance_of template }
26
+ its(:to_der) { should == der }
27
+ end
28
+ context "rejects wrong encoding" do
29
+ let(:der) { "\x30\x03\x04\x01\x01" }
30
+ it { -> { subject.version }.should raise_error asn1error }
31
+ end
32
+ context "rejects encoding that is too long" do
33
+ let(:der) { "\x30\x06\x04\x01\x01\x04\x01\x01" }
34
+ it { -> { subject.version }.should raise_error asn1error }
35
+ end
36
+ context "rejects encoding that is not complete" do
37
+ let(:der) { "\x30\x03\x04\x01" }
38
+ it { -> { subject.version }.should raise_error asn1error }
39
+ end
40
+ end
41
+
42
+ context "two fields" do
43
+ let(:template) do
44
+ Class.new do
45
+ include SEQ
46
+ asn1_integer :version
47
+ asn1_boolean :works?
48
+ end
49
+ end
50
+ context "accepts correct encoding" do
51
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
52
+ its(:version) { should == 1 }
53
+ its(:works?) { should == true }
54
+ it { subject.should be_an_instance_of template }
55
+ its(:to_der) { should == der }
56
+ end
57
+ context "rejects encodings where either field is missing" do
58
+ context "(first)" do
59
+ let(:der) { "\x30\x03\x01\x01\xFF" }
60
+ it { -> { subject.version }.should raise_error asn1error }
61
+ end
62
+ context "(second)" do
63
+ let(:der) { "\x30\x03\x02\x01\x01" }
64
+ it { -> { subject.version }.should raise_error asn1error }
65
+ end
66
+ end
67
+ end
68
+
69
+ context "preserves non-DER encodings" do
70
+ let(:template) do
71
+ Class.new do
72
+ include SEQ
73
+ asn1_boolean :a
74
+ asn1_octet_string :b
75
+ end
76
+ end
77
+ let(:der) { "\x30\x83\x00\x00\x0D\x01\x01\xBB\x24\x80\x04\x01\x01\x04\x01\x02\x00\x00" }
78
+ its(:to_der) { should == der }
79
+ end
80
+
81
+ context "does not choke on invalid encodings" do
82
+ let(:template) do
83
+ Class.new do
84
+ include SEQ
85
+ asn1_integer :a
86
+ asn1_octet_string :b
87
+ end
88
+ end
89
+
90
+ context "when parsing them" do
91
+ let(:der) { "\x30\x04\x00\x00\x22\x99" }
92
+ it { -> { subject }.should_not raise_error }
93
+ end
94
+
95
+ context "and encodes them again exactly as received" do
96
+ let(:der) { "\x30\x04\x00\x00\x22\x99" }
97
+ its(:to_der) { should == der }
98
+ end
99
+
100
+ context "but raises an error when accessing the fields" do
101
+ let(:der) { "\x30\x04\x00\x00\x22\x99" }
102
+ it { -> { subject.a }.should raise_error asn1error }
103
+ end
104
+
105
+ context "but raises an error if the tag doesn't match" do
106
+ let(:der) { "\x31\x06\x02\x01\x01\x04\x01a" }
107
+ it { -> { subject.a }.should raise_error asn1error }
108
+ end
109
+ end
110
+
111
+ context "tagged field" do
112
+ let(:template) do
113
+ t = tag
114
+ tg = tagging
115
+ Class.new do
116
+ include SEQ
117
+ asn1_integer :a, tag: t, tagging: tg
118
+ asn1_boolean :b
119
+ end
120
+ end
121
+
122
+ shared_examples_for "a non-constructed encoding" do |tagging, tag_byte|
123
+ context "accepts correct encoding" do
124
+ let(:der) { "\x30\x06#{tag_byte}\x01\x01\x01\x01\xFF" }
125
+ let(:tag) { 0 }
126
+ let(:tagging) { tagging }
127
+ its(:a) { should == 1 }
128
+ its(:b) { should == true }
129
+ its(:to_der) { should == der }
130
+ end
131
+
132
+ context "rejects wrong encoding" do
133
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
134
+ let(:tag) { 0 }
135
+ let(:tagging) { tagging }
136
+ it { -> { subject.a }.should raise_error asn1error }
137
+ end
138
+ end
139
+
140
+ context ":IMPLICIT" do
141
+ it_behaves_like "a non-constructed encoding", :IMPLICIT, "\x80"
142
+ end
143
+
144
+ context ":EXPLICIT" do
145
+ context "accepts correct encoding" do
146
+ let(:der) { "\x30\x08\xA0\x03\x02\x01\x01\x01\x01\xFF" }
147
+ let(:tag) { 0 }
148
+ let(:tagging) { :EXPLICIT }
149
+ its(:a) { should == 1 }
150
+ its(:b) { should == true }
151
+ its(:to_der) { should == der }
152
+ end
153
+
154
+ context "reject wrong encoding (non-constructed)" do
155
+ let(:der) { "\x30\x08\x80\x03\x02\x01\x01\x01\x01\xFF" }
156
+ let(:tag) { 0 }
157
+ let(:tagging) { :EXPLICIT }
158
+ it { -> { subject.a }.should raise_error asn1error }
159
+ end
160
+
161
+ context "reject wrong encoding" do
162
+ let(:der) { "\x30\x06\x80\x01\x01\x01\x01\xFF" }
163
+ let(:tag) { 0 }
164
+ let(:tagging) { :EXPLICIT }
165
+ it { -> { subject.a }.should raise_error asn1error }
166
+ end
167
+ end
168
+
169
+ context ":CONTEXT_SPECIFIC" do
170
+ it_behaves_like "a non-constructed encoding", :IMPLICIT, "\x80"
171
+ end
172
+
173
+ context ":APPLICATION" do
174
+ it_behaves_like "a non-constructed encoding", :APPLICATION, "\x40"
175
+ end
176
+
177
+ context ":PRIVATE" do
178
+ it_behaves_like "a non-constructed encoding", :PRIVATE, "\xC0"
179
+ end
180
+ end
181
+
182
+ context "optional first field" do
183
+ let(:template) do
184
+ Class.new do
185
+ include SEQ
186
+ asn1_integer :a, optional: true
187
+ asn1_boolean :b
188
+ asn1_octet_string :c
189
+ end
190
+ end
191
+
192
+ context "present" do
193
+ let(:der) { "\x30\x09\x02\x01\x01\x01\x01\xFF\x04\x01a" }
194
+ its(:a) { should == 1 }
195
+ its(:b) { should == true }
196
+ its(:c) { should == "a" }
197
+ it { subject.should be_an_instance_of template }
198
+ its(:to_der) { should == der }
199
+ end
200
+
201
+ context "absent" do
202
+ let(:der) { "\x30\x06\x01\x01\xFF\x04\x01a" }
203
+ its(:a) { should be_nil }
204
+ its(:b) { should == true }
205
+ its(:c) { should == "a" }
206
+ it { subject.should be_an_instance_of template }
207
+ its(:to_der) { should == der }
208
+ end
209
+ end
210
+
211
+ context "optional field between others" do
212
+ let(:template) do
213
+ Class.new do
214
+ include SEQ
215
+ asn1_integer :a
216
+ asn1_boolean :b, optional: true
217
+ asn1_octet_string :c
218
+ end
219
+ end
220
+
221
+ context "present" do
222
+ let(:der) { "\x30\x09\x02\x01\x01\x01\x01\xFF\x04\x01a" }
223
+ its(:a) { should == 1 }
224
+ its(:b) { should == true }
225
+ its(:c) { should == "a" }
226
+ it { subject.should be_an_instance_of template }
227
+ its(:to_der) { should == der }
228
+ end
229
+
230
+ context "absent" do
231
+ let(:der) { "\x30\x06\x02\x01\x01\x04\x01a" }
232
+ its(:a) { should == 1 }
233
+ its(:b) { should be_nil }
234
+ its(:c) { should == "a" }
235
+ it { subject.should be_an_instance_of template }
236
+ its(:to_der) { should == der }
237
+ end
238
+ end
239
+
240
+ context "optional field at end" do
241
+ let(:template) do
242
+ Class.new do
243
+ include SEQ
244
+ asn1_integer :a
245
+ asn1_boolean :b
246
+ asn1_octet_string :c, optional: true
247
+ end
248
+ end
249
+
250
+ context "present" do
251
+ let(:der) { "\x30\x09\x02\x01\x01\x01\x01\xFF\x04\x01a" }
252
+ its(:a) { should == 1 }
253
+ its(:b) { should == true }
254
+ its(:c) { should == "a" }
255
+ it { subject.should be_an_instance_of template }
256
+ its(:to_der) { should == der }
257
+ end
258
+
259
+ context "absent" do
260
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
261
+ its(:a) { should == 1 }
262
+ its(:b) { should == true }
263
+ its(:c) { should be_nil }
264
+ it { subject.should be_an_instance_of template }
265
+ its(:to_der) { should == der }
266
+ end
267
+ end
268
+
269
+ context "multiple optional fields at end" do
270
+ let(:template) do
271
+ Class.new do
272
+ include SEQ
273
+ asn1_integer :a
274
+ asn1_boolean :b
275
+ asn1_octet_string :c, optional: true
276
+ asn1_t61_string :d, optional: true
277
+ asn1_ia5_string :e, optional: true
278
+ end
279
+ end
280
+
281
+ context "all present" do
282
+ let(:der) { "\x30\x0F\x02\x01\x01\x01\x01\xFF\x04\x01a\x14\x01b\x16\x01c" }
283
+ its(:a) { should == 1 }
284
+ its(:b) { should == true }
285
+ its(:c) { should == "a" }
286
+ its(:d) { should == "b" }
287
+ its(:e) { should == "c" }
288
+ it { subject.should be_an_instance_of template }
289
+ its(:to_der) { should == der }
290
+ end
291
+
292
+ context "first absent" do
293
+ let(:der) { "\x30\x0C\x02\x01\x01\x01\x01\xFF\x14\x01b\x16\x01c" }
294
+ its(:a) { should == 1 }
295
+ its(:b) { should == true }
296
+ its(:c) { should be_nil }
297
+ its(:d) { should == "b" }
298
+ its(:e) { should == "c" }
299
+ it { subject.should be_an_instance_of template }
300
+ its(:to_der) { should == der }
301
+ end
302
+
303
+ context "absent between others" do
304
+ let(:der) { "\x30\x0C\x02\x01\x01\x01\x01\xFF\x04\x01a\x16\x01c" }
305
+ its(:a) { should == 1 }
306
+ its(:b) { should == true }
307
+ its(:c) { should == "a" }
308
+ its(:d) { should be_nil }
309
+ its(:e) { should == "c" }
310
+ it { subject.should be_an_instance_of template }
311
+ its(:to_der) { should == der }
312
+ end
313
+
314
+ context "last absent" do
315
+ let(:der) { "\x30\x0C\x02\x01\x01\x01\x01\xFF\x04\x01a\x14\x01b" }
316
+ its(:a) { should == 1 }
317
+ its(:b) { should == true }
318
+ its(:c) { should == "a" }
319
+ its(:d) { should == "b"}
320
+ its(:e) { should be_nil }
321
+ it { subject.should be_an_instance_of template }
322
+ its(:to_der) { should == der }
323
+ end
324
+
325
+ context "all absent" do
326
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
327
+ its(:a) { should == 1 }
328
+ its(:b) { should == true }
329
+ its(:c) { should be_nil }
330
+ its(:d) { should be_nil }
331
+ its(:e) { should be_nil }
332
+ it { subject.should be_an_instance_of template }
333
+ its(:to_der) { should == der }
334
+ end
335
+ end
336
+
337
+ context "single first default value field" do
338
+ let(:template) do
339
+ Class.new do
340
+ include SEQ
341
+ asn1_integer :a, default: 42
342
+ asn1_boolean :b
343
+ end
344
+ end
345
+
346
+ context "present" do
347
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
348
+ its(:a) { should == 1 }
349
+ its(:b) { should == true }
350
+ it { subject.should be_an_instance_of template }
351
+ its(:to_der) { should == der }
352
+ end
353
+
354
+ context "absent" do
355
+ let(:der) { "\x30\x03\x01\x01\xFF" }
356
+ its(:a) { should == 42 }
357
+ its(:b) { should == true }
358
+ it { subject.should be_an_instance_of template }
359
+ its(:to_der) { should == der }
360
+ end
361
+ end
362
+
363
+ context "default value field between others" do
364
+ let(:template) do
365
+ Class.new do
366
+ include SEQ
367
+ asn1_integer :a
368
+ asn1_boolean :b, default: false
369
+ asn1_octet_string :c
370
+ end
371
+ end
372
+
373
+ context "present" do
374
+ let(:der) { "\x30\x09\x02\x01\x01\x01\x01\xFF\x04\x01a" }
375
+ its(:a) { should == 1 }
376
+ its(:b) { should == true }
377
+ its(:c) { should == "a" }
378
+ it { subject.should be_an_instance_of template }
379
+ its(:to_der) { should == der }
380
+ end
381
+
382
+ context "absent" do
383
+ let(:der) { "\x30\x06\x02\x01\x01\x04\x01a" }
384
+ its(:a) { should == 1 }
385
+ its(:b) { should == false }
386
+ its(:c) { should == "a" }
387
+ it { subject.should be_an_instance_of template }
388
+ its(:to_der) { should == der }
389
+ end
390
+ end
391
+
392
+ context "default value field at end" do
393
+ let(:template) do
394
+ Class.new do
395
+ include SEQ
396
+ asn1_integer :a
397
+ asn1_boolean :b
398
+ asn1_octet_string :c, default: "b"
399
+ end
400
+ end
401
+
402
+ context "present" do
403
+ let(:der) { "\x30\x09\x02\x01\x01\x01\x01\xFF\x04\x01a" }
404
+ its(:a) { should == 1 }
405
+ its(:b) { should == true }
406
+ its(:c) { should == "a" }
407
+ it { subject.should be_an_instance_of template }
408
+ its(:to_der) { should == der }
409
+ end
410
+
411
+ context "absent" do
412
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
413
+ its(:a) { should == 1 }
414
+ its(:b) { should == true }
415
+ its(:c) { should == "b" }
416
+ it { subject.should be_an_instance_of template }
417
+ its(:to_der) { should == der }
418
+ end
419
+ end
420
+
421
+ context "multiple default value fields at end" do
422
+ let(:template) do
423
+ Class.new do
424
+ include SEQ
425
+ asn1_integer :a
426
+ asn1_boolean :b
427
+ asn1_octet_string :c, default: "a"
428
+ asn1_t61_string :d, default: "a"
429
+ asn1_ia5_string :e, default: "a"
430
+ end
431
+ end
432
+
433
+ context "all present" do
434
+ let(:der) { "\x30\x0F\x02\x01\x01\x01\x01\xFF\x04\x01b\x14\x01b\x16\x01b" }
435
+ its(:a) { should == 1 }
436
+ its(:b) { should == true }
437
+ its(:c) { should == "b" }
438
+ its(:d) { should == "b" }
439
+ its(:e) { should == "b" }
440
+ it { subject.should be_an_instance_of template }
441
+ its(:to_der) { should == der }
442
+ end
443
+
444
+ context "first absent" do
445
+ let(:der) { "\x30\x0C\x02\x01\x01\x01\x01\xFF\x14\x01b\x16\x01b" }
446
+ its(:a) { should == 1 }
447
+ its(:b) { should == true }
448
+ its(:c) { should == "a" }
449
+ its(:d) { should == "b" }
450
+ its(:e) { should == "b" }
451
+ it { subject.should be_an_instance_of template }
452
+ its(:to_der) { should == der }
453
+ end
454
+
455
+ context "absent between others" do
456
+ let(:der) { "\x30\x0C\x02\x01\x01\x01\x01\xFF\x04\x01b\x16\x01b" }
457
+ its(:a) { should == 1 }
458
+ its(:b) { should == true }
459
+ its(:c) { should == "b" }
460
+ its(:d) { should == "a" }
461
+ its(:e) { should == "b" }
462
+ it { subject.should be_an_instance_of template }
463
+ its(:to_der) { should == der }
464
+ end
465
+
466
+ context "last absent" do
467
+ let(:der) { "\x30\x0C\x02\x01\x01\x01\x01\xFF\x04\x01b\x14\x01b" }
468
+ its(:a) { should == 1 }
469
+ its(:b) { should == true }
470
+ its(:c) { should == "b" }
471
+ its(:d) { should == "b"}
472
+ its(:e) { should == "a" }
473
+ it { subject.should be_an_instance_of template }
474
+ its(:to_der) { should == der }
475
+ end
476
+
477
+ context "all absent" do
478
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
479
+ its(:a) { should == 1 }
480
+ its(:b) { should == true }
481
+ its(:c) { should == "a" }
482
+ its(:d) { should == "a" }
483
+ its(:e) { should == "a" }
484
+ it { subject.should be_an_instance_of template }
485
+ its(:to_der) { should == der }
486
+ end
487
+ end
488
+
489
+ context "default value and optional fields mixed at beginning" do
490
+ let(:template) do
491
+ Class.new do
492
+ include SEQ
493
+ asn1_octet_string :a, optional: true
494
+ asn1_t61_string :b, default: "a"
495
+ asn1_ia5_string :c, default: "a"
496
+ asn1_integer :d
497
+ end
498
+ end
499
+
500
+ context "all present" do
501
+ let(:der) { "\x30\x0C\x04\x01b\x14\x01b\x16\x01b\x02\x01\x01" }
502
+ its(:a) { should == "b" }
503
+ its(:b) { should == "b" }
504
+ its(:c) { should == "b" }
505
+ its(:d) { should == 1 }
506
+ its(:to_der) { should == der }
507
+ end
508
+
509
+ context "all absent" do
510
+ let(:der) { "\x30\x03\x02\x01\x01" }
511
+ its(:a) { should be_nil }
512
+ its(:b) { should == "a" }
513
+ its(:c) { should == "a" }
514
+ its(:d) { should == 1 }
515
+ its(:to_der) { should == der }
516
+ end
517
+
518
+ context "rejects otherwise correct encoding if stream is not consumed" do
519
+ let(:der) { "\x30\x06\x02\x01\x01\x04\x01\x01" } # :d is matched, all others optional or default
520
+ it { -> { subject.a }.should raise_error asn1error }
521
+ end
522
+
523
+ context "rejects when wrong encoding is given for an optional field" do
524
+ let(:der) { "\x30\x0C\x01\x01\x00\x14\x01b\x16\x01b\x02\x01\x01" }
525
+ it { -> { subject.a }.should raise_error asn1error }
526
+ end
527
+
528
+ context "rejects when wrong encoding is given for a default field" do
529
+ let(:der) { "\x30\x0C\x04\x01\x01\x04\x01b\x16\x01b\x02\x01\x01" }
530
+ it { -> { subject.a }.should raise_error asn1error }
531
+ end
532
+
533
+ context "rejects when wrong encoding is given for a default field and the
534
+ optional field is omitted" do
535
+ let(:der) { "\x30\x09\x01\x01\xFF\x16\x01b\x02\x01\x01" }
536
+ it { -> { subject.a }.should raise_error asn1error }
537
+ end
538
+ end
539
+
540
+ context "default value and optional fields mixed at end" do
541
+ let(:template) do
542
+ Class.new do
543
+ include SEQ
544
+ asn1_integer :a
545
+ asn1_octet_string :b, optional: true
546
+ asn1_t61_string :c, default: "a"
547
+ asn1_ia5_string :d, default: "a"
548
+ end
549
+ end
550
+
551
+ context "all present" do
552
+ let(:der) { "\x30\x0C\x02\x01\x01\x04\x01b\x14\x01b\x16\x01b" }
553
+ its(:a) { should == 1 }
554
+ its(:b) { should == "b" }
555
+ its(:c) { should == "b" }
556
+ its(:d) { should == "b" }
557
+ its(:to_der) { should == der }
558
+ end
559
+
560
+ context "all absent" do
561
+ let(:der) { "\x30\x03\x02\x01\x01" }
562
+ its(:a) { should == 1 }
563
+ its(:b) { should be_nil }
564
+ its(:c) { should == "a" }
565
+ its(:d) { should == "a" }
566
+ its(:to_der) { should == der }
567
+ end
568
+ end
569
+
570
+ context "inner template" do
571
+ let(:template2) do
572
+ Class.new do
573
+ include SEQ
574
+ asn1_boolean :a
575
+ end
576
+ end
577
+
578
+ context "at beginning" do
579
+ let(:template) do
580
+ t = template2
581
+ Class.new do
582
+ include SEQ
583
+ asn1_template :a, t
584
+ asn1_integer :b
585
+ end
586
+ end
587
+
588
+ context "accepts valid encoding" do
589
+ let(:der) { "\x30\x08\x30\x03\x01\x01\xFF\x02\x01\x01" }
590
+ its(:a) { should be_an_instance_of template2 }
591
+ it { subject.a.a.should == true }
592
+ its(:b) { should == 1 }
593
+ its(:to_der) { should == der }
594
+ end
595
+
596
+ context "rejects wrong encoding" do
597
+ let(:der) { "\x30\x06\x01\x01\xFF\x02\x01\x01" }
598
+ it { -> { subject.a }.should raise_error asn1error }
599
+ end
600
+ end
601
+
602
+ context "at end" do
603
+ let(:template) do
604
+ t = template2
605
+ Class.new do
606
+ include SEQ
607
+ asn1_integer :a
608
+ asn1_template :b, t
609
+ end
610
+ end
611
+
612
+ context "accepts valid encoding" do
613
+ let(:der) { "\x30\x08\x02\x01\x01\x30\x03\x01\x01\xFF" }
614
+ its(:a) { should == 1 }
615
+ its(:b) { should be_an_instance_of template2 }
616
+ it { subject.b.a.should == true }
617
+ its(:to_der) { should == der }
618
+ end
619
+
620
+ context "rejects wrong encoding" do
621
+ let(:der) { "\x31\x08\x02\x01\x01\x30\x03\x01\x01\xFF" }
622
+ it { -> { subject.a }.should raise_error asn1error }
623
+ end
624
+ end
625
+
626
+ context "with implicit tagging" do
627
+ let(:template) do
628
+ t = template2
629
+ Class.new do
630
+ include SEQ
631
+ asn1_template :a, t, tag: 0, tagging: :IMPLICIT
632
+ asn1_integer :b
633
+ end
634
+ end
635
+
636
+ context "accepts valid encoding" do
637
+ let(:der) { "\x30\x08\xA0\x03\x01\x01\xFF\x02\x01\x01" }
638
+ its(:a) { should be_an_instance_of template2 }
639
+ it { subject.a.a.should == true }
640
+ its(:b) { should == 1 }
641
+ its(:to_der) { should == der }
642
+ end
643
+
644
+ context "rejects wrong encoding" do
645
+ let(:der) { "\x30\x08\x30\x03\x01\x01\xFF\x02\x01\x01" }
646
+ it { -> { subject.a }.should raise_error asn1error }
647
+ end
648
+ end
649
+
650
+ context "with explicit tagging" do
651
+ let(:template) do
652
+ t = template2
653
+ Class.new do
654
+ include SEQ
655
+ asn1_template :a, t, tag: 0, tagging: :EXPLICIT
656
+ asn1_integer :b
657
+ end
658
+ end
659
+
660
+ context "accepts valid encoding" do
661
+ let(:der) { "\x30\x0A\xA0\x05\x30\x03\x01\x01\xFF\x02\x01\x01" }
662
+ its(:a) { should be_an_instance_of template2 }
663
+ it { subject.a.a.should == true }
664
+ its(:b) { should == 1 }
665
+ its(:to_der) { should == der }
666
+ end
667
+
668
+ context "rejects wrong encoding" do
669
+ let(:der) { "\x30\x08\x30\x03\x01\x01\xFF\x02\x01\x01" }
670
+ it { -> { subject.a }.should raise_error asn1error }
671
+ end
672
+ end
673
+
674
+ context "optional" do
675
+ let(:template) do
676
+ t = template2
677
+ Class.new do
678
+ include SEQ
679
+ asn1_template :a, t, optional: true
680
+ asn1_integer :b
681
+ end
682
+ end
683
+
684
+ context "present" do
685
+ let(:der) { "\x30\x08\x30\x03\x01\x01\xFF\x02\x01\x01" }
686
+ its(:a) { should be_an_instance_of template2 }
687
+ it { subject.a.a.should == true }
688
+ its(:b) { should == 1 }
689
+ its(:to_der) { should == der }
690
+ end
691
+
692
+ context "absent" do
693
+ let(:der) { "\x30\x03\x02\x01\x01" }
694
+ its(:a) { should be_nil }
695
+ its(:b) { should == 1 }
696
+ its(:to_der) { should == der }
697
+ end
698
+ end
699
+
700
+ context "with default value at beginning" do
701
+ let(:template) do
702
+ t = template2
703
+ obj = t.new
704
+ obj.a = false
705
+ Class.new do
706
+ include SEQ
707
+ asn1_template :a, t, default: obj
708
+ asn1_integer :b
709
+ end
710
+ end
711
+
712
+ context "present" do
713
+ let(:der) { "\x30\x08\x30\x03\x01\x01\xFF\x02\x01\x01" }
714
+ its(:a) { should be_an_instance_of template2 }
715
+ it { subject.a.a.should == true }
716
+ its(:b) { should == 1 }
717
+ its(:to_der) { should == der }
718
+ end
719
+
720
+ context "absent" do
721
+ let(:der) { "\x30\x03\x02\x01\x01" }
722
+ its(:a) { should be_an_instance_of template2 }
723
+ it { subject.a.a.should == false }
724
+ its(:b) { should == 1 }
725
+ its(:to_der) { should == der }
726
+ end
727
+ end
728
+
729
+ context "with default value at end" do
730
+ let(:template) do
731
+ t = template2
732
+ obj = t.new
733
+ obj.a = false
734
+ Class.new do
735
+ include SEQ
736
+ asn1_integer :a
737
+ asn1_template :b, t, default: obj
738
+ end
739
+ end
740
+
741
+ context "present" do
742
+ let(:der) { "\x30\x08\x02\x01\x01\x30\x03\x01\x01\xFF" }
743
+ its(:a) { should == 1 }
744
+ its(:b) { should be_an_instance_of template2 }
745
+ it { subject.b.a.should == true }
746
+ its(:to_der) { should == der }
747
+ end
748
+
749
+ context "absent" do
750
+ let(:der) { "\x30\x03\x02\x01\x01" }
751
+ its(:a) { should == 1 }
752
+ its(:b) { should be_an_instance_of template2 }
753
+ it { subject.b.a.should == false }
754
+ its(:to_der) { should == der }
755
+ end
756
+ end
757
+ end
758
+
759
+ context "SEQUENCE OF" do
760
+ context "standard" do
761
+ let(:template) do
762
+ t = type
763
+ Class.new do
764
+ include SEQ
765
+ asn1_sequence_of :a, t
766
+ end
767
+ end
768
+
769
+ context "multiple Templates" do
770
+ let(:template2) do
771
+ Class.new do
772
+ include SEQ
773
+ asn1_integer :a
774
+ end
775
+ end
776
+ let(:type) { template2 }
777
+ let(:der) { "\x30\x0C\x30\x0A\x30\x03\x02\x01\x01\x30\x03\x02\x01\x01" }
778
+ its(:a) { should be_an_instance_of Array }
779
+ it { subject.a.size.should == 2 }
780
+ it { subject.a.all? { |asn1| asn1.instance_of?(type) && asn1.a == 1 }.should == true }
781
+ its(:to_der) { should == der }
782
+ end
783
+
784
+ context "multiple Primitives" do
785
+ let(:type) { Krypt::ASN1::Integer }
786
+ let(:der) { "\x30\x08\x30\x06\x02\x01\x01\x02\x01\x01" }
787
+ its(:a) { should be_an_instance_of Array }
788
+ it { subject.a.size.should == 2 }
789
+ it { subject.a.all? { |asn1| asn1.instance_of?(type) && asn1.value == 1 }.should == true }
790
+ its(:to_der) { should == der }
791
+ end
792
+ end
793
+ end
794
+
795
+ context "SET OF" do
796
+ context "standard" do
797
+ let(:template) do
798
+ t = type
799
+ Class.new do
800
+ include SEQ
801
+ asn1_set_of :a, t
802
+ end
803
+ end
804
+
805
+ context "multiple Templates" do
806
+ let(:template2) do
807
+ Class.new do
808
+ include SEQ
809
+ asn1_integer :a
810
+ end
811
+ end
812
+ let(:type) { template2 }
813
+ let(:der) { "\x30\x0C\x31\x0A\x30\x03\x02\x01\x01\x30\x03\x02\x01\x01" }
814
+ its(:a) { should be_an_instance_of Array }
815
+ it { subject.a.size.should == 2 }
816
+ it { subject.a.all? { |asn1| asn1.instance_of?(type) && asn1.a == 1 }.should == true }
817
+ its(:to_der) { should == der }
818
+ end
819
+
820
+ context "multiple Primitives" do
821
+ let(:type) { Krypt::ASN1::Integer }
822
+ let(:der) { "\x30\x08\x31\x06\x02\x01\x01\x02\x01\x01" }
823
+ its(:a) { should be_an_instance_of Array }
824
+ it { subject.a.size.should == 2 }
825
+ it { subject.a.all? { |asn1| asn1.instance_of?(type) && asn1.value == 1 }.should == true }
826
+ its(:to_der) { should == der }
827
+ end
828
+ end
829
+ end
830
+
831
+ context "ANY values" do
832
+ context "at beginning" do
833
+ let(:template) do
834
+ Class.new do
835
+ include SEQ
836
+ asn1_any :a
837
+ asn1_boolean :b
838
+ end
839
+ end
840
+
841
+ context "as primitive value" do
842
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
843
+ its(:a) { should be_an_instance_of Krypt::ASN1::Integer }
844
+ it { subject.a.value.should == 1 }
845
+ its(:b) { should == true }
846
+ its(:to_der) { should == der }
847
+ end
848
+
849
+ context "as sequence" do
850
+ let(:der) { "\x30\x0B\x30\x06\x02\x01\x01\x02\x01\x01\x01\x01\xFF" }
851
+ its(:a) { should be_an_instance_of Krypt::ASN1::Sequence }
852
+ it { subject.a.value.should be_an_instance_of Array }
853
+ it { subject.a.value.size.should == 2 }
854
+ it { subject.a.value.all? { |v| v.instance_of?(Krypt::ASN1::Integer) && v.value == 1 }.should == true }
855
+ its(:b) { should == true }
856
+ its(:to_der) { should == der }
857
+ end
858
+ end
859
+
860
+ context "at end" do
861
+ let(:template) do
862
+ Class.new do
863
+ include SEQ
864
+ asn1_integer :a
865
+ asn1_any :b
866
+ end
867
+ end
868
+
869
+ context "as primitive value" do
870
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
871
+ its(:a) { should == 1 }
872
+ its(:b) { should be_an_instance_of Krypt::ASN1::Boolean }
873
+ it { subject.b.value.should == true }
874
+ its(:to_der) { should == der }
875
+ end
876
+
877
+ context "as sequence" do
878
+ let(:der) { "\x30\x0B\x02\x01\x02\x30\x06\x02\x01\x01\x02\x01\x01" }
879
+ its(:a) { should == 2 }
880
+ its(:b) { should be_an_instance_of Krypt::ASN1::Sequence }
881
+ it { subject.b.value.should be_an_instance_of Array }
882
+ it { subject.b.value.size.should == 2 }
883
+ it { subject.b.value.all? { |v| v.instance_of?(Krypt::ASN1::Integer) && v.value == 1 }.should == true }
884
+ its(:to_der) { should == der }
885
+ end
886
+ end
887
+
888
+ context "optionally and tagged between mandatory" do
889
+ let(:template) do
890
+ Class.new do
891
+ include SEQ
892
+ asn1_integer :a
893
+ asn1_any :b, tag: 0, tagging: :IMPLICIT, optional: true
894
+ asn1_boolean :c
895
+ end
896
+ end
897
+
898
+ context "present" do
899
+ let(:der) { "\x30\x09\x02\x01\x01\x80\x01a\x01\x01\xFF" }
900
+ its(:a) { should == 1 }
901
+ its(:b) { should be_an_instance_of Krypt::ASN1::ASN1Data }
902
+ it { subject.b.value.should == "a" }
903
+ it { subject.b.tag.should == 0 }
904
+ it { subject.b.tag_class.should == :CONTEXT_SPECIFIC }
905
+ its(:c) { should == true }
906
+ its(:to_der) { should == der }
907
+ end
908
+
909
+ context "absent" do
910
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
911
+ its(:a) { should == 1 }
912
+ its(:b) { should be_nil }
913
+ its(:c) { should == true }
914
+ its(:to_der) { should == der }
915
+ end
916
+ end
917
+
918
+ context "tagged with default" do
919
+ let(:null) { Krypt::ASN1::Null.new }
920
+ context
921
+ let(:template) do
922
+ n = null
923
+ Class.new do
924
+ include SEQ
925
+ asn1_integer :a
926
+ asn1_any :b, tag: 0, tagging: :IMPLICIT, default: n
927
+ asn1_boolean :c
928
+ end
929
+ end
930
+
931
+ context "present" do
932
+ let(:der) { "\x30\x09\x02\x01\x01\x80\x01a\x01\x01\xFF" }
933
+ its(:a) { should == 1 }
934
+ its(:b) { should be_an_instance_of Krypt::ASN1::ASN1Data }
935
+ it { subject.b.value.should == "a" }
936
+ it { subject.b.tag.should == 0 }
937
+ it { subject.b.tag_class.should == :CONTEXT_SPECIFIC }
938
+ its(:c) { should == true }
939
+ its(:to_der) { should == der }
940
+ end
941
+
942
+ context "absent" do
943
+ let(:der) { "\x30\x06\x02\x01\x01\x01\x01\xFF" }
944
+ its(:a) { should == 1 }
945
+ its(:b) { should == null }
946
+ its(:c) { should == true }
947
+ its(:to_der) { should == der }
948
+ end
949
+ end
950
+ end
951
+
952
+ context "inner CHOICEs" do
953
+ context "rejects tagging other than :EXPLICIT" do
954
+ let(:choice) do
955
+ Class.new do
956
+ include Krypt::ASN1::Template::Choice
957
+ asn1_integer
958
+ end
959
+ end
960
+ let(:template) do
961
+ c = choice
962
+ tc = tagging
963
+ Class.new do
964
+ include SEQ
965
+ asn1_template :a, c, tag: 0, tagging: tc
966
+ end
967
+ end
968
+
969
+ context ":IMPLICIT" do
970
+ let(:tagging) { :IMPLICIT }
971
+ let(:der) { "\x30\x03\x80\x01\x01" }
972
+ it { -> { subject.a.value }.should raise_error asn1error }
973
+ end
974
+
975
+ context ":CONTEXT_SPECIFIC" do
976
+ let(:tagging) { :CONTEXT_SPECIFIC }
977
+ let(:der) { "\x30\x03\x80\x01\x01" }
978
+ it { -> { subject.a.value }.should raise_error asn1error }
979
+ end
980
+
981
+ context ":APPLICATION" do
982
+ let(:tagging) { :APPLICATION }
983
+ let(:der) { "\x30\x03\x40\x01\x01" }
984
+ it { -> { subject.a.value }.should raise_error asn1error }
985
+ end
986
+
987
+ context ":PRIVATE" do
988
+ let(:tagging) { :PRIVATE }
989
+ let(:der) { "\x30\x03\xC0\x01\x01" }
990
+ it { -> { subject.a.value }.should raise_error asn1error }
991
+ end
992
+
993
+ #Can be argued. For now, let's not endorse redundancy
994
+ context ":UNIVERSAL" do
995
+ let(:tagging) { :UNIVERSAL }
996
+ let(:der) { "\x30\x03\x02\x01\x01" }
997
+ it { -> { subject.a.value }.should raise_error asn1error }
998
+ end
999
+
1000
+ context ":EXPLICIT" do
1001
+ let(:tagging) { :EXPLICIT }
1002
+ let(:der) { "\x30\x05\xA0\x03\x02\x01\x01" }
1003
+ it { -> { subject.a.value }.should_not raise_error }
1004
+ end
1005
+ end
1006
+
1007
+ context "at beginning, primitive choices only" do
1008
+ let(:choice) do
1009
+ Class.new do
1010
+ include Krypt::ASN1::Template::Choice
1011
+ asn1_integer
1012
+ asn1_boolean
1013
+ end
1014
+ end
1015
+ let(:template) do
1016
+ c = choice
1017
+ Class.new do
1018
+ include SEQ
1019
+ asn1_template :a, c
1020
+ asn1_octet_string :b
1021
+ end
1022
+ end
1023
+
1024
+ context "match first" do
1025
+ let(:der) { "\x30\x06\x02\x01\x01\x04\x01a" }
1026
+ its(:a) { should be_an_instance_of choice }
1027
+ it { subject.a.type.should == Krypt::ASN1::INTEGER }
1028
+ it { subject.a.tag.should == Krypt::ASN1::INTEGER }
1029
+ it { subject.a.value.should == 1 }
1030
+ its(:b) { should == "a" }
1031
+ its(:to_der) { should == der }
1032
+ end
1033
+
1034
+ context "match second" do
1035
+ let(:der) { "\x30\x06\x01\x01\xFF\x04\x01a" }
1036
+ its(:a) { should be_an_instance_of choice }
1037
+ it { subject.a.type.should == Krypt::ASN1::BOOLEAN }
1038
+ it { subject.a.tag.should == Krypt::ASN1::BOOLEAN }
1039
+ it { subject.a.value.should == true }
1040
+ its(:b) { should == "a" }
1041
+ its(:to_der) { should == der }
1042
+ end
1043
+ end
1044
+
1045
+ context "with inner tags" do
1046
+ let(:choice) do
1047
+ Class.new do
1048
+ include Krypt::ASN1::Template::Choice
1049
+ asn1_integer tag: 0, tagging: :IMPLICIT
1050
+ asn1_boolean tag: 1, tagging: :EXPLICIT
1051
+ end
1052
+ end
1053
+ let(:template) do
1054
+ c = choice
1055
+ Class.new do
1056
+ include SEQ
1057
+ asn1_template :a, c
1058
+ asn1_octet_string :b
1059
+ end
1060
+ end
1061
+
1062
+ context "match first" do
1063
+ let(:der) { "\x30\x06\x80\x01\x01\x04\x01a" }
1064
+ its(:a) { should be_an_instance_of choice }
1065
+ it { subject.a.type.should == Krypt::ASN1::INTEGER }
1066
+ it { subject.a.tag.should == 0 }
1067
+ it { subject.a.value.should == 1 }
1068
+ its(:b) { should == "a" }
1069
+ its(:to_der) { should == der }
1070
+ end
1071
+
1072
+ context "match second" do
1073
+ let(:der) { "\x30\x08\xA1\x03\x01\x01\xFF\x04\x01a" }
1074
+ its(:a) { should be_an_instance_of choice }
1075
+ it { subject.a.type.should == Krypt::ASN1::BOOLEAN }
1076
+ it { subject.a.tag.should == 1 }
1077
+ it { subject.a.value.should == true }
1078
+ its(:b) { should == "a" }
1079
+ its(:to_der) { should == der }
1080
+ end
1081
+ end
1082
+
1083
+ context "primitive choices only, explicitly tagged and default value" do
1084
+ let(:choice) do
1085
+ Class.new do
1086
+ include Krypt::ASN1::Template::Choice
1087
+ asn1_integer
1088
+ asn1_boolean
1089
+ end
1090
+ end
1091
+ let(:default_value) do
1092
+ choice.new do |o|
1093
+ o.type = Krypt::ASN1::INTEGER
1094
+ o.value = 42
1095
+ end
1096
+ end
1097
+ let(:template) do
1098
+ c = choice
1099
+ v = default_value
1100
+ Class.new do
1101
+ include SEQ
1102
+ asn1_template :a, c, tag: 0, tagging: :EXPLICIT, default: v
1103
+ asn1_octet_string :b
1104
+ end
1105
+ end
1106
+
1107
+ context "present, match first" do
1108
+ let(:der) { "\x30\x08\xA0\x03\x02\x01\x01\x04\x01a" }
1109
+ its(:a) { should be_an_instance_of choice }
1110
+ it { subject.a.type.should == Krypt::ASN1::INTEGER }
1111
+ it { subject.a.tag.should == 2 } # it's the tag within the choice, the outer tag doesn't matter
1112
+ it { subject.a.value.should == 1 }
1113
+ its(:b) { should == "a" }
1114
+ its(:to_der) { should == der }
1115
+ end
1116
+
1117
+ context "present, match second" do
1118
+ let(:der) { "\x30\x08\xA0\x03\x01\x01\xFF\x04\x01a" }
1119
+ its(:a) { should be_an_instance_of choice }
1120
+ it { subject.a.type.should == Krypt::ASN1::BOOLEAN }
1121
+ it { subject.a.tag.should == 1 } # it's the tag within the choice, the outer tag doesn't matter
1122
+ it { subject.a.value.should == true }
1123
+ its(:b) { should == "a" }
1124
+ its(:to_der) { should == der }
1125
+ end
1126
+
1127
+ context "absent" do
1128
+ let(:der) { "\x30\x03\x04\x01a" }
1129
+ its(:a) { should == default_value }
1130
+ its(:b) { should == "a" }
1131
+ its(:to_der) { should == der }
1132
+ end
1133
+ end
1134
+
1135
+ context "with inner tagged templates, while outer CHOICE is explicitly tagged" do
1136
+ let(:template2) do
1137
+ Class.new do
1138
+ include Krypt::ASN1::Template::Sequence
1139
+ asn1_integer :a
1140
+ end
1141
+ end
1142
+ let(:template3) do
1143
+ Class.new do
1144
+ include Krypt::ASN1::Template::Sequence
1145
+ asn1_boolean :a
1146
+ end
1147
+ end
1148
+ let(:choice) do
1149
+ t2 = template2
1150
+ t3 = template3
1151
+ Class.new do
1152
+ include Krypt::ASN1::Template::Choice
1153
+ asn1_template t2, tag: 0, tagging: :IMPLICIT
1154
+ asn1_template t3, tag: 1, tagging: :EXPLICIT
1155
+ end
1156
+ end
1157
+ let(:template) do
1158
+ c = choice
1159
+ Class.new do
1160
+ include SEQ
1161
+ asn1_integer :a
1162
+ asn1_template :b, c, tag: 2, tagging: :EXPLICIT
1163
+ end
1164
+ end
1165
+
1166
+ context "match first" do
1167
+ let(:der) { "\x30\x0A\x02\x01\x01\xA2\x05\xA0\x03\x02\x01\x01" }
1168
+ its(:a) { should == 1 }
1169
+ its(:b) { should be_an_instance_of choice }
1170
+ it { subject.b.type.should == template2 }
1171
+ it { subject.b.tag.should == 0 } # it's the tag within the choice, the outer tag doesn't matter
1172
+ it { subject.b.value.should be_an_instance_of template2 }
1173
+ it { subject.b.value.a.should == 1 }
1174
+ its(:to_der) { should == der }
1175
+ end
1176
+
1177
+ context "match second" do
1178
+ let(:der) { "\x30\x0C\x02\x01\x01\xA2\x07\xA1\x05\x30\x03\x01\x01\xFF" }
1179
+ its(:a) { should == 1 }
1180
+ its(:b) { should be_an_instance_of choice }
1181
+ it { subject.b.type.should == template3 }
1182
+ it { subject.b.tag.should == 1 } # it's the tag within the choice, the outer tag doesn't matter
1183
+ it { subject.b.value.should be_an_instance_of template3 }
1184
+ it { subject.b.value.a.should == true }
1185
+ its(:to_der) { should == der }
1186
+ end
1187
+ end
1188
+
1189
+ context "integer and SEQUENCE OF template" do
1190
+ let(:template2) do
1191
+ Class.new do
1192
+ include Krypt::ASN1::Template::Sequence
1193
+ asn1_integer :a
1194
+ end
1195
+ end
1196
+ let(:seqof) do
1197
+ t2 = template2
1198
+ Class.new do
1199
+ include Krypt::ASN1::Template::SequenceOf
1200
+ asn1_type t2
1201
+ end
1202
+ end
1203
+ let(:choice) do
1204
+ sof = seqof
1205
+ Class.new do
1206
+ include Krypt::ASN1::Template::Choice
1207
+ asn1_integer
1208
+ asn1_template sof
1209
+ end
1210
+ end
1211
+ let(:template) do
1212
+ c = choice
1213
+ Class.new do
1214
+ include SEQ
1215
+ asn1_template :a, c
1216
+ end
1217
+ end
1218
+
1219
+ context "match integer" do
1220
+ let(:der) { "\x30\x03\x02\x01\x01" }
1221
+ its(:a) { should be_an_instance_of choice }
1222
+ it { subject.a.tag.should == Krypt::ASN1::INTEGER }
1223
+ it { subject.a.type.should == Krypt::ASN1::INTEGER }
1224
+ it { subject.a.value.should == 1 }
1225
+ end
1226
+
1227
+ context "match SEQUENCE OF template" do
1228
+ let(:der) { "\x30\x0C\x30\x0A\x30\x03\x02\x01\x01\x30\x03\x02\x01\x01" }
1229
+ its(:a) { should be_an_instance_of choice }
1230
+ it { subject.a.tag.should == Krypt::ASN1::SEQUENCE }
1231
+ it { subject.a.type.should == seqof }
1232
+ it { subject.a.value.should be_an_instance_of seqof }
1233
+ it { subject.a.value.value.should be_an_instance_of Array }
1234
+ it { subject.a.value.value.size.should == 2 }
1235
+ it { subject.a.value.value.all? { |v| v.instance_of?(template2) && v.a == 1 }.should == true }
1236
+ end
1237
+ end
1238
+ end
1239
+ end
1240
+ end
1241
+