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,102 @@
1
+ require 'rspec'
2
+ require 'krypt'
3
+
4
+ describe Krypt::Hex do
5
+
6
+ let(:mod) { Krypt::Hex }
7
+
8
+ describe "encode" do
9
+ context "single parameter data" do
10
+ context "RFC 4648 test vectors" do
11
+ specify "empty string" do
12
+ mod.encode("").should == ""
13
+ end
14
+
15
+ specify "f" do
16
+ mod.encode("f").should == "66"
17
+ end
18
+
19
+ specify "fo" do
20
+ mod.encode("fo").should == "666f"
21
+ end
22
+
23
+ specify "foo" do
24
+ mod.encode("foo").should == "666f6f"
25
+ end
26
+
27
+ specify "foob" do
28
+ mod.encode("foob").should == "666f6f62"
29
+ end
30
+
31
+ specify "fooba" do
32
+ mod.encode("fooba").should == "666f6f6261"
33
+ end
34
+
35
+ specify "foobar" do
36
+ mod.encode("foobar").should == "666f6f626172"
37
+ end
38
+ end
39
+ end
40
+
41
+ it "should return a string with US-ASCII encoding" do
42
+ mod.encode("test").encoding.should == Encoding::US_ASCII
43
+ end
44
+
45
+ it "should return a string with US-ASCII encoding even if
46
+ the underlying encoding is not" do
47
+ auml = [%w{ C3 A4 }.join('')].pack('H*')
48
+ auml.force_encoding(Encoding::UTF_8)
49
+ mod.encode(auml).encoding.should == Encoding::US_ASCII
50
+ end
51
+ end
52
+
53
+ describe "decode" do
54
+ context "RFC 4648 test vectors" do
55
+ specify "empty string" do
56
+ mod.decode("").should == ""
57
+ end
58
+
59
+ specify "f" do
60
+ mod.decode("66").should == "f"
61
+ end
62
+
63
+ specify "fo" do
64
+ mod.decode("666f").should == "fo"
65
+ end
66
+
67
+ specify "foo" do
68
+ mod.decode("666f6f").should == "foo"
69
+ end
70
+
71
+ specify "foob" do
72
+ mod.decode("666f6f62").should == "foob"
73
+ end
74
+
75
+ specify "fooba" do
76
+ mod.decode("666f6f6261").should == "fooba"
77
+ end
78
+
79
+ specify "foobar" do
80
+ mod.decode("666f6f626172").should == "foobar"
81
+ end
82
+ end
83
+
84
+ it "should return a string with binary encoding" do
85
+ mod.decode("666f6f626172").encoding.should == Encoding::BINARY
86
+ end
87
+
88
+ it "should return a string with US-ASCII encoding even if
89
+ the underlying encoding is not" do
90
+ data = "666f"
91
+ data.force_encoding(Encoding::UTF_8)
92
+ mod.decode(data).encoding.should == Encoding::BINARY
93
+ end
94
+
95
+ it "ignores case for a-f" do
96
+ str = "666f6f626172"
97
+ dec = "foobar"
98
+ mod.decode(str).should == dec
99
+ mod.decode(str.upcase).should == dec
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,235 @@
1
+ # encoding: US-ASCII
2
+
3
+ require 'rspec'
4
+ require 'krypt'
5
+ require 'stringio'
6
+ require 'base64'
7
+ require_relative '../resources'
8
+
9
+ describe Krypt::PEM do
10
+ let(:mod) { Krypt::PEM }
11
+ let(:pemerror) { Krypt::PEM::PEMError }
12
+ let(:intb64) { ::Base64.encode64("\x02\x01\x01") }
13
+
14
+ def create_pem_b64(b64, name)
15
+ "-----BEGIN #{name}-----\n#{b64}-----END #{name}-----\n"
16
+ end
17
+
18
+ describe "PEM.decode" do
19
+ subject { mod.decode(value) }
20
+
21
+ context "returns an Array" do
22
+ let(:value) { Resources.certificate_pem }
23
+ it { should be_an_instance_of(Array) }
24
+ end
25
+
26
+ context"decodes Strings" do
27
+ context "decodes a single PEM value" do
28
+ let(:value) { Resources.certificate_pem }
29
+ its(:size) { should == 1 }
30
+ it { subject[0].should == Resources.certificate }
31
+ end
32
+
33
+ context "decodes multiple PEM values" do
34
+ let(:value) { Resources.certificate_pem * 3 }
35
+ its(:size) { should == 3 }
36
+ it { subject.all? { |der| der == Resources.certificate }.should be_true }
37
+ end
38
+
39
+ context "decodes multiple mixed PEM values" do
40
+ let(:value) { Resources.certificate_pem + create_pem_b64(intb64, "INTEGER") }
41
+ its(:size) { should == 2 }
42
+ it do
43
+ subject[0].should == Resources.certificate
44
+ subject[1].should == "\x02\x01\x01"
45
+ end
46
+ end
47
+
48
+ context "decodes long PEM values" do
49
+ let(:der) { "\x04\x82\x4E\x20" + "\x01" * 20_000 }
50
+ let(:value) { create_pem_b64("#{::Base64.encode64(der)}", "OCTET STRING") }
51
+ its(:size) { should == 1 }
52
+ it { subject[0].should == der }
53
+ end
54
+ end
55
+
56
+ context "decodes StringIO" do
57
+ context "decodes a single PEM value" do
58
+ let(:value) { StringIO.new(Resources.certificate_pem) }
59
+ its(:size) { should == 1 }
60
+ it { subject[0].should == Resources.certificate }
61
+ end
62
+
63
+ context "decodes multiple PEM values" do
64
+ let(:value) { StringIO.new(Resources.certificate_pem * 3) }
65
+ its(:size) { should == 3 }
66
+ it { subject.all? { |der| der == Resources.certificate }.should be_true }
67
+ end
68
+ end
69
+
70
+ context "decodes Files" do
71
+ subject do
72
+ begin
73
+ mod.decode(io)
74
+ ensure
75
+ io.close
76
+ end
77
+ end
78
+
79
+ context "decodes a File containing a single PEM value" do
80
+ let(:io) { Resources.certificate_pem_io }
81
+ its(:size) { should == 1 }
82
+ it { subject[0].should == Resources.certificate }
83
+ end
84
+
85
+ context "decodes a File containing multiple PEM values" do
86
+ let(:io) { Resources.multi_certificate_pem_io }
87
+ its(:size) { should == 3 }
88
+ it { subject.all? { |der| der == Resources.certificate }.should be_true }
89
+ end
90
+ end
91
+
92
+ context "decodes arbitrary objects that respond to to_pem" do
93
+ let(:value) do
94
+ o = Object.new
95
+ def o.to_pem
96
+ Resources.certificate_pem
97
+ end
98
+ o
99
+ end
100
+ its(:size) { should == 1 }
101
+ it { subject[0].should == Resources.certificate }
102
+ end
103
+
104
+ context "does not require terminating line break" do
105
+ let(:value) { "-----BEGIN ABC-----\n#{intb64}-----END ABC-----" }
106
+ its(:size) { should == 1 }
107
+ it { subject[0].should == "\x02\x01\x01" }
108
+ end
109
+
110
+ context "ignores empty lines" do
111
+ context "LF" do
112
+ let(:value) { "\n" + create_pem_b64("\n#{intb64}\n", "INTEGER") + "\n" }
113
+ its(:size) { should == 1 }
114
+ it { subject[0].should == "\x02\x01\x01" }
115
+ end
116
+
117
+ context "CRLF" do
118
+ let(:value) { "\r\n" + create_pem_b64("\r\n#{intb64}\r\n", "INTEGER") + "\r\n" }
119
+ its(:size) { should == 1 }
120
+ it { subject[0].should == "\x02\x01\x01" }
121
+ end
122
+ end
123
+
124
+ context "normalizes CRLF and LF" do
125
+ context "LF only" do
126
+ let(:value) { "-----BEGIN A-----\n#{intb64}-----END A-----\n" }
127
+ it { subject[0].should == "\x02\x01\x01" }
128
+ end
129
+
130
+ context "CRLF only" do
131
+ let(:value) { "-----BEGIN A-----\r\n#{::Base64.encode64("\x02\x01\x01")}\r\n-----END A-----\r\n" }
132
+ it { subject[0].should == "\x02\x01\x01" }
133
+ end
134
+
135
+ context "mixed: CRLF header, LF footer" do
136
+ let(:value) { "-----BEGIN A-----\r\n#{intb64}-----END A-----\n" }
137
+ it { subject[0].should == "\x02\x01\x01" }
138
+ end
139
+
140
+ context "mixed: LF header, CRLF footer" do
141
+ let(:value) { "-----BEGIN A-----\n#{intb64}-----END A-----\r\n" }
142
+ it { subject[0].should == "\x02\x01\x01" }
143
+ end
144
+ end
145
+
146
+ context "allows arbitrary content between PEM blocks" do
147
+ context "String with LF as last character" do
148
+ let(:value) { "Next up a certificate.\n#{Resources.certificate_pem}After the certificate\n" }
149
+ its(:size) { should == 1 }
150
+ it { subject[0].should == Resources.certificate }
151
+ end
152
+
153
+ context "String not ending in LF as last character" do
154
+ let(:value) { "Next up a certificate.\n#{Resources.certificate_pem}After the certificate" }
155
+ its(:size) { should == 1 }
156
+ it { subject[0].should == Resources.certificate }
157
+ end
158
+
159
+ context "File containing a 'CA certificate bundle'" do
160
+ let(:value) { Resources.ca_certificate_pem_io }
161
+ its(:size) { should == 136 }
162
+ end
163
+ end
164
+
165
+ context "rejects values with non-matching names" do
166
+ let(:value) { "-----BEGIN A-----\n#{intb64}-----END B-----" }
167
+ it { -> { subject }.should raise_error pemerror }
168
+ end
169
+
170
+ context "allows no redundant whitespace" do
171
+ context"leading in header" do
172
+ let(:value) { " -----BEGIN A-----\n#{intb64}-----END A-----" }
173
+ it { subject.should be_empty }
174
+ end
175
+
176
+ context"leading in footer" do
177
+ let(:value) { "-----BEGIN A-----\n#{intb64} -----END A-----" }
178
+ it { -> { subject }.should raise_error pemerror }
179
+ end
180
+
181
+ context"trailing in header" do
182
+ let(:value) { "-----BEGIN A----- \n#{intb64}-----END A-----" }
183
+ it { subject.should be_empty }
184
+ end
185
+
186
+ context"trailing in footer" do
187
+ let(:value) { "-----BEGIN A-----\n#{intb64}-----END A----- " }
188
+ it { -> { subject }.should raise_error pemerror }
189
+ end
190
+ end
191
+
192
+ context "does not expect line breaks for Base64 content" do
193
+ context "in small data" do
194
+ let(:der) { "\x04\x82\x03\xE8" + "\x01" * 80 }
195
+ let(:value) { "-----BEGIN ABC-----\n#{::Base64.strict_encode64(der)}\n-----END ABC-----" }
196
+ it { subject[0].should == der }
197
+ end
198
+
199
+ context "in large data" do
200
+ let(:der) { "\x04\x82\x4E\x20" + "\x01" * 20_000 }
201
+ let(:value) { "-----BEGIN ABC-----\n#{::Base64.strict_encode64(der)}\n-----END ABC-----" }
202
+ it { subject[0].should == der }
203
+ end
204
+ end
205
+
206
+ context "takes a block" do
207
+ context "whose first argument is the current value" do
208
+ let(:value) { Resources.certificate_pem * 3 }
209
+ it do
210
+ ary = []
211
+ cmp = mod.decode(value) { |asn1| ary << asn1 }
212
+ ary.should == cmp
213
+ end
214
+ end
215
+
216
+ context "whose second argument is the name of the current value" do
217
+ let(:value) { Resources.certificate_pem * 3 }
218
+ it do
219
+ ary = []
220
+ mod.decode(value) { |asn1, name| ary << name }
221
+ ary.should == ["CERTIFICATE", "CERTIFICATE", "CERTIFICATE"]
222
+ end
223
+ end
224
+
225
+ context "whose third argument is the current index, starting at 0" do
226
+ let(:value) { Resources.certificate_pem * 3 }
227
+ it do
228
+ ary = []
229
+ mod.decode(value) { |asn1, name, i| ary << i }
230
+ ary.should == [0,1,2]
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
@@ -0,0 +1 @@
1
+ require_relative '../resources'
@@ -0,0 +1,289 @@
1
+ # encoding: US-ASCII
2
+
3
+ require 'rspec'
4
+ require 'krypt'
5
+ require_relative '../resources'
6
+
7
+ describe "Krypt::ASN1::Template::Choice" do
8
+ CHOICE = Krypt::ASN1::Template::Choice
9
+ let(:asn1error) { Krypt::ASN1::ASN1Error }
10
+
11
+ context "extracted from parse_der" do
12
+ subject { template.parse_der(der) }
13
+
14
+ context "single field" do
15
+ let(:template) do
16
+ Class.new do
17
+ include CHOICE
18
+ asn1_integer
19
+ end
20
+ end
21
+
22
+ context "accepts correct encoding" do
23
+ let(:der) { "\x02\x01\x01" }
24
+ its(:value) { should == 1 }
25
+ it { subject.type.should == Krypt::ASN1::INTEGER }
26
+ it { subject.tag.should == Krypt::ASN1::INTEGER }
27
+ it { subject.should be_an_instance_of template }
28
+ its(:to_der) { should == der }
29
+ end
30
+
31
+ context "rejects wrong encoding" do
32
+ let(:der) { "\x04\x01\x01" }
33
+ it { -> { subject.value }.should raise_error asn1error }
34
+ end
35
+
36
+ context "rejects encoding that is not complete" do
37
+ let(:der) { "\x02\x01" }
38
+ it { -> { subject.value }.should raise_error asn1error }
39
+ end
40
+ end
41
+
42
+ context "two fields" do
43
+ let(:template) do
44
+ Class.new do
45
+ include CHOICE
46
+ asn1_integer
47
+ asn1_boolean
48
+ end
49
+ end
50
+
51
+ context "accepts correct encoding integer" do
52
+ let(:der) { "\x02\x01\x01" }
53
+ its(:value) { should == 1 }
54
+ its(:type) { should == Krypt::ASN1::INTEGER }
55
+ its(:tag) { should == Krypt::ASN1::INTEGER }
56
+ it { subject.should be_an_instance_of template }
57
+ its(:to_der) { should == der }
58
+ end
59
+
60
+ context "accepts correct encoding boolean" do
61
+ let(:der) { "\x01\x01\xFF" }
62
+ its(:value) { should == true }
63
+ its(:type) { should == Krypt::ASN1::BOOLEAN }
64
+ its(:tag) { should == Krypt::ASN1::BOOLEAN }
65
+ it { subject.should be_an_instance_of template }
66
+ its(:to_der) { should == der }
67
+ end
68
+
69
+ context "rejects wrong encoding" do
70
+ let(:der) { "\x04\x01\xFF" }
71
+ it { -> { subject.value }.should raise_error asn1error }
72
+ end
73
+ end
74
+
75
+ context "preserves non-DER encodings" do
76
+ let(:template) do
77
+ Class.new do
78
+ include CHOICE
79
+ asn1_boolean
80
+ end
81
+ end
82
+ let(:der) { "\x01\x83\x00\x00\x01\x22" }
83
+ its(:to_der) { should == der }
84
+ end
85
+
86
+ context "does not choke on invalid encodings" do
87
+ let(:template) do
88
+ Class.new do
89
+ include CHOICE
90
+ asn1_integer
91
+ asn1_octet_string
92
+ end
93
+ end
94
+
95
+ context "when parsing them" do
96
+ let(:der) { "\x02\x00" }
97
+ it { -> { subject }.should_not raise_error }
98
+ end
99
+
100
+ context "and encodes them again exactly as received" do
101
+ let(:der) { "\x02\x00" }
102
+ its(:to_der) { should == der }
103
+ end
104
+
105
+ context "but raises an error when accessing the fields" do
106
+ let(:der) { "\x02\x00" }
107
+ it { -> { subject.value }.should raise_error asn1error }
108
+ end
109
+
110
+ context "but raises an error if the tag does not match" do
111
+ let(:der) { "\x01\x01\xFF" }
112
+ it { -> { subject.value }.should raise_error asn1error }
113
+ end
114
+ end
115
+
116
+ context "with inner templates" do
117
+ let(:template2) do
118
+ Class.new do
119
+ include Krypt::ASN1::Template::Sequence
120
+ asn1_integer :a
121
+ end
122
+ end
123
+
124
+ context "no further options" do
125
+ let(:template) do
126
+ t = template2
127
+ Class.new do
128
+ include CHOICE
129
+ asn1_template t
130
+ end
131
+ end
132
+ let(:der) { "\x30\x03\x02\x01\x01" }
133
+ its(:value) { should be_an_instance_of template2 }
134
+ its(:tag) { should == Krypt::ASN1::SEQUENCE }
135
+ its(:type) { should == template2 }
136
+ it { subject.value.a.should == 1 }
137
+ end
138
+
139
+ context "with implicit tags" do
140
+ let(:template3) do
141
+ Class.new do
142
+ include Krypt::ASN1::Template::Sequence
143
+ asn1_boolean :a
144
+ end
145
+ end
146
+ let(:template) do
147
+ t2 = template2
148
+ t3 = template3
149
+ Class.new do
150
+ include CHOICE
151
+ asn1_template t2, tag: 0, tagging: :IMPLICIT
152
+ asn1_template t3, tag: 1, tagging: :IMPLICIT
153
+ end
154
+ end
155
+
156
+ context "matches first" do
157
+ let(:der) { "\xA0\x03\x02\x01\x01" }
158
+ its(:value) { should be_an_instance_of template2 }
159
+ its(:tag) { should == 0 }
160
+ its(:type) { should == template2 }
161
+ it { subject.value.a.should == 1 }
162
+ end
163
+
164
+ context "matches second" do
165
+ let(:der) { "\xA1\x03\x01\x01\xFF" }
166
+ its(:value) { should be_an_instance_of template3 }
167
+ its(:tag) { should == 1 }
168
+ its(:type) { should == template3 }
169
+ it { subject.value.a.should == true }
170
+ end
171
+ end
172
+
173
+ context "with explicit tags" do
174
+ let(:template3) do
175
+ Class.new do
176
+ include Krypt::ASN1::Template::Sequence
177
+ asn1_boolean :a
178
+ end
179
+ end
180
+ let(:template) do
181
+ t2 = template2
182
+ t3 = template3
183
+ Class.new do
184
+ include CHOICE
185
+ asn1_template t2, tag: 0, tagging: :EXPLICIT
186
+ asn1_template t3, tag: 1, tagging: :EXPLICIT
187
+ end
188
+ end
189
+
190
+ context "matches first" do
191
+ let(:der) { "\xA0\x05\x30\x03\x02\x01\x01" }
192
+ its(:value) { should be_an_instance_of template2 }
193
+ its(:tag) { should == 0 }
194
+ its(:type) { should == template2 }
195
+ it { subject.value.a.should == 1 }
196
+ end
197
+
198
+ context "matches second" do
199
+ let(:der) { "\xA1\x05\x30\x03\x01\x01\xFF" }
200
+ its(:value) { should be_an_instance_of template3 }
201
+ its(:tag) { should == 1 }
202
+ its(:type) { should == template3 }
203
+ it { subject.value.a.should == true }
204
+ end
205
+ end
206
+
207
+ context "with SEQUENCE OF" do
208
+ let(:template) do
209
+ t2 = template2
210
+ Class.new do
211
+ include CHOICE
212
+ asn1_sequence_of t2
213
+ end
214
+ end
215
+ let(:der) { "\x30\x0A\x30\x03\x02\x01\x01\x30\x03\x02\x01\x01" }
216
+ its(:value) { should be_an_instance_of Array }
217
+ its(:type) { should == template2 }
218
+ its(:tag) { should == Krypt::ASN1::SEQUENCE }
219
+ it { subject.value.size.should == 2 }
220
+ it { subject.value.all? { |v| v.instance_of?(template2) && v.a == 1 }.should == true }
221
+ its(:to_der) { should == der }
222
+ end
223
+
224
+ context "with SET OF" do
225
+ let(:template) do
226
+ t2 = template2
227
+ Class.new do
228
+ include CHOICE
229
+ asn1_set_of t2
230
+ end
231
+ end
232
+ let(:der) { "\x31\x0A\x30\x03\x02\x01\x01\x30\x03\x02\x01\x01" }
233
+ its(:value) { should be_an_instance_of Array }
234
+ its(:type) { should == template2 }
235
+ its(:tag) { should == Krypt::ASN1::SET }
236
+ it { subject.value.size.should == 2 }
237
+ it { subject.value.all? { |v| v.instance_of?(template2) && v.a == 1 }.should == true }
238
+ its(:to_der) { should == der }
239
+ end
240
+
241
+ context "with ANY" do
242
+ context "alone" do
243
+ let(:template) do
244
+ t2 = template2
245
+ Class.new do
246
+ include CHOICE
247
+ asn1_any
248
+ end
249
+ end
250
+ let(:der) { "\x02\x01\x01" }
251
+ its(:value) { should be_an_instance_of Krypt::ASN1::Integer }
252
+ its(:type) { should == Krypt::ASN1::ASN1Data }
253
+ its(:tag) { should == Krypt::ASN1::INTEGER }
254
+ it { subject.value.value.should == 1 }
255
+ its(:to_der) { should == der }
256
+ end
257
+
258
+ context "the first ANY field matches if no other will" do
259
+ let(:template) do
260
+ t2 = template2
261
+ Class.new do
262
+ include CHOICE
263
+ asn1_integer
264
+ asn1_any
265
+ end
266
+ end
267
+
268
+ context "other matches" do
269
+ let(:der) { "\x02\x01\x01" }
270
+ its(:value) { should == 1 }
271
+ its(:type) { should == Krypt::ASN1::INTEGER }
272
+ its(:tag) { should == Krypt::ASN1::INTEGER }
273
+ its(:to_der) { should == der }
274
+ end
275
+
276
+ context "ANY matches" do
277
+ let(:der) { "\x01\x01\xFF" }
278
+ its(:value) { should be_an_instance_of Krypt::ASN1::Boolean }
279
+ its(:type) { should == Krypt::ASN1::ASN1Data }
280
+ its(:tag) { should == Krypt::ASN1::BOOLEAN }
281
+ it { subject.value.value.should == true }
282
+ its(:to_der) { should == der }
283
+ end
284
+ end
285
+ end
286
+ end
287
+ end
288
+ end
289
+