hexapdf 0.19.3 → 0.20.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -0
  3. data/data/hexapdf/cert/demo_cert.rb +22 -0
  4. data/data/hexapdf/cert/root-ca.crt +119 -0
  5. data/data/hexapdf/cert/signing.crt +125 -0
  6. data/data/hexapdf/cert/signing.key +52 -0
  7. data/data/hexapdf/cert/sub-ca.crt +125 -0
  8. data/data/hexapdf/encoding/glyphlist.txt +4283 -4282
  9. data/data/hexapdf/encoding/zapfdingbats.txt +203 -202
  10. data/lib/hexapdf/cli/form.rb +9 -1
  11. data/lib/hexapdf/cli/info.rb +21 -1
  12. data/lib/hexapdf/configuration.rb +26 -0
  13. data/lib/hexapdf/content/processor.rb +1 -1
  14. data/lib/hexapdf/document/signatures.rb +327 -0
  15. data/lib/hexapdf/document.rb +26 -0
  16. data/lib/hexapdf/encryption/security_handler.rb +5 -1
  17. data/lib/hexapdf/font/encoding/glyph_list.rb +5 -6
  18. data/lib/hexapdf/importer.rb +1 -1
  19. data/lib/hexapdf/object.rb +5 -3
  20. data/lib/hexapdf/rectangle.rb +0 -6
  21. data/lib/hexapdf/revision.rb +13 -6
  22. data/lib/hexapdf/task/dereference.rb +12 -4
  23. data/lib/hexapdf/task/optimize.rb +3 -3
  24. data/lib/hexapdf/type/acro_form/appearance_generator.rb +2 -4
  25. data/lib/hexapdf/type/acro_form/field.rb +2 -0
  26. data/lib/hexapdf/type/acro_form/form.rb +9 -1
  27. data/lib/hexapdf/type/annotation.rb +37 -4
  28. data/lib/hexapdf/type/font_simple.rb +1 -1
  29. data/lib/hexapdf/type/object_stream.rb +3 -1
  30. data/lib/hexapdf/type/signature/adbe_pkcs7_detached.rb +121 -0
  31. data/lib/hexapdf/type/signature/adbe_x509_rsa_sha1.rb +95 -0
  32. data/lib/hexapdf/type/signature/handler.rb +140 -0
  33. data/lib/hexapdf/type/signature/verification_result.rb +92 -0
  34. data/lib/hexapdf/type/signature.rb +236 -0
  35. data/lib/hexapdf/type.rb +1 -0
  36. data/lib/hexapdf/version.rb +1 -1
  37. data/lib/hexapdf/writer.rb +27 -11
  38. data/test/hexapdf/content/test_processor.rb +1 -1
  39. data/test/hexapdf/document/test_signatures.rb +225 -0
  40. data/test/hexapdf/encryption/test_security_handler.rb +11 -3
  41. data/test/hexapdf/task/test_optimize.rb +4 -1
  42. data/test/hexapdf/test_document.rb +28 -0
  43. data/test/hexapdf/test_object.rb +7 -2
  44. data/test/hexapdf/test_rectangle.rb +0 -7
  45. data/test/hexapdf/test_revision.rb +44 -14
  46. data/test/hexapdf/test_writer.rb +15 -3
  47. data/test/hexapdf/type/acro_form/test_field.rb +11 -1
  48. data/test/hexapdf/type/acro_form/test_form.rb +5 -0
  49. data/test/hexapdf/type/signature/common.rb +71 -0
  50. data/test/hexapdf/type/signature/test_adbe_pkcs7_detached.rb +99 -0
  51. data/test/hexapdf/type/signature/test_adbe_x509_rsa_sha1.rb +66 -0
  52. data/test/hexapdf/type/signature/test_handler.rb +102 -0
  53. data/test/hexapdf/type/signature/test_verification_result.rb +47 -0
  54. data/test/hexapdf/type/test_annotation.rb +47 -3
  55. data/test/hexapdf/type/test_font_simple.rb +5 -5
  56. data/test/hexapdf/type/test_object_stream.rb +9 -0
  57. data/test/hexapdf/type/test_signature.rb +131 -0
  58. metadata +21 -3
@@ -25,7 +25,7 @@ describe HexaPDF::Type::FontSimple do
25
25
  describe "encoding" do
