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