krypt 0.0.1

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.
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
+