hexapdf 0.19.0 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +69 -0
- data/data/hexapdf/cert/demo_cert.rb +22 -0
- data/data/hexapdf/cert/root-ca.crt +119 -0
- data/data/hexapdf/cert/signing.crt +125 -0
- data/data/hexapdf/cert/signing.key +52 -0
- data/data/hexapdf/cert/sub-ca.crt +125 -0
- data/lib/hexapdf/cli/info.rb +21 -1
- data/lib/hexapdf/configuration.rb +26 -0
- data/lib/hexapdf/content/graphics_state.rb +24 -5
- data/lib/hexapdf/content/processor.rb +1 -1
- data/lib/hexapdf/document/signatures.rb +327 -0
- data/lib/hexapdf/document.rb +26 -0
- data/lib/hexapdf/encryption/standard_security_handler.rb +1 -2
- data/lib/hexapdf/importer.rb +1 -1
- data/lib/hexapdf/layout/style.rb +2 -1
- data/lib/hexapdf/object.rb +5 -3
- data/lib/hexapdf/parser.rb +21 -9
- data/lib/hexapdf/rectangle.rb +0 -6
- data/lib/hexapdf/revision.rb +13 -6
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +2 -4
- data/lib/hexapdf/type/acro_form/field.rb +2 -0
- data/lib/hexapdf/type/acro_form/form.rb +9 -1
- data/lib/hexapdf/type/annotation.rb +36 -3
- data/lib/hexapdf/type/font.rb +5 -0
- data/lib/hexapdf/type/font_simple.rb +1 -1
- data/lib/hexapdf/type/font_type3.rb +20 -0
- data/lib/hexapdf/type/object_stream.rb +3 -1
- data/lib/hexapdf/type/signature/adbe_pkcs7_detached.rb +125 -0
- data/lib/hexapdf/type/signature/adbe_x509_rsa_sha1.rb +99 -0
- data/lib/hexapdf/type/signature/handler.rb +112 -0
- data/lib/hexapdf/type/signature/verification_result.rb +92 -0
- data/lib/hexapdf/type/signature.rb +236 -0
- data/lib/hexapdf/type.rb +1 -0
- data/lib/hexapdf/version.rb +1 -1
- data/lib/hexapdf/writer.rb +24 -10
- data/test/hexapdf/content/test_graphics_state.rb +9 -1
- data/test/hexapdf/content/test_operator.rb +8 -3
- data/test/hexapdf/content/test_processor.rb +1 -1
- data/test/hexapdf/document/test_signatures.rb +225 -0
- data/test/hexapdf/encryption/test_standard_security_handler.rb +8 -6
- data/test/hexapdf/layout/test_style.rb +11 -0
- data/test/hexapdf/test_document.rb +28 -0
- data/test/hexapdf/test_object.rb +7 -2
- data/test/hexapdf/test_parser.rb +14 -0
- data/test/hexapdf/test_rectangle.rb +0 -7
- data/test/hexapdf/test_revision.rb +44 -14
- data/test/hexapdf/test_writer.rb +44 -14
- data/test/hexapdf/type/acro_form/test_field.rb +11 -1
- data/test/hexapdf/type/acro_form/test_form.rb +5 -0
- data/test/hexapdf/type/signature/common.rb +71 -0
- data/test/hexapdf/type/signature/test_adbe_pkcs7_detached.rb +99 -0
- data/test/hexapdf/type/signature/test_adbe_x509_rsa_sha1.rb +66 -0
- data/test/hexapdf/type/signature/test_handler.rb +76 -0
- data/test/hexapdf/type/signature/test_verification_result.rb +47 -0
- data/test/hexapdf/type/test_annotation.rb +40 -2
- data/test/hexapdf/type/test_font.rb +4 -0
- data/test/hexapdf/type/test_font_simple.rb +5 -5
- data/test/hexapdf/type/test_font_type3.rb +16 -1
- data/test/hexapdf/type/test_object_stream.rb +9 -0
- data/test/hexapdf/type/test_signature.rb +131 -0
- metadata +21 -33
- data/test/data/cert/create.sh +0 -171
- data/test/data/cert/root-ca/certs/84E66B6F4C359E741C0AFA014790DF39.pem +0 -119
- data/test/data/cert/root-ca/certs/84E66B6F4C359E741C0AFA014790DF3A.pem +0 -125
- data/test/data/cert/root-ca/db/crlnumber +0 -1
- data/test/data/cert/root-ca/db/index +0 -2
- data/test/data/cert/root-ca/db/index.attr +0 -1
- data/test/data/cert/root-ca/db/index.attr.old +0 -1
- data/test/data/cert/root-ca/db/index.old +0 -1
- data/test/data/cert/root-ca/db/serial +0 -1
- data/test/data/cert/root-ca/db/serial.old +0 -1
- data/test/data/cert/root-ca/private/root-ca.key +0 -52
- data/test/data/cert/root-ca/root-ca.conf +0 -65
- data/test/data/cert/root-ca/root-ca.crt +0 -119
- data/test/data/cert/root-ca/root-ca.csr +0 -28
- data/test/data/cert/signature-1-pkcs7-detached.pdf +0 -182
- data/test/data/cert/sub-ca/certs/453FF080E3EDCD6A388D5368DFC320D9.pem +0 -125
- data/test/data/cert/sub-ca/db/crlnumber +0 -1
- data/test/data/cert/sub-ca/db/index +0 -1
- data/test/data/cert/sub-ca/db/index.attr +0 -1
- data/test/data/cert/sub-ca/db/index.old +0 -0
- data/test/data/cert/sub-ca/db/serial +0 -1
- data/test/data/cert/sub-ca/db/serial.old +0 -1
- data/test/data/cert/sub-ca/private/signing.key +0 -52
- data/test/data/cert/sub-ca/private/sub-ca.key +0 -52
- data/test/data/cert/sub-ca/signing.crt +0 -125
- data/test/data/cert/sub-ca/signing.csr +0 -28
- data/test/data/cert/sub-ca/signing.p12 +0 -0
- data/test/data/cert/sub-ca/sub-ca.conf +0 -65
- data/test/data/cert/sub-ca/sub-ca.crt +0 -125
- data/test/data/cert/sub-ca/sub-ca.csr +0 -28
@@ -0,0 +1,76 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'hexapdf/type/signature'
|
5
|
+
require 'time'
|
6
|
+
require 'ostruct'
|
7
|
+
|
8
|
+
describe HexaPDF::Type::Signature::Handler do
|
9
|
+
before do
|
10
|
+
@time = Time.parse("2021-11-14 7:00")
|
11
|
+
@dict = {Name: "handler", M: @time}
|
12
|
+
@handler = HexaPDF::Type::Signature::Handler.new(@dict)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns the signer name" do
|
16
|
+
assert_equal("handler", @handler.signer_name)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "returns the signing time" do
|
20
|
+
assert_equal(@time, @handler.signing_time)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "needs an implementation of certificate_chain" do
|
24
|
+
assert_raises(RuntimeError) { @handler.certificate_chain }
|
25
|
+
end
|
26
|
+
|
27
|
+
it "needs an implementation of signer_certificate" do
|
28
|
+
assert_raises(RuntimeError) { @handler.signer_certificate }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "store_verification_callback" do
|
32
|
+
before do
|
33
|
+
@result = HexaPDF::Type::Signature::VerificationResult.new
|
34
|
+
@context = OpenStruct.new
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can allow self-signed certificates" do
|
38
|
+
[OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN,
|
39
|
+
OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN].each do |error|
|
40
|
+
[true, false].each do |allow_self_signed|
|
41
|
+
@result.messages.clear
|
42
|
+
@context.error = error
|
43
|
+
@handler.store_verification_callback(@result, allow_self_signed: allow_self_signed).
|
44
|
+
call(false, @context)
|
45
|
+
assert_equal(1, @result.messages.size)
|
46
|
+
assert_match(/self-signed certificate/i, @result.messages[0].content)
|
47
|
+
assert_equal(allow_self_signed ? :info : :error, @result.messages[0].type)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "verifies the signing time" do
|
54
|
+
result = HexaPDF::Type::Signature::VerificationResult.new
|
55
|
+
[
|
56
|
+
[true, '6:00', '8:00'],
|
57
|
+
[false, '7:30', '8:00'],
|
58
|
+
[false, '5:00', '6:00'],
|
59
|
+
].each do |success, not_before, not_after|
|
60
|
+
result.messages.clear
|
61
|
+
@handler.define_singleton_method(:signer_certificate) do
|
62
|
+
OpenStruct.new.tap do |struct|
|
63
|
+
struct.not_before = Time.parse("2021-11-14 #{not_before}")
|
64
|
+
struct.not_after = Time.parse("2021-11-14 #{not_after}")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
@handler.send(:verify_signing_time, result)
|
68
|
+
if success
|
69
|
+
assert(result.messages.empty?)
|
70
|
+
else
|
71
|
+
assert_equal(1, result.messages.size)
|
72
|
+
end
|
73
|
+
@handler.singleton_class.remove_method(:signer_certificate)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'hexapdf/type/signature'
|
5
|
+
|
6
|
+
describe HexaPDF::Type::Signature::VerificationResult do
|
7
|
+
describe "Message" do
|
8
|
+
it "accepts a type and a content argument on creation" do
|
9
|
+
m = HexaPDF::Type::Signature::VerificationResult::Message.new(:type, 'content')
|
10
|
+
assert_equal(:type, m.type)
|
11
|
+
assert_equal('content', m.content)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "allows sorting by type" do
|
15
|
+
info = HexaPDF::Type::Signature::VerificationResult::Message.new(:info, 'c')
|
16
|
+
warning = HexaPDF::Type::Signature::VerificationResult::Message.new(:warning, 'c')
|
17
|
+
error = HexaPDF::Type::Signature::VerificationResult::Message.new(:error, 'c')
|
18
|
+
assert_equal([error, warning, info], [info, error, warning].sort)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
before do
|
23
|
+
@result = HexaPDF::Type::Signature::VerificationResult.new
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can add new messages" do
|
27
|
+
@result.log(:error, "content")
|
28
|
+
assert_equal(1, @result.messages.size)
|
29
|
+
assert_equal(:error, @result.messages[0].type)
|
30
|
+
assert_equal('content', @result.messages[0].content)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "reports success if no error messages have been logged" do
|
34
|
+
assert(@result.success?)
|
35
|
+
@result.log(:info, 'content')
|
36
|
+
assert(@result.success?)
|
37
|
+
@result.log(:error, 'failure')
|
38
|
+
refute(@result.success?)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "reports failure if there is at least one error message" do
|
42
|
+
@result.log(:info, 'content')
|
43
|
+
refute(@result.failure?)
|
44
|
+
@result.log(:error, 'failure')
|
45
|
+
assert(@result.failure?)
|
46
|
+
end
|
47
|
+
end
|
@@ -25,12 +25,33 @@ describe HexaPDF::Type::Annotation::AppearanceDictionary do
|
|
25
25
|
@ap.delete(:D)
|
26
26
|
assert_equal(:n, @ap.down_appearance)
|
27
27
|
end
|
28
|
+
|
29
|
+
describe "set_appearance" do
|
30
|
+
it "sets the appearance for the given type" do
|
31
|
+
@ap.set_appearance(1, type: :normal)
|
32
|
+
@ap.set_appearance(2, type: :rollover)
|
33
|
+
@ap.set_appearance(3, type: :down)
|
34
|
+
|
35
|
+
assert_equal(1, @ap.normal_appearance)
|
36
|
+
assert_equal(2, @ap.rollover_appearance)
|
37
|
+
assert_equal(3, @ap.down_appearance)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "respects the provided state name" do
|
41
|
+
@ap.set_appearance(1, state_name: :X)
|
42
|
+
assert_equal(1, @ap.normal_appearance[:X])
|
43
|
+
end
|
44
|
+
|
45
|
+
it "fails if an invalid appearance type is specified" do
|
46
|
+
assert_raises(ArgumentError) { @ap.set_appearance(5, type: :other) }
|
47
|
+
end
|
48
|
+
end
|
28
49
|
end
|
29
50
|
|
30
51
|
describe HexaPDF::Type::Annotation do
|
31
52
|
before do
|
32
53
|
@doc = HexaPDF::Document.new
|
33
|
-
@annot = @doc.add({Type: :Annot, F: 0b100011})
|
54
|
+
@annot = @doc.add({Type: :Annot, F: 0b100011, Rect: [10, 10, 110, 60]})
|
34
55
|
end
|
35
56
|
|
36
57
|
it "must always be indirect" do
|
@@ -66,7 +87,24 @@ describe HexaPDF::Type::Annotation do
|
|
66
87
|
assert_same(stream.data, @annot.appearance.data)
|
67
88
|
|
68
89
|
@annot[:AP][:D] = {X: stream}
|
69
|
-
assert_same(stream.data, @annot.appearance(:down).data)
|
90
|
+
assert_same(stream.data, @annot.appearance(type: :down).data)
|
91
|
+
assert_same(stream.data, @annot.appearance(type: :down, state_name: :X).data)
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "create_appearance" do
|
95
|
+
it "creates the appearance stream directly underneath /AP" do
|
96
|
+
stream = @annot.create_appearance
|
97
|
+
assert_same(stream, @annot.appearance_dict.normal_appearance)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "respects the state name when creating the appearance" do
|
101
|
+
stream = @annot.create_appearance(type: :down, state_name: :X)
|
102
|
+
assert_same(stream, @annot.appearance_dict.down_appearance[:X])
|
103
|
+
|
104
|
+
@annot[:AS] = :X
|
105
|
+
stream = @annot.create_appearance(type: :down)
|
106
|
+
assert_same(stream, @annot.appearance_dict.down_appearance[:X])
|
107
|
+
end
|
70
108
|
end
|
71
109
|
|
72
110
|
describe "flags" do
|
@@ -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(
|
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(
|
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(
|
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(
|
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(
|
71
|
+
assert_raises(RuntimeError) { @font.encoding }
|
72
72
|
end
|
73
73
|
|
74
74
|
it "returns a difference encoding if /Differences is specified" do
|
@@ -9,10 +9,25 @@ describe HexaPDF::Type::FontType3 do
|
|
9
9
|
@doc = HexaPDF::Document.new
|
10
10
|
@font = @doc.add({Type: :Font, Subtype: :Type3, Encoding: :WinAnsiEncoding,
|
11
11
|
FirstChar: 32, LastChar: 34, Widths: [600, 0, 700],
|
12
|
-
FontBBox: [0,
|
12
|
+
FontBBox: [0, 100, 100, 0], FontMatrix: [0.002, 0, 0, 0.002, 0, 0],
|
13
13
|
CharProcs: {}})
|
14
14
|
end
|
15
15
|
|
16
|
+
describe "bounding_box" do
|
17
|
+
it "returns the font's bounding box" do
|
18
|
+
assert_equal([0, 0, 100, 100], @font.bounding_box)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "inverts the y-values if necessary based on /FontMatrix" do
|
22
|
+
@font[:FontMatrix][3] *= -1
|
23
|
+
assert_equal([0, -100, 100, 0], @font.bounding_box)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns the glyph scaling factor" do
|
28
|
+
assert_equal(0.002, @font.glyph_scaling_factor)
|
29
|
+
end
|
30
|
+
|
16
31
|
describe "validation" do
|
17
32
|
it "works for valid objects" do
|
18
33
|
assert(@font.validate)
|
@@ -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.
|
4
|
+
version: 0.20.0
|
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-
|
11
|
+
date: 2021-12-30 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
|
@@ -434,36 +445,6 @@ files:
|
|
434
445
|
- test/data/aes-test-vectors/CBCVarTxt-192-encrypt.data.gz
|
435
446
|
- test/data/aes-test-vectors/CBCVarTxt-256-decrypt.data.gz
|
436
447
|
- test/data/aes-test-vectors/CBCVarTxt-256-encrypt.data.gz
|
437
|
-
- test/data/cert/create.sh
|
438
|
-
- test/data/cert/root-ca/certs/84E66B6F4C359E741C0AFA014790DF39.pem
|
439
|
-
- test/data/cert/root-ca/certs/84E66B6F4C359E741C0AFA014790DF3A.pem
|
440
|
-
- test/data/cert/root-ca/db/crlnumber
|
441
|
-
- test/data/cert/root-ca/db/index
|
442
|
-
- test/data/cert/root-ca/db/index.attr
|
443
|
-
- test/data/cert/root-ca/db/index.attr.old
|
444
|
-
- test/data/cert/root-ca/db/index.old
|
445
|
-
- test/data/cert/root-ca/db/serial
|
446
|
-
- test/data/cert/root-ca/db/serial.old
|
447
|
-
- test/data/cert/root-ca/private/root-ca.key
|
448
|
-
- test/data/cert/root-ca/root-ca.conf
|
449
|
-
- test/data/cert/root-ca/root-ca.crt
|
450
|
-
- test/data/cert/root-ca/root-ca.csr
|
451
|
-
- test/data/cert/signature-1-pkcs7-detached.pdf
|
452
|
-
- test/data/cert/sub-ca/certs/453FF080E3EDCD6A388D5368DFC320D9.pem
|
453
|
-
- test/data/cert/sub-ca/db/crlnumber
|
454
|
-
- test/data/cert/sub-ca/db/index
|
455
|
-
- test/data/cert/sub-ca/db/index.attr
|
456
|
-
- test/data/cert/sub-ca/db/index.old
|
457
|
-
- test/data/cert/sub-ca/db/serial
|
458
|
-
- test/data/cert/sub-ca/db/serial.old
|
459
|
-
- test/data/cert/sub-ca/private/signing.key
|
460
|
-
- test/data/cert/sub-ca/private/sub-ca.key
|
461
|
-
- test/data/cert/sub-ca/signing.crt
|
462
|
-
- test/data/cert/sub-ca/signing.csr
|
463
|
-
- test/data/cert/sub-ca/signing.p12
|
464
|
-
- test/data/cert/sub-ca/sub-ca.conf
|
465
|
-
- test/data/cert/sub-ca/sub-ca.crt
|
466
|
-
- test/data/cert/sub-ca/sub-ca.csr
|
467
448
|
- test/data/fonts/Ubuntu-Title.ttf
|
468
449
|
- test/data/images/cmyk.jpg
|
469
450
|
- test/data/images/fillbytes.jpg
|
@@ -527,6 +508,7 @@ files:
|
|
527
508
|
- test/hexapdf/document/test_fonts.rb
|
528
509
|
- test/hexapdf/document/test_images.rb
|
529
510
|
- test/hexapdf/document/test_pages.rb
|
511
|
+
- test/hexapdf/document/test_signatures.rb
|
530
512
|
- test/hexapdf/encryption/common.rb
|
531
513
|
- test/hexapdf/encryption/test_aes.rb
|
532
514
|
- test/hexapdf/encryption/test_arc4.rb
|
@@ -635,6 +617,11 @@ files:
|
|
635
617
|
- test/hexapdf/type/annotations/test_markup_annotation.rb
|
636
618
|
- test/hexapdf/type/annotations/test_text.rb
|
637
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
|
638
625
|
- test/hexapdf/type/test_annotation.rb
|
639
626
|
- test/hexapdf/type/test_catalog.rb
|
640
627
|
- test/hexapdf/type/test_cid_font.rb
|
@@ -653,6 +640,7 @@ files:
|
|
653
640
|
- test/hexapdf/type/test_page.rb
|
654
641
|
- test/hexapdf/type/test_page_tree_node.rb
|
655
642
|
- test/hexapdf/type/test_resources.rb
|
643
|
+
- test/hexapdf/type/test_signature.rb
|
656
644
|
- test/hexapdf/type/test_trailer.rb
|
657
645
|
- test/hexapdf/type/test_xref_stream.rb
|
658
646
|
- test/hexapdf/utils/test_bit_field.rb
|
@@ -683,7 +671,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
683
671
|
- !ruby/object:Gem::Version
|
684
672
|
version: '0'
|
685
673
|
requirements: []
|
686
|
-
rubygems_version: 3.2.
|
674
|
+
rubygems_version: 3.2.32
|
687
675
|
signing_key:
|
688
676
|
specification_version: 4
|
689
677
|
summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|