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