26
26
  it "fails if /Encoding is absent because encoding_from_font is not implemented" do
27
27
  @font.delete(:Encoding)
28
- assert_raises(NotImplementedError) { @font.encoding }
28
+ assert_raises(RuntimeError) { @font.encoding }
29
29
  end
30
30
 
31
31
  describe "/Encoding is a name" do
@@ -35,7 +35,7 @@ describe HexaPDF::Type::FontSimple do
35
35
 
36
36
  it "fails if /Encoding is an invalid name because encoding_from_font is not implemented" do
37
37
  @font[:Encoding] = :SomethingUnknown
38
- assert_raises(NotImplementedError) { @font.encoding }
38
+ assert_raises(RuntimeError) { @font.encoding }
39
39
  end
40
40
  end
41
41
 
@@ -47,12 +47,12 @@ describe HexaPDF::Type::FontSimple do
47
47
  describe "no /BaseEncoding is specified" do
48
48
  it "fails if the font is embedded because encoding_from_font is not implemented" do
49
49
  @font[:FontDescriptor][:FontFile] = 5
50
- assert_raises(NotImplementedError) { @font.encoding }
50
+ assert_raises(RuntimeError) { @font.encoding }
51
51
  end
52
52
 
53
53
  it "fails for a symbolic non-embedded font because encoding_from_font is not implemented" do
54
54
  @font[:FontDescriptor].flag(:symbolic, clear_existing: true)
55
- assert_raises(NotImplementedError) { @font.encoding }
55
+ assert_raises(RuntimeError) { @font.encoding }
56
56
  end
57
57
 
58
58
  it "returns the StandardEncoding for a non-symbolic non-embedded font" do
@@ -68,7 +68,7 @@ describe HexaPDF::Type::FontSimple do
68
68
 
69
69
  it "fails if /BaseEncoding is invalid because encoding_from_font is not implemented" do
70
70
  @font[:Encoding] = {BaseEncoding: :SomethingUnknown}
71
- assert_raises(NotImplementedError) { @font.encoding }
71
+ assert_raises(RuntimeError) { @font.encoding }
72
72
  end
73
73
 
74
74
  it "returns a difference encoding if /Differences is specified" do
@@ -104,6 +104,15 @@ describe HexaPDF::Type::ObjectStream do
104
104
  assert_equal(0, @obj.value[:First])
105
105
  assert_equal("", @obj.stream)
106
106
  end
107
+
108
+ it "doesn't allow signature dictionaries to be compressed" do
109
+ @obj.add_object(HexaPDF::Dictionary.new({Type: :Sig}, oid: 1))
110
+ @obj.add_object(HexaPDF::Dictionary.new({Type: :DocTimeStamp}, oid: 2))
111
+ @obj.add_object(HexaPDF::Dictionary.new({ByteRange: [], Contents: ''}, oid: 3))
112
+ @obj.write_objects(@revision)
113
+ assert_equal(0, @obj.value[:N])
114
+ assert_equal("", @obj.stream)
115
+ end
107
116
  end
108
117
 
109
118
  it "fails validation if gen != 0" do
