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,795 @@
1
+ # encoding: US-ASCII
2
+
3
+ require 'rspec'
4
+ require 'krypt'
5
+ require 'openssl'
6
+ require_relative './resources'
7
+
8
+ describe Krypt::ASN1::Set do
9
+ include Krypt::ASN1::Resources
10
+
11
+ let(:mod) { Krypt::ASN1 }
12
+ let(:klass) { mod::Set }
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::Set
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 'accepts SET as Array' do
38
+ let(:value) { [s('hello'), i(42), s('world')] }
39
+ its(:tag) { should == Krypt::ASN1::SET }
40
+ its(:tag_class) { should == :UNIVERSAL }
41
+ its(:value) { should == value }
42
+ its(:infinite_length) { should == false }
43
+ end
44
+
45
+ context 'accepts SET OF as Array' do
46
+ let(:value) { [s('hello'), s(','), s('world')] }
47
+ its(:tag) { should == Krypt::ASN1::SET }
48
+ its(:tag_class) { should == :UNIVERSAL }
49
+ its(:value) { should == value }
50
+ its(:infinite_length) { should == false }
51
+ end
52
+
53
+ context 'accepts empty Array' do
54
+ let(:value) { [] }
55
+ its(:value) { should == [] }
56
+ end
57
+ end
58
+
59
+ context 'gets explicit tag number as the 2nd argument' do
60
+ let(:value) { [s('hello')] }
61
+ subject { klass.new(value, tag, :PRIVATE) }
62
+
63
+ context 'accepts default tag' do
64
+ let(:tag) { Krypt::ASN1::SET }
65
+ its(:tag) { should == tag }
66
+ end
67
+
68
+ context 'accepts custom tag' do
69
+ let(:tag) { 14 }
70
+ its(:tag) { should == tag }
71
+ end
72
+ end
73
+
74
+ context 'gets tag class symbol as the 3rd argument' do
75
+ let(:value) { [s('hello')] }
76
+ subject { klass.new(value, Krypt::ASN1::SET, tag_class) }
77
+
78
+ context 'accepts :UNIVERSAL' do
79
+ let(:tag_class) { :UNIVERSAL }
80
+ its(:tag_class) { should == tag_class }
81
+ end
82
+
83
+ context 'accepts :APPLICATION' do
84
+ let(:tag_class) { :APPLICATION }
85
+ its(:tag_class) { should == tag_class }
86
+ end
87
+
88
+ context 'accepts :CONTEXT_SPECIFIC' do
89
+ let(:tag_class) { :CONTEXT_SPECIFIC }
90
+ its(:tag_class) { should == tag_class }
91
+ end
92
+
93
+ context 'accepts :PRIVATE' do
94
+ let(:tag_class) { :PRIVATE }
95
+ its(:tag_class) { should == tag_class }
96
+ end
97
+
98
+ context 'accepts :IMPLICIT' do
99
+ let(:tag_class) { :IMPLICIT }
100
+ its(:tag_class) { should == tag_class }
101
+ end
102
+
103
+ context 'accepts :EXPLICIT' do
104
+ let(:tag_class) { :EXPLICIT }
105
+ its(:tag_class) { should == tag_class }
106
+ end
107
+ end
108
+
109
+ context 'when the 2nd argument is given but 3rd argument is omitted' do
110
+ subject { klass.new([s('hello')], Krypt::ASN1::SET) }
111
+ its(:tag_class) { should == :CONTEXT_SPECIFIC }
112
+ end
113
+ end
114
+
115
+ describe 'accessors' do
116
+ describe '#value' do
117
+ subject { o = klass.new(nil); o.value = value; o }
118
+
119
+ context 'accepts SET as Array' do
120
+ let(:value) { [s('hello'), i(42), s('world')] }
121
+ its(:tag) { should == Krypt::ASN1::SET }
122
+ its(:tag_class) { should == :UNIVERSAL }
123
+ its(:value) { should == value }
124
+ its(:infinite_length) { should == false }
125
+ end
126
+
127
+ context 'accepts SET OF as Array' do
128
+ let(:value) { [s('hello'), s(','), s('world')] }
129
+ its(:tag) { should == Krypt::ASN1::SET }
130
+ its(:tag_class) { should == :UNIVERSAL }
131
+ its(:value) { should == value }
132
+ its(:infinite_length) { should == false }
133
+ end
134
+
135
+ context 'accepts empty Array' do
136
+ let(:value) { [] }
137
+ its(:value) { should == [] }
138
+ end
139
+ end
140
+
141
+ describe '#tag' do
142
+ subject { o = klass.new(nil); o.tag = tag; o }
143
+
144
+ context 'accepts default tag' do
145
+ let(:tag) { Krypt::ASN1::SET }
146
+ its(:tag) { should == tag }
147
+ end
148
+
149
+ context 'accepts custom tag' do
150
+ let(:tag) { 14 }
151
+ its(:tag) { should == tag }
152
+ end
153
+ end
154
+
155
+ describe '#tag_class' do
156
+ subject { o = klass.new(nil); o.tag_class = tag_class; o }
157
+
158
+ context 'accepts :UNIVERSAL' do
159
+ let(:tag_class) { :UNIVERSAL }
160
+ its(:tag_class) { should == tag_class }
161
+ end
162
+
163
+ context 'accepts :APPLICATION' do
164
+ let(:tag_class) { :APPLICATION }
165
+ its(:tag_class) { should == tag_class }
166
+ end
167
+
168
+ context 'accepts :CONTEXT_SPECIFIC' do
169
+ let(:tag_class) { :CONTEXT_SPECIFIC }
170
+ its(:tag_class) { should == tag_class }
171
+ end
172
+
173
+ context 'accepts :PRIVATE' do
174
+ let(:tag_class) { :PRIVATE }
175
+ its(:tag_class) { should == tag_class }
176
+ end
177
+
178
+ context 'accepts :IMPLICIT' do
179
+ let(:tag_class) { :IMPLICIT }
180
+ its(:tag_class) { should == tag_class }
181
+ end
182
+
183
+ context 'accepts :EXPLICIT' do
184
+ let(:tag_class) { :EXPLICIT }
185
+ its(:tag_class) { should == tag_class }
186
+ end
187
+ end
188
+
189
+ describe '#infinite_length' do
190
+ subject { o = klass.new(nil); o.infinite_length = infinite_length; o }
191
+
192
+ context 'accepts true' do
193
+ let(:infinite_length) { true }
194
+ its(:infinite_length) { should == true }
195
+ end
196
+
197
+ context 'accepts false' do
198
+ let(:infinite_length) { false }
199
+ its(:infinite_length) { should == false }
200
+ end
201
+
202
+ context 'accepts nil as false' do
203
+ let(:infinite_length) { nil }
204
+ its(:infinite_length) { should == false }
205
+ end
206
+
207
+ context 'accepts non boolean as true' do
208
+ let(:infinite_length) { Object.new }
209
+ its(:infinite_length) { should == true }
210
+ end
211
+ end
212
+ end
213
+
214
+ describe '#to_der' do
215
+ context 'encodes a given value' do
216
+ subject { klass.new(value).to_der }
217
+
218
+ context 'SET' do
219
+ let(:value) { [s('hello'), i(42), s('world')] }
220
+ it { should == "\x31\x11\x02\x01\x2A\x04\x05hello\x04\x05world" }
221
+ end
222
+
223
+ context 'SET OF OctetString' do
224
+ let(:value) { [s(''), s(''), s('')] }
225
+ it { should == "\x31\x06\x04\x00\x04\x00\x04\x00" }
226
+ end
227
+
228
+ context 'SET OF Integer' do
229
+ let(:value) { [i(-1), i(0), i(1)] }
230
+ it { should == "\x31\x09\x02\x01\x00\x02\x01\x01\x02\x01\xFF" }
231
+ end
232
+
233
+ context '(empty)' do
234
+ let(:value) { [] }
235
+ it { should == "\x31\x00" }
236
+ end
237
+
238
+ context '1000 elements' do
239
+ let(:value) { [i(0)] * 1000 }
240
+ it { should == "\x31\x82\x0B\xB8" + "\x02\x01\x00" * 1000 }
241
+ end
242
+
243
+ context 'responds to :each and to sort' do
244
+ let(:value) {
245
+ o = Object.new
246
+ def o.each
247
+ yield Krypt::ASN1::OctetString.new('hello')
248
+ yield Krypt::ASN1::Integer.new(42)
249
+ yield Krypt::ASN1::OctetString.new('world')
250
+ end
251
+ def o.sort
252
+ [
253
+ Krypt::ASN1::OctetString.new('hello'),
254
+ Krypt::ASN1::Integer.new(42),
255
+ Krypt::ASN1::OctetString.new('world')
256
+ ].sort
257
+ end
258
+ o
259
+ }
260
+ it { should == "\x31\x11\x02\x01\x2A\x04\x05hello\x04\x05world" }
261
+ end
262
+
263
+ context 'responds to :each, but not sortable' do
264
+ let(:value) {
265
+ o = Object.new
266
+ def o.each
267
+ yield Krypt::ASN1::OctetString.new('hello')
268
+ yield Krypt::ASN1::Integer.new(42)
269
+ yield Krypt::ASN1::OctetString.new('world')
270
+ end
271
+ o
272
+ }
273
+ it { should == "\x31\x11\x02\x01\x2A\x04\x05hello\x04\x05world" }
274
+ end
275
+
276
+ context "orders SET encoding by tag when creating the SET" do
277
+ context "definite length Array" do
278
+ let (:value) { [
279
+ Krypt::ASN1::Null.new,
280
+ Krypt::ASN1::Integer.new(1),
281
+ Krypt::ASN1::Boolean.new(true)
282
+ ] }
283
+ it { should == "\x31\x08\x01\x01\xFF\x02\x01\x01\x05\x00" }
284
+ end
285
+
286
+ context "definite length Enumerable" do
287
+ let(:value) {
288
+ o = Object.new
289
+ def o.each
290
+ yield Krypt::ASN1::Null.new
291
+ yield Krypt::ASN1::Integer.new(1)
292
+ yield Krypt::ASN1::Boolean.new(true)
293
+ end
294
+ o
295
+ }
296
+ it { should == "\x31\x08\x01\x01\xFF\x02\x01\x01\x05\x00" }
297
+ end
298
+
299
+ context "infinite length" do
300
+ subject { o = klass.new(value); o.infinite_length = true; o.to_der }
301
+
302
+ context "infinite length Array" do
303
+ let (:value) { [
304
+ Krypt::ASN1::Null.new,
305
+ Krypt::ASN1::Integer.new(1),
306
+ Krypt::ASN1::Boolean.new(true)
307
+ ] }
308
+ it { should == "\x31\x80\x01\x01\xFF\x02\x01\x01\x05\x00\x00\x00" }
309
+ end
310
+
311
+ context "infinite length Enumerable" do
312
+ let(:value) {
313
+ o = Object.new
314
+ def o.each
315
+ yield Krypt::ASN1::Null.new
316
+ yield Krypt::ASN1::Integer.new(1)
317
+ yield Krypt::ASN1::Boolean.new(true)
318
+ end
319
+ o
320
+ }
321
+ it { should == "\x31\x80\x01\x01\xFF\x02\x01\x01\x05\x00\x00\x00" }
322
+ end
323
+ end
324
+ end
325
+
326
+ context "orders SET OF encoding in lexicographical order when creating the SET" do
327
+ context "definite length Array" do
328
+ let (:value) { [
329
+ Krypt::ASN1::OctetString.new("aaaaaa"),
330
+ Krypt::ASN1::OctetString.new("aaaab"),
331
+ Krypt::ASN1::OctetString.new("aaa"),
332
+ Krypt::ASN1::OctetString.new("b")
333
+ ] }
334
+ it { should == "\x31\x17\x04\x01b\x04\x03aaa\x04\x05aaaab\x04\x06aaaaaa" }
335
+ end
336
+
337
+ context "definite length Enumerable" do
338
+ let (:value) {
339
+ o = Object.new
340
+ def o.each
341
+ yield Krypt::ASN1::OctetString.new("aaaaaa")
342
+ yield Krypt::ASN1::OctetString.new("aaaab")
343
+ yield Krypt::ASN1::OctetString.new("aaa")
344
+ yield Krypt::ASN1::OctetString.new("b")
345
+ end
346
+ o
347
+ }
348
+ it { should == "\x31\x17\x04\x01b\x04\x03aaa\x04\x05aaaab\x04\x06aaaaaa" }
349
+ end
350
+
351
+ context "infinite length" do
352
+ subject { o = klass.new(value); o.infinite_length = true; o.to_der }
353
+
354
+ context "Array" do
355
+ let (:value) { [
356
+ Krypt::ASN1::OctetString.new("aaaaaa"),
357
+ Krypt::ASN1::OctetString.new("aaaab"),
358
+ Krypt::ASN1::OctetString.new("aaa"),
359
+ Krypt::ASN1::OctetString.new("b")
360
+ ] }
361
+ it { should == "\x31\x80\x04\x01b\x04\x03aaa\x04\x05aaaab\x04\x06aaaaaa\x00\x00" }
362
+ end
363
+
364
+ context "Enumerable" do
365
+ let (:value) {
366
+ o = Object.new
367
+ def o.each
368
+ yield Krypt::ASN1::OctetString.new("aaaaaa")
369
+ yield Krypt::ASN1::OctetString.new("aaaab")
370
+ yield Krypt::ASN1::OctetString.new("aaa")
371
+ yield Krypt::ASN1::OctetString.new("b")
372
+ end
373
+ o
374
+ }
375
+ it { should == "\x31\x80\x04\x01b\x04\x03aaa\x04\x05aaaab\x04\x06aaaaaa\x00\x00" }
376
+ end
377
+ end
378
+ end
379
+
380
+ context 'nil' do
381
+ let(:value) { nil }
382
+ it { -> { subject }.should raise_error asn1error }
383
+ end
384
+
385
+ context 'does not respond to :each' do
386
+ let(:value) { '123' }
387
+ it { -> { subject }.should raise_error asn1error }
388
+ end
389
+ end
390
+
391
+ context 'encodes tag number' do
392
+ let(:value) { [s(''), s(''), s('')] }
393
+ subject { klass.new(value, tag, :PRIVATE).to_der }
394
+
395
+ context 'default tag' do
396
+ let(:tag) { Krypt::ASN1::SET }
397
+ it { should == "\xF1\x06\x04\x00\x04\x00\x04\x00" }
398
+ end
399
+
400
+ context 'custom tag' do
401
+ let(:tag) { 14 }
402
+ it { should == "\xEE\x06\x04\x00\x04\x00\x04\x00" }
403
+ end
404
+
405
+ context 'nil' do
406
+ let(:tag) { nil }
407
+ it { -> { subject }.should raise_error asn1error }
408
+ end
409
+ end
410
+
411
+ context 'encodes tag class' do
412
+ let(:value) { [s(''), s(''), s('')] }
413
+ subject { klass.new(value, Krypt::ASN1::SET, tag_class).to_der }
414
+
415
+ context 'UNIVERSAL' do
416
+ let(:tag_class) { :UNIVERSAL }
417
+ it { should == "\x31\x06\x04\x00\x04\x00\x04\x00" }
418
+ end
419
+
420
+ context 'APPLICATION' do
421
+ let(:tag_class) { :APPLICATION }
422
+ it { should == "\x71\x06\x04\x00\x04\x00\x04\x00" }
423
+ end
424
+
425
+ context 'CONTEXT_SPECIFIC' do
426
+ let(:tag_class) { :CONTEXT_SPECIFIC }
427
+ it { should == "\xB1\x06\x04\x00\x04\x00\x04\x00" }
428
+ end
429
+
430
+ context 'PRIVATE' do
431
+ let(:tag_class) { :PRIVATE }
432
+ it { should == "\xF1\x06\x04\x00\x04\x00\x04\x00" }
433
+ end
434
+
435
+ context 'IMPLICIT' do
436
+ let(:tag_class) { :IMPLICIT }
437
+ it { should == "\xB1\x06\x04\x00\x04\x00\x04\x00" }
438
+ end
439
+
440
+ context 'EXPLICIT' do
441
+ let(:tag_class) { :EXPLICIT }
442
+ it { should == "\xB1\x08\x31\x06\x04\x00\x04\x00\x04\x00" }
443
+ end
444
+
445
+ context nil do
446
+ let(:tag_class) { nil }
447
+ it { -> { subject }.should raise_error asn1error } # TODO: ossl does not check nil
448
+ end
449
+
450
+ context :no_such_class do
451
+ let(:tag_class) { :no_such_class }
452
+ it { -> { subject }.should raise_error asn1error }
453
+ end
454
+ end
455
+
456
+ context 'encodes indefinite length packets' do
457
+ subject {
458
+ o = klass.new(nil, Krypt::ASN1::SET, :UNIVERSAL)
459
+ o.value = value if defined? value
460
+ o.infinite_length = true
461
+ o
462
+ }
463
+
464
+ context 'with EndOfContents' do
465
+ let(:value) { [s('hello'), i(42), s('world'), eoc] }
466
+ let(:infinite_length) { true }
467
+ its(:to_der) { should == "\x31\x80\x02\x01\x2A\x04\x05hello\x04\x05world\x00\x00" }
468
+ end
469
+
470
+ context 'with 0-tagged zero-length value without EndOfContents' do
471
+ let(:value) { [i(0), i(-1), Krypt::ASN1::ASN1Data.new(nil, 0, :CONTEXT_SPECIFIC)] }
472
+ let(:infinite_length) { true }
473
+ its(:to_der) { should == "\x31\x80\x80\x00\x02\x01\x00\x02\x01\xFF\x00\x00" }
474
+ end
475
+
476
+ context 'with 0-tagged zero-length value with EndOfContents' do
477
+ let(:value) { [i(0), i(-1), Krypt::ASN1::ASN1Data.new(nil, 0, :CONTEXT_SPECIFIC), Krypt::ASN1::EndOfContents.new] }
478
+ let(:infinite_length) { true }
479
+ its(:to_der) { should == "\x31\x80\x80\x00\x02\x01\x00\x02\x01\xFF\x00\x00" }
480
+ end
481
+ end
482
+
483
+ context 'encodes values set via accessors' do
484
+ subject {
485
+ o = klass.new(nil)
486
+ o.value = value if defined? value
487
+ o.tag = tag if defined? tag
488
+ o.tag_class = tag_class if defined? tag_class
489
+ o.to_der
490
+ }
491
+
492
+ context 'value: SET' do
493
+ let(:value) { [s('hello'), i(42), s('world')] }
494
+ it { should == "\x31\x11\x02\x01\x2A\x04\x05hello\x04\x05world" }
495
+ end
496
+
497
+ context 'custom tag' do
498
+ let(:value) { [s('hello'), i(42), s('world')] }
499
+ let(:tag) { 14 }
500
+ let(:tag_class) { :PRIVATE }
501
+ it { should == "\xEE\x11\x04\x05hello\x02\x01\x2A\x04\x05world" }
502
+ end
503
+
504
+ context 'tag_class' do
505
+ let(:value) { [s('hello'), i(42), s('world')] }
506
+ let(:tag_class) { :APPLICATION }
507
+ it { should == "\x71\x11\x04\x05hello\x02\x01\x2A\x04\x05world" }
508
+ end
509
+ end
510
+
511
+ context "encodes infinite length values" do
512
+ subject do
513
+ asn1 = klass.new(value)
514
+ asn1.infinite_length = true
515
+ asn1.to_der
516
+ end
517
+
518
+ context "with explicit EOC" do
519
+ let(:value) { [
520
+ mod::Integer.new(1),
521
+ mod::Boolean.new(true),
522
+ mod::EndOfContents.new
523
+ ] }
524
+ it { subject.should == "\x31\x80\x01\x01\xFF\x02\x01\x01\x00\x00" }
525
+ end
526
+
527
+ context "without explicit EOC" do
528
+ let(:value) { [
529
+ mod::Integer.new(1),
530
+ mod::Boolean.new(true),
531
+ ] }
532
+ it { subject.should == "\x31\x80\x01\x01\xFF\x02\x01\x01\x00\x00" }
533
+ end
534
+ end
535
+ end
536
+
537
+ describe '#encode_to' do
538
+ context 'encodes to an IO' do
539
+ subject { klass.new(value).encode_to(io); io }
540
+
541
+ context "StringIO" do
542
+ let(:value) { [s(''), s(''), s('')] }
543
+ let(:io) { string_io_object }
544
+ its(:written_bytes) { should == "\x31\x06\x04\x00\x04\x00\x04\x00" }
545
+ end
546
+
547
+ context "Object responds to :write" do
548
+ let(:value) { [s(''), s(''), s('')] }
549
+ let(:io) { writable_object }
550
+ its(:written_bytes) { should == "\x31\x06\x04\x00\x04\x00\x04\x00" }
551
+ end
552
+
553
+ context "raise IO error transparently" do
554
+ let(:value) { [s(''), s(''), s('')] }
555
+ let(:io) { io_error_object }
556
+ it { -> { subject }.should raise_error asn1error }
557
+ end
558
+ end
559
+
560
+ it 'returns self' do
561
+ obj = klass.new([s(''), s(''), s('')])
562
+ obj.encode_to(string_io_object).should == obj
563
+ end
564
+ end
565
+
566
+ describe '#each' do
567
+ subject { yielded_value_from_each(klass.new(value)) }
568
+
569
+ context "yields each value in its order" do
570
+ let(:value) { [s('hello'), i(42), s('world')] }
571
+ it { should == value }
572
+ end
573
+
574
+ context "yields nothing for empty value" do
575
+ let(:value) { [] }
576
+ it { should == value }
577
+ end
578
+
579
+ it "is Enumerable via each" do
580
+ value = [s('hello'), i(42), s('world')]
581
+ klass.new(value).map { |e| e.value }.should == ['hello', 42, 'world']
582
+ end
583
+
584
+ it "returns Enumerator for blockless call" do
585
+ value = [s('hello'), i(42), s('world')]
586
+ klass.new(value).each.next.value.should == 'hello'
587
+ end
588
+
589
+ it "yields each value for an Enumerable" do
590
+ o = Object.new
591
+ def o.each
592
+ yield Krypt::ASN1::Integer.new(1)
593
+ yield Krypt::ASN1::Integer.new(2)
594
+ yield Krypt::ASN1::Integer.new(3)
595
+ end
596
+ klass.new(o).map { |e| e.value }.should == [1, 2, 3]
597
+ end
598
+ end
599
+
600
+ describe 'extracted from ASN1.decode' do
601
+ subject { decoder.decode(der) }
602
+
603
+ context 'extracted value' do
604
+ context 'SET' do
605
+ let(:der) { "\x31\x11\x04\x05hello\x02\x01\x2A\x04\x05world" }
606
+ its(:class) { should == klass }
607
+ its(:tag) { should == Krypt::ASN1::SET }
608
+ it 'contains decoded value' do
609
+ value = subject.value
610
+ value.size.should == 3
611
+ value[0].value == 'hello'
612
+ value[1].value == 42
613
+ value[2].value == 'world'
614
+ end
615
+ end
616
+
617
+ context 'SET OF Integer' do
618
+ let(:der) { "\x31\x0C\x02\x04\xFF\xFF\xFF\xFF\x02\x01\x00\x02\x01\x01" }
619
+ its(:class) { should == klass }
620
+ its(:tag) { should == Krypt::ASN1::SET }
621
+ it 'contains decoded value' do
622
+ value = subject.value
623
+ value.size.should == 3
624
+ value[0].value == -1
625
+ value[1].value == 0
626
+ value[2].value == 1
627
+ end
628
+ end
629
+
630
+ context '(empty)' do
631
+ let(:der) { "\x31\x00" }
632
+ its(:class) { should == klass }
633
+ its(:tag) { should == Krypt::ASN1::SET }
634
+ its(:value) { should == [] }
635
+ end
636
+
637
+ context '1000 elements' do
638
+ let(:der) { "\x31\x82\x0B\xB8" + "\x02\x01\x00" * 1000 }
639
+ its(:class) { should == klass }
640
+ its(:tag) { should == Krypt::ASN1::SET }
641
+ it 'contains decoded value' do
642
+ value = subject.value
643
+ value.size == 1000
644
+ value.all? { |v| v.value == 0 }.should be_true
645
+ end
646
+ end
647
+ end
648
+
649
+ context 'extracted tag class' do
650
+ context 'UNIVERSAL' do
651
+ let(:der) { "\x31\x11\x04\x05hello\x02\x01\x2A\x04\x05world" }
652
+ its(:tag_class) { should == :UNIVERSAL }
653
+ end
654
+
655
+ context 'APPLICATION' do
656
+ let(:der) { "\x71\x11\x04\x05hello\x02\x01\x2A\x04\x05world" }
657
+ its(:tag_class) { should == :APPLICATION }
658
+ end
659
+
660
+ context 'CONTEXT_SPECIFIC' do
661
+ let(:der) { "\xB1\x11\x04\x05hello\x02\x01\x2A\x04\x05world" }
662
+ its(:tag_class) { should == :CONTEXT_SPECIFIC }
663
+ end
664
+
665
+ context 'PRIVATE' do
666
+ let(:der) { "\xF1\x11\x04\x05hello\x02\x01\x2A\x04\x05world" }
667
+ its(:tag_class) { should == :PRIVATE }
668
+ end
669
+
670
+ context "setting IMPLICIT will result in CONTEXT_SPECIFIC" do
671
+ let(:der) { "\x31\x11\x04\x05hello\x02\x01\x2A\x04\x05world" }
672
+ it do
673
+ subject.tag_class = :IMPLICIT
674
+ subject.to_der.should == "\xB1\x11\x04\x05hello\x02\x01\x2A\x04\x05world"
675
+ end
676
+ end
677
+
678
+ context "setting EXPLICIT will reencode as CONTEXT_SPECIFIC" do
679
+ let(:der) { "\x31\x11\x04\x05hello\x02\x01\x2A\x04\x05world" }
680
+ it do
681
+ subject.tag_class = :EXPLICIT
682
+ subject.tag = 0
683
+ subject.to_der.should == "\xA0\x13\x31\x11\x02\x01\x2A\x04\x05hello\x04\x05world"
684
+ end
685
+ end
686
+ end
687
+
688
+ context "preserves wrongly encoded SET encodings" do
689
+ context "definite length" do
690
+ let(:der) { "\x31\x08\x05\x00\x02\x01\x01\x01\x01\xFF" }
691
+ it do
692
+ ary = subject.value
693
+ ary.size.should == 3
694
+ ary[0].tag.should == Krypt::ASN1::NULL
695
+ ary[1].tag.should == Krypt::ASN1::INTEGER
696
+ ary[2].tag.should == Krypt::ASN1::BOOLEAN
697
+ subject.to_der.should == der
698
+ end
699
+ end
700
+
701
+ context "infinite length" do
702
+ let(:der) { "\x31\x80\x05\x00\x02\x01\x01\x01\x01\xFF\x00\x00" }
703
+ it do
704
+ ary = subject.value
705
+ ary.size.should == 3
706
+ ary[0].tag.should == Krypt::ASN1::NULL
707
+ ary[1].tag.should == Krypt::ASN1::INTEGER
708
+ ary[2].tag.should == Krypt::ASN1::BOOLEAN
709
+ subject.to_der.should == der
710
+ end
711
+ end
712
+
713
+ context "reencodes the value in proper SET encoding when the set value is changed" do
714
+ let(:der) { "\x31\x08\x05\x00\x02\x01\x01\x01\x01\xFF" }
715
+ it do
716
+ subject.value = [
717
+ Krypt::ASN1::Null.new,
718
+ Krypt::ASN1::Integer.new(1),
719
+ Krypt::ASN1::Boolean.new(true)
720
+ ]
721
+ subject.to_der.should == "\x31\x08\x01\x01\xFF\x02\x01\x01\x05\x00"
722
+ end
723
+ end
724
+
725
+ context "keeps the wrong SET order when an inner value is changed" do # would be too expensive to track
726
+ let(:der) { "\x31\x08\x05\x00\x02\x01\x01\x01\x01\xFF" }
727
+ it do
728
+ ary = subject.value
729
+ ary[1].value = 7
730
+ subject.to_der.should == "\x31\x08\x05\x00\x02\x01\x07\x01\x01\xFF"
731
+ end
732
+ end
733
+ end
734
+
735
+ context "preserves wrongly encoded SET OF encodings" do
736
+ context "definite length" do
737
+ let(:der) { "\x31\x0C\x04\x01b\x04\x03aaa\x04\x02aa" }
738
+ it do
739
+ ary = subject.value
740
+ ary.size.should == 3
741
+ ary[0].value.should == "b"
742
+ ary[1].value.should == "aaa"
743
+ ary[2].value.should == "aa"
744
+ subject.to_der.should == der
745
+ end
746
+ end
747
+
748
+ context "infinite length" do
749
+ let(:der) { "\x31\x80\x04\x01b\x04\x03aaa\x04\x02aa\x00\x00" }
750
+ it do
751
+ ary = subject.value
752
+ ary.size.should == 3
753
+ ary[0].value.should == "b"
754
+ ary[1].value.should == "aaa"
755
+ ary[2].value.should == "aa"
756
+ subject.to_der.should == der
757
+ end
758
+ end
759
+
760
+ context "reencodes the value in proper SET OF encoding when the set value is changed" do
761
+ let(:der) { "\x31\x0C\x04\x01b\x04\x03aaa\x04\x02aa" }
762
+ it do
763
+ subject.value = subject.value
764
+ subject.to_der.should == "\x31\x0C\x04\x01b\x04\x02aa\x04\x03aaa"
765
+ end
766
+ end
767
+
768
+ context "keeps the wrong SET order when an inner value is changed" do # would be too expensive to track
769
+ let(:der) { "\x31\x0C\x04\x01b\x04\x03aaa\x04\x02aa" }
770
+ it do
771
+ ary = subject.value
772
+ ary[0].value = "c"
773
+ subject.to_der.should == "\x31\x0C\x04\x01c\x04\x03aaa\x04\x02aa"
774
+ end
775
+ end
776
+ end
777
+
778
+ context 'extracted infinite_length' do
779
+ context 'definite encoding' do
780
+ let(:der) { "\x31\x11\x04\x05hello\x02\x01\x2A\x04\x05world" }
781
+ its(:infinite_length) { should == false }
782
+ end
783
+
784
+ context 'indefinite encoding' do
785
+ let(:der) { "\x31\x80\x04\x05hello\x02\x01\x2A\x04\x05world\x00\x00" }
786
+ its(:infinite_length) { should == true }
787
+ it "drops EndOfContents as last value" do
788
+ subject.value.size.should == 3
789
+ subject.value.any? { |o| o.instance_of? Krypt::ASN1::EndOfContents }.should be_false
790
+ end
791
+ end
792
+ end
793
+ end
794
+ end
795
+