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,133 @@
1
+ # encoding: US-ASCII
2
+
3
+ require 'rspec'
4
+ require 'krypt'
5
+ require 'openssl'
6
+ require_relative './resources'
7
+
8
+ describe Krypt::ASN1::EndOfContents do
9
+ include Krypt::ASN1::Resources
10
+
11
+ let(:mod) { Krypt::ASN1 }
12
+ let(:klass) { mod::EndOfContents }
13
+ let(:decoder) { mod }
14
+ let(:asn1error) { mod::ASN1Error }
15
+
16
+ # For test against OpenSSL
17
+ #
18
+ #let(:mod) { OpenSSL::ASN1 }
19
+ #let(:klass) { mod::EndOfContent }
20
+
21
+ describe '#new' do
22
+ context 'constructs without value' do
23
+ subject { klass.new }
24
+
25
+ its(:tag) { should == Krypt::ASN1::END_OF_CONTENTS }
26
+ its(:tag_class) { should == :UNIVERSAL }
27
+ its(:value) { should == nil } # TODO: ossl returns ''
28
+ its(:infinite_length) { should == false }
29
+ end
30
+
31
+ context 'constructs with nil' do
32
+ subject { klass.new(nil) }
33
+
34
+ its(:tag) { should == Krypt::ASN1::END_OF_CONTENTS }
35
+ its(:tag_class) { should == :UNIVERSAL }
36
+ its(:value) { should == nil }
37
+ its(:infinite_length) { should == false }
38
+ end
39
+
40
+ it "only accepts nil as the value argument" do
41
+ -> { klass.new(1) }.should raise_error(ArgumentError)
42
+ end
43
+
44
+ context "does not accept tag and tag_class arguments" do
45
+ it { -> { klass.new(nil, 0) }.should raise_error(ArgumentError) }
46
+ it { -> { klass.new(nil, 0, :UNIVERSAL) }.should raise_error(ArgumentError) }
47
+ end
48
+ end
49
+
50
+ describe 'accessors' do
51
+ describe '#value' do
52
+ subject { o = klass.new(nil); o.value = value; o }
53
+
54
+ context 'accepts nil' do
55
+ let(:value) { nil }
56
+ its(:value) { should == nil }
57
+ end
58
+
59
+ it "accepts objects other than nil as the value argument, but raises on encoding" do
60
+ asn1 = klass.new
61
+ asn1.value = 1
62
+ -> { asn1.to_der }.should raise_error asn1error
63
+ end
64
+ end
65
+ end
66
+
67
+ describe '#to_der' do
68
+ context 'encodes without value' do
69
+ subject { klass.new.to_der }
70
+ it { should == "\x00\x00" }
71
+ end
72
+
73
+ context 'encodes a given value' do
74
+ subject { klass.new(nil).to_der }
75
+ it { should == "\x00\x00" }
76
+ end
77
+
78
+ context 'encodes values set via accessors' do
79
+ subject {
80
+ o = klass.new(nil)
81
+ o.value = nil
82
+ o.to_der
83
+ }
84
+
85
+ it { should == "\x00\x00" }
86
+ end
87
+ end
88
+
89
+ describe '#encode_to' do
90
+ context 'encodes to an IO' do
91
+ subject { klass.new(value).encode_to(io); io }
92
+
93
+ context "StringIO" do
94
+ let(:value) { nil }
95
+ let(:io) { string_io_object }
96
+ its(:written_bytes) { should == "\x00\x00" }
97
+ end
98
+
99
+ context "Object responds to :write" do
100
+ let(:value) { nil }
101
+ let(:io) { writable_object }
102
+ its(:written_bytes) { should == "\x00\x00" }
103
+ end
104
+
105
+ context "raise IO error transparently" do
106
+ let(:value) { nil }
107
+ let(:io) { io_error_object }
108
+ it { -> { subject }.should raise_error asn1error }
109
+ end
110
+ end
111
+
112
+ it 'returns self' do
113
+ obj = klass.new(nil)
114
+ obj.encode_to(string_io_object).should == obj
115
+ end
116
+ end
117
+
118
+ describe 'extracted from ASN1.decode' do
119
+ subject { decoder.decode(der) }
120
+
121
+ context 'extracted value' do
122
+ let(:der) { "\x00\x00" }
123
+ its(:class) { should == klass }
124
+ its(:tag) { should == Krypt::ASN1::END_OF_CONTENTS }
125
+ its(:value) { should == nil }
126
+ end
127
+
128
+ context 'rejects values with a lenght > 0' do
129
+ let(:der) { "\x00\x01\x00" }
130
+ it { -> { subject.value }.should raise_error asn1error }
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,458 @@
1
+ # encoding: US-ASCII
2
+
3
+ require 'rspec'
4
+ require 'krypt'
5
+ require 'openssl'
6
+ require_relative './resources'
7
+
8
+ describe Krypt::ASN1::Enumerated do
9
+ include Krypt::ASN1::Resources
10
+
11
+ let(:mod) { Krypt::ASN1 }
12
+ let(:klass) { mod::Enumerated }
13
+ let(:decoder) { mod }
14
+ let(:asn1error) { mod::ASN1Error }
15
+
16
+ # For test against OpenSSL
17
+ #
18
+ #let(:mod) { OpenSSL::ASN1 }
19
+ #
20
+ # OpenSSL stub for signature mismatch
21
+ class OpenSSL::ASN1::Enumerated
22
+ class << self
23
+ alias old_new new
24
+ def new(*args)
25
+ if args.size > 1
26
+ args = [args[0], args[1], :IMPLICIT, args[2]]
27
+ end
28
+ old_new(*args)
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#new' do
34
+ context 'gets value for construct' do
35
+ subject { klass.new(value) }
36
+
37
+ context 'Integer' do
38
+ let(:value) { 72 }
39
+ its(:tag) { should == Krypt::ASN1::ENUMERATED }
40
+ its(:tag_class) { should == :UNIVERSAL }
41
+ its(:value) { should == 72 }
42
+ its(:infinite_length) { should == false }
43
+ end
44
+
45
+ context '0' do
46
+ let(:value) { 0 }
47
+ its(:value) { should == 0 }
48
+ end
49
+
50
+ context 'negative Integer' do
51
+ let(:value) { -72 }
52
+ its(:value) { should == -72 }
53
+ end
54
+ end
55
+
56
+ context 'gets explicit tag number as the 2nd argument' do
57
+ subject { klass.new(72, tag, :PRIVATE) }
58
+
59
+ context 'accepts default tag' do
60
+ let(:tag) { Krypt::ASN1::ENUMERATED }
61
+ its(:tag) { should == tag }
62
+ end
63
+
64
+ context 'accepts custom tag' do
65
+ let(:tag) { 14 }
66
+ its(:tag) { should == tag }
67
+ end
68
+ end
69
+
70
+ context 'gets tag class symbol as the 3rd argument' do
71
+ subject { klass.new(72, Krypt::ASN1::ENUMERATED, tag_class) }
72
+
73
+ context 'accepts :UNIVERSAL' do
74
+ let(:tag_class) { :UNIVERSAL }
75
+ its(:tag_class) { should == tag_class }
76
+ end
77
+
78
+ context 'accepts :APPLICATION' do
79
+ let(:tag_class) { :APPLICATION }
80
+ its(:tag_class) { should == tag_class }
81
+ end
82
+
83
+ context 'accepts :CONTEXT_SPECIFIC' do
84
+ let(:tag_class) { :CONTEXT_SPECIFIC }
85
+ its(:tag_class) { should == tag_class }
86
+ end
87
+
88
+ context 'accepts :PRIVATE' do
89
+ let(:tag_class) { :PRIVATE }
90
+ its(:tag_class) { should == tag_class }
91
+ end
92
+
93
+ context 'accepts :IMPLICIT' do
94
+ let(:tag_class) { :IMPLICIT }
95
+ its(:tag_class) { should == tag_class }
96
+ end
97
+
98
+ context 'accepts :EXPLICIT' do
99
+ let(:tag_class) { :EXPLICIT }
100
+ its(:tag_class) { should == tag_class }
101
+ end
102
+ end
103
+
104
+ context 'when the 2nd argument is given but 3rd argument is omitted' do
105
+ subject { klass.new(72, Krypt::ASN1::ENUMERATED) }
106
+ its(:tag_class) { should == :CONTEXT_SPECIFIC }
107
+ end
108
+ end
109
+
110
+ describe 'accessors' do
111
+ describe '#value' do
112
+ subject { o = klass.new(nil); o.value = value; o }
113
+
114
+ context 'Integer' do
115
+ let(:value) { 72 }
116
+ its(:tag) { should == Krypt::ASN1::ENUMERATED }
117
+ its(:tag_class) { should == :UNIVERSAL }
118
+ its(:value) { should == 72 }
119
+ its(:infinite_length) { should == false }
120
+ end
121
+
122
+ context '0' do
123
+ let(:value) { 0 }
124
+ its(:value) { should == 0 }
125
+ end
126
+
127
+ context 'negative Integer' do
128
+ let(:value) { -72 }
129
+ its(:value) { should == -72 }
130
+ end
131
+ end
132
+
133
+ describe '#tag' do
134
+ subject { o = klass.new(nil); o.tag = tag; o }
135
+
136
+ context 'accepts default tag' do
137
+ let(:tag) { Krypt::ASN1::ENUMERATED }
138
+ its(:tag) { should == tag }
139
+ end
140
+
141
+ context 'accepts custom tag' do
142
+ let(:tag) { 14 }
143
+ its(:tag) { should == tag }
144
+ end
145
+ end
146
+
147
+ describe '#tag_class' do
148
+ subject { o = klass.new(nil); o.tag_class = tag_class; o }
149
+
150
+ context 'accepts :UNIVERSAL' do
151
+ let(:tag_class) { :UNIVERSAL }
152
+ its(:tag_class) { should == tag_class }
153
+ end
154
+
155
+ context 'accepts :APPLICATION' do
156
+ let(:tag_class) { :APPLICATION }
157
+ its(:tag_class) { should == tag_class }
158
+ end
159
+
160
+ context 'accepts :CONTEXT_SPECIFIC' do
161
+ let(:tag_class) { :CONTEXT_SPECIFIC }
162
+ its(:tag_class) { should == tag_class }
163
+ end
164
+
165
+ context 'accepts :PRIVATE' do
166
+ let(:tag_class) { :PRIVATE }
167
+ its(:tag_class) { should == tag_class }
168
+ end
169
+
170
+ context 'accepts :IMPLICIT' do
171
+ let(:tag_class) { :IMPLICIT }
172
+ its(:tag_class) { should == tag_class }
173
+ end
174
+
175
+ context 'accepts :EXPLICIT' do
176
+ let(:tag_class) { :EXPLICIT }
177
+ its(:tag_class) { should == tag_class }
178
+ end
179
+ end
180
+ end
181
+
182
+ describe '#to_der' do
183
+ context 'encodes a given value' do
184
+ subject { klass.new(value).to_der }
185
+
186
+ context 0 do
187
+ let(:value) { 0 }
188
+ it { should == "\x0A\x01\x00" }
189
+ end
190
+
191
+ context 72 do
192
+ let(:value) { 72 }
193
+ it { should == "\x0A\x01\x48" }
194
+ end
195
+
196
+ context 127 do
197
+ let(:value) { 127 }
198
+ it { should == "\x0A\x01\x7F" }
199
+ end
200
+
201
+ context -128 do
202
+ let(:value) { -128 }
203
+ it { should == "\x0A\x01\x80" }
204
+ end
205
+
206
+ context 128 do
207
+ let(:value) { 128 }
208
+ it { should == "\x0A\x02\x00\x80" }
209
+ end
210
+
211
+ context -27066 do
212
+ let(:value) { -27066 }
213
+ it { should == "\x0A\x02\x96\x46" }
214
+ end
215
+
216
+ context 'max Fixnum on 32bit box' do
217
+ let(:value) { 2**30-1 }
218
+ it { should == "\x0A\x04\x3F\xFF\xFF\xFF" }
219
+ end
220
+
221
+ context 'max Fixnum on 64bit box' do
222
+ let(:value) { 2**62-1 }
223
+ it { should == "\x0A\x08\x3F\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }
224
+ end
225
+
226
+ context 'nil' do
227
+ let(:value) { nil }
228
+ it { -> { subject }.should raise_error asn1error } # TODO: ossl crashes
229
+ end
230
+
231
+ context 'String' do
232
+ let(:value) { '123' }
233
+ it { -> { subject }.should raise_error asn1error }
234
+ end
235
+ end
236
+
237
+ context 'encodes tag number' do
238
+ subject { klass.new(72, tag, :PRIVATE).to_der }
239
+
240
+ context 'default tag' do
241
+ let(:tag) { Krypt::ASN1::ENUMERATED }
242
+ it { should == "\xCA\x01\x48" }
243
+ end
244
+
245
+ context 'custom tag' do
246
+ let(:tag) { 14 }
247
+ it { should == "\xCE\x01\x48" }
248
+ end
249
+
250
+ context 'nil' do
251
+ let(:tag) { nil }
252
+ it { -> { subject }.should raise_error asn1error }
253
+ end
254
+ end
255
+
256
+ context 'encodes tag class' do
257
+ subject { klass.new(72, Krypt::ASN1::ENUMERATED, tag_class).to_der }
258
+
259
+ context 'UNIVERSAL' do
260
+ let(:tag_class) { :UNIVERSAL }
261
+ it { should == "\x0A\x01\x48" }
262
+ end
263
+
264
+ context 'APPLICATION' do
265
+ let(:tag_class) { :APPLICATION }
266
+ it { should == "\x4A\x01\x48" }
267
+ end
268
+
269
+ context 'CONTEXT_SPECIFIC' do
270
+ let(:tag_class) { :CONTEXT_SPECIFIC }
271
+ it { should == "\x8A\x01\x48" }
272
+ end
273
+
274
+ context 'PRIVATE' do
275
+ let(:tag_class) { :PRIVATE }
276
+ it { should == "\xCA\x01\x48" }
277
+ end
278
+
279
+ context 'IMPLICIT' do
280
+ let(:tag_class) { :IMPLICIT }
281
+ it { should == "\x8A\x01\x48" }
282
+ end
283
+
284
+ context 'EXPLICIT' do
285
+ let(:tag_class) { :EXPLICIT }
286
+ it { should == "\xAA\x03\x0A\x01\x48" }
287
+ end
288
+
289
+ context nil do
290
+ let(:tag_class) { nil }
291
+ it { -> { subject }.should raise_error asn1error } # TODO: ossl does not check nil
292
+ end
293
+
294
+ context :no_such_class do
295
+ let(:tag_class) { :no_such_class }
296
+ it { -> { subject }.should raise_error asn1error }
297
+ end
298
+ end
299
+
300
+ context 'encodes values set via accessors' do
301
+ subject {
302
+ o = klass.new(nil)
303
+ o.value = value if defined? value
304
+ o.tag = tag if defined? tag
305
+ o.tag_class = tag_class if defined? tag_class
306
+ o.to_der
307
+ }
308
+
309
+ context 'value: 72' do
310
+ let(:value) { 72 }
311
+ it { should == "\x0A\x01\x48" }
312
+ end
313
+
314
+ context 'custom tag' do
315
+ let(:value) { 72 }
316
+ let(:tag) { 14 }
317
+ let(:tag_class) { :PRIVATE }
318
+ it { should == "\xCE\x01\x48" }
319
+ end
320
+
321
+ context 'tag_class' do
322
+ let(:value) { 72 }
323
+ let(:tag_class) { :APPLICATION }
324
+ it { should == "\x4A\x01\x48" }
325
+ end
326
+ end
327
+ end
328
+
329
+ describe '#encode_to' do
330
+ context 'encodes to an IO' do
331
+ subject { klass.new(value).encode_to(io); io }
332
+
333
+ context "StringIO" do
334
+ let(:value) { 72 }
335
+ let(:io) { string_io_object }
336
+ its(:written_bytes) { should == "\x0A\x01\x48" }
337
+ end
338
+
339
+ context "Object responds to :write" do
340
+ let(:value) { 72 }
341
+ let(:io) { writable_object }
342
+ its(:written_bytes) { should == "\x0A\x01\x48" }
343
+ end
344
+
345
+ context "raise IO error transparently" do
346
+ let(:value) { 72 }
347
+ let(:io) { io_error_object }
348
+ it { -> { subject }.should raise_error asn1error }
349
+ end
350
+ end
351
+
352
+ it 'returns self' do
353
+ obj = klass.new(72)
354
+ obj.encode_to(string_io_object).should == obj
355
+ end
356
+ end
357
+
358
+ describe 'extracted from ASN1.decode' do
359
+ subject { decoder.decode(der) }
360
+
361
+ context 'extracted value' do
362
+ context 0 do
363
+ let(:der) { "\x0A\x01\x00" }
364
+ its(:class) { should == klass }
365
+ its(:tag) { should == Krypt::ASN1::ENUMERATED }
366
+ its(:value) { should == 0 }
367
+ end
368
+
369
+ context 72 do
370
+ let(:der) { "\x0A\x01\x48" }
371
+ its(:class) { should == klass }
372
+ its(:tag) { should == Krypt::ASN1::ENUMERATED }
373
+ its(:value) { should == 72 }
374
+ end
375
+
376
+ context 127 do
377
+ let(:der) { "\x0A\x01\x7F" }
378
+ its(:class) { should == klass }
379
+ its(:tag) { should == Krypt::ASN1::ENUMERATED }
380
+ its(:value) { should == 127 }
381
+ end
382
+
383
+ context -128 do
384
+ let(:der) { "\x0A\x01\x80" }
385
+ its(:class) { should == klass }
386
+ its(:tag) { should == Krypt::ASN1::ENUMERATED }
387
+ its(:value) { should == -128 } # TODO: ossl returns 128 (positive value)
388
+ end
389
+
390
+ context 128 do
391
+ let(:der) { "\x0A\x02\x00\x80" }
392
+ its(:class) { should == klass }
393
+ its(:tag) { should == Krypt::ASN1::ENUMERATED }
394
+ its(:value) { should == 128 }
395
+ end
396
+
397
+ context -27066 do
398
+ let(:der) { "\x0A\x02\x96\x46" }
399
+ its(:class) { should == klass }
400
+ its(:tag) { should == Krypt::ASN1::ENUMERATED }
401
+ its(:value) { should == -27066 } # TODO: ossl returns 27066 (positive value)
402
+ end
403
+
404
+ context 'max Fixnum on 32bit box' do
405
+ let(:der) { "\x0A\x04\x3F\xFF\xFF\xFF" }
406
+ its(:class) { should == klass }
407
+ its(:tag) { should == Krypt::ASN1::ENUMERATED }
408
+ its(:value) { should == 2**30-1 }
409
+ end
410
+
411
+ context 'max Fixnum on 64bit box' do
412
+ let(:der) { "\x0A\x08\x3F\xFF\xFF\xFF\xFF\xFF\xFF\xFF" }
413
+ its(:class) { should == klass }
414
+ its(:tag) { should == Krypt::ASN1::ENUMERATED }
415
+ its(:value) { should == 2**62-1 }
416
+ end
417
+ end
418
+
419
+ context 'extracted tag class' do
420
+ context 'UNIVERSAL' do
421
+ let(:der) { "\x0A\x02\x00\x80" }
422
+ its(:tag_class) { should == :UNIVERSAL }
423
+ end
424
+
425
+ context 'APPLICATION' do
426
+ let(:der) { "\x4A\x02\x00\x80" }
427
+ its(:tag_class) { should == :APPLICATION }
428
+ end
429
+
430
+ context 'CONTEXT_SPECIFIC' do
431
+ let(:der) { "\x8A\x02\x00\x80" }
432
+ its(:tag_class) { should == :CONTEXT_SPECIFIC }
433
+ end
434
+
435
+ context 'PRIVATE' do
436
+ let(:der) { "\xCA\x02\x00\x80" }
437
+ its(:tag_class) { should == :PRIVATE }
438
+ end
439
+
440
+ context "setting IMPLICIT will result in CONTEXT_SPECIFIC" do
441
+ let(:der) { "\x0A\x02\x00\x80" }
442
+ it do
443
+ subject.tag_class = :IMPLICIT
444
+ subject.to_der.should == "\x8A\x02\x00\x80"
445
+ end
446
+ end
447
+
448
+ context "setting EXPLICIT will reencode as CONTEXT_SPECIFIC" do
449
+ let(:der) { "\x0A\x02\x00\x80" }
450
+ it do
451
+ subject.tag_class = :EXPLICIT
452
+ subject.tag = 0
453
+ subject.to_der.should == "\xA0\x04\x0A\x02\x00\x80"
454
+ end
455
+ end
456
+ end
457
+ end
458
+ end