@@ -0,0 +1,131 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/type/signature'
6
+ require_relative 'signature/common'
7
+ require 'stringio'
8
+
9
+ describe HexaPDF::Type::Signature::TransformParams do
10
+ before do
11
+ @doc = HexaPDF::Document.new
12
+ @params = @doc.add({Type: :TransformParams})
13
+ end
14
+
15
+ describe "validation" do
16
+ it "checks the /Annots field for valid values" do
17
+ @params[:Annots] = [:Create, :Other, :Delete, :Other, :New]
18
+ refute(@params.validate(auto_correct: false))
19
+ @params.validate
20
+ assert_equal([:Create, :Delete], @params[:Annots].value)
21
+ end
22
+
23
+ it "checks the /Form field for valid values" do
24
+ @params[:Form] = [:Add, :Other, :Delete, :Other, :New]
25
+ refute(@params.validate(auto_correct: false))
26
+ @params.validate
27
+ assert_equal([:Add, :Delete], @params[:Form].value)
28
+ end
29
+
30
+ it "checks the /EF field for valid values" do
31
+ @params[:EF] = [:Create, :Other, :Delete, :Other, :New]
32
+ refute(@params.validate(auto_correct: false))
33
+ @params.validate
34
+ assert_equal([:Create, :Delete], @params[:EF].value)
35
+ end
36
+ end
37
+ end
38
+
39
+ describe HexaPDF::Type::Signature::SignatureReference do
40
+ before do
41
+ @doc = HexaPDF::Document.new
42
+ @sigref = @doc.add({Type: :SigRef})
43
+ end
44
+
45
+ describe "validation" do
46
+ it "checks the existence of the /Data field for FieldMDP transforms" do
47
+ @sigref[:TransformMethod] = :FieldMDP
48
+ refute(@sigref.validate)
49
+ @sigref[:Data] = HexaPDF::Object.new('data', oid: 1)
50
+ assert(@sigref.validate)
51
+ end
52
+ end
53
+ end
54
+
55
+ describe HexaPDF::Type::Signature do
56
+ before do
57
+ @doc = HexaPDF::Document.new
58
+ @sig = @doc.add({Type: :Sig, Filter: :'Adobe.PPKLite', SubFilter: :'ETSI.CAdES.detached'})
59
+
60
+ @pdf_data = 'Some data'
61
+ @pkcs7 = OpenSSL::PKCS7.sign(CERTIFICATES.signer_certificate, CERTIFICATES.signer_key,
62
+ @pdf_data, [CERTIFICATES.ca_certificate],
63
+ OpenSSL::PKCS7::DETACHED)
64
+ @sig[:Contents] = @pkcs7.to_der
65
+ end
66
+
67
+ it "returns the signer name" do
68
+ assert_equal('signer', @sig.signer_name)
69
+ end
70
+
71
+ it "returns the signing time" do
72
+ assert_equal(@sig.signature_handler.signing_time, @sig.signing_time)
73
+ end
74
+
75
+ it "returns the signing reason" do
76
+ @sig[:Reason] = 'reason'
77
+ assert_equal('reason', @sig.signing_reason)
78
+ end
79
+
80
+ it "returns the signing location" do
81
+ @sig[:Location] = 'location'
82
+ assert_equal('location', @sig.signing_location)
83
+ end
84
+
85
+ it "returns the signature type" do
86
+ assert_equal('ETSI.CAdES.detached', @sig.signature_type)
87
+ end
88
+
89
+ describe "signature_handler" do
90
+ it "returns the signature handler" do
91
+ assert_kind_of(HexaPDF::Type::Signature::Handler, @sig.signature_handler)
92
+ end
93
+
94
+ it "fails if the required handler is not available" do
95
+ @sig[:SubFilter] = :Unknown
96
+ assert_raises(HexaPDF::Error) { @sig.signature_handler }
97
+ end
98
+ end
99
+
100
+ it "returns the signature contents" do
101
+ @sig[:Contents] = 'hallo'
102
+ assert_equal('hallo', @sig.contents)
103
+ end
104
+
105
+ describe "signed_data" do
106
+ it "reads the specified portions of the document" do
107
+ io = StringIO.new(MINIMAL_PDF)
108
+ doc = HexaPDF::Document.new(io: io)
109
+ @sig.document = doc
110
+ @sig[:ByteRange] = [0, 400, 500, 333]
111
+ assert_equal((MINIMAL_PDF[0, 400] << MINIMAL_PDF[500, 333]).b, @sig.signed_data)
112
+ end
113
+
114
+ it "fails if the document isn't associated with an existing PDF file" do
115
+ assert_raises(HexaPDF::Error) { @sig.signed_data }
116
+ end
117
+ end
118
+
119
+ it "invokes the signature handler for verification" do
120
+ handler = Object.new
121
+ store, kwargs = nil
122
+ handler.define_singleton_method(:verify) do |in_store, in_kwargs|
123
+ store, kwargs = in_store, in_kwargs
124
+ :result
125
+ end
126
+ @sig.define_singleton_method(:signature_handler) { handler }
127
+ assert_equal(:result, @sig.verify(allow_self_signed: true))
128
+ assert_kind_of(OpenSSL::X509::Store, store)
129
+ assert(kwargs[:allow_self_signed])
130
+ end
131
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hexapdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.3
4
+ version: 0.20.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Leitner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-14 00:00:00.000000000 Z
11
+ date: 2022-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse
@@ -124,6 +124,11 @@ files:
124
124
  - data/hexapdf/afm/Times-Italic.afm
