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