125
125
  - data/hexapdf/afm/Times-Roman.afm
126
126
  - data/hexapdf/afm/ZapfDingbats.afm
127
+ - data/hexapdf/cert/demo_cert.rb
128
+ - data/hexapdf/cert/root-ca.crt
129
+ - data/hexapdf/cert/signing.crt
130
+ - data/hexapdf/cert/signing.key
131
+ - data/hexapdf/cert/sub-ca.crt
127
132
  - data/hexapdf/cmap/83pv-RKSJ-H
128
133
  - data/hexapdf/cmap/90ms-RKSJ-H
129
134
  - data/hexapdf/cmap/90ms-RKSJ-V
@@ -254,6 +259,7 @@ files:
254
259
  - lib/hexapdf/document/fonts.rb
255
260
  - lib/hexapdf/document/images.rb
256
261
  - lib/hexapdf/document/pages.rb
262
+ - lib/hexapdf/document/signatures.rb
257
263
  - lib/hexapdf/encryption.rb
258
264
  - lib/hexapdf/encryption/aes.rb
259
265
  - lib/hexapdf/encryption/arc4.rb
@@ -396,6 +402,11 @@ files:
396
402
  - lib/hexapdf/type/page.rb
397
403
  - lib/hexapdf/type/page_tree_node.rb
398
404
  - lib/hexapdf/type/resources.rb
405
+ - lib/hexapdf/type/signature.rb
406
+ - lib/hexapdf/type/signature/adbe_pkcs7_detached.rb
407
+ - lib/hexapdf/type/signature/adbe_x509_rsa_sha1.rb
408
+ - lib/hexapdf/type/signature/handler.rb
409
+ - lib/hexapdf/type/signature/verification_result.rb
399
410
  - lib/hexapdf/type/trailer.rb
400
411
  - lib/hexapdf/type/viewer_preferences.rb
401
412
  - lib/hexapdf/type/xref_stream.rb
@@ -497,6 +508,7 @@ files:
497
508
  - test/hexapdf/document/test_fonts.rb
498
509
  - test/hexapdf/document/test_images.rb
499
510
  - test/hexapdf/document/test_pages.rb
511
+ - test/hexapdf/document/test_signatures.rb
500
512
  - test/hexapdf/encryption/common.rb
501
513
  - test/hexapdf/encryption/test_aes.rb
502
514
  - test/hexapdf/encryption/test_arc4.rb
@@ -605,6 +617,11 @@ files:
605
617
  - test/hexapdf/type/annotations/test_markup_annotation.rb
606
618
  - test/hexapdf/type/annotations/test_text.rb
607
619
  - test/hexapdf/type/annotations/test_widget.rb
620
+ - test/hexapdf/type/signature/common.rb
621
+ - test/hexapdf/type/signature/test_adbe_pkcs7_detached.rb
622
+ - test/hexapdf/type/signature/test_adbe_x509_rsa_sha1.rb
623
+ - test/hexapdf/type/signature/test_handler.rb
624
+ - test/hexapdf/type/signature/test_verification_result.rb
608
625
  - test/hexapdf/type/test_annotation.rb
609
626
  - test/hexapdf/type/test_catalog.rb
610
627
  - test/hexapdf/type/test_cid_font.rb
@@ -623,6 +640,7 @@ files:
623
640
  - test/hexapdf/type/test_page.rb
624
641
  - test/hexapdf/type/test_page_tree_node.rb
625
642
  - test/hexapdf/type/test_resources.rb
643
+ - test/hexapdf/type/test_signature.rb
626
644
  - test/hexapdf/type/test_trailer.rb
627
645
  - test/hexapdf/type/test_xref_stream.rb
628
646
  - test/hexapdf/utils/test_bit_field.rb
@@ -653,7 +671,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
653
671
  - !ruby/object:Gem::Version
654
672
  version: '0'
655
673
  requirements: []
656
- rubygems_version: 3.2.3
674
+ rubygems_version: 3.3.3
657
675
  signing_key:
658
676
  specification_version: 4
659
677
  summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby