rubrik 0.2.1 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9faab13628886a83554fb2dd75b71d7315701da037377bb70d7aba3e9769ffe
4
- data.tar.gz: 90fbf56ed6afbd1ab7b54ad4290800ad079fd4b600eb4334f2974a248b2631c9
3
+ metadata.gz: a28dfceafc9ceb57e6b2a30f82b6e8ca237c8ce3381a05d6793568154775c43a
4
+ data.tar.gz: 1a0a6f8b8079396583cdf27fae2638a9f24c16f0483c830d54a805dc707982f5
5
5
  SHA512:
6
- metadata.gz: 3a83c73ca910d0ce84298c65d7f704ed93ccd3104bb44f1d70331b82bdcdecae1355fb2b5a0b8177a9954b3c39394153cbb521cf67ec4d4a677fc98684c90f5e
7
- data.tar.gz: 0da9fd89c054a40db22642cfb4b390be64fb49c12b42f449d901c898b86bcd10d4f8e72892ecfc59618aca1678f115165209a41497315c3b2f1cde8d29882194
6
+ metadata.gz: 4b294ed919bade9e09eef834afb47a17f65928b40099a9add84f079df46102e852a7289c7fbacbb745b67929ae14098fc002ebd2b12987a921e4461b5996a406
7
+ data.tar.gz: 283e213a97967fb54d4c2b21f2ab009e96c434a93b26f3ff34ee4f75cfdcd925bd5cbc633bcb22844822ed4eb2e36efa4158f33b40f633b5ade6af7c9d97d30a
data/README.md CHANGED
@@ -52,14 +52,14 @@ input_pdf = File.open("example.pdf", "rb")
52
52
  output_pdf = File.open("signed_example.pdf", "wb+") # needs read permission
53
53
 
54
54
  # Load Certificate(s)
55
- certificate = File.open("example_cert.pem", "rb")
56
- private_key = OpenSSL::PKey::RSA.new(certificate, "")
57
- certificate.rewind
58
- public_key = OpenSSL::X509::Certificate.new(certificate)
59
- certificate.close
55
+ certificate_file = File.open("example_cert.pem", "rb")
56
+ private_key = OpenSSL::PKey::RSA.new(certificate_file, "")
57
+ certificate_file.rewind
58
+ certificate = OpenSSL::X509::Certificate.new(certificate_file)
59
+ certificate_file.close
60
60
 
61
61
  # Will write the signed document to `output_pdf`
62
- Rubrik::Sign.call(input_pdf, output_pdf, private_key:, public_key:, certificate_chain: [])
62
+ Rubrik::Sign.call(input_pdf, output_pdf, private_key:, certificate:, certificate_chain: [])
63
63
 
64
64
  # Don't forget to close the files
65
65
  input_pdf.close
@@ -46,11 +46,11 @@ module Rubrik
46
46
  io << "#{starting_id} #{length}\n"
47
47
 
48
48
  if starting_id.zero?
49
- io << "0000000000 65535 f\n"
49
+ io << "#{format("%010d", document.first_free_object_id)} 65535 f \n"
50
50
  subsection.shift
51
51
  end
52
52
 
53
- subsection.each { |entry| io << "#{format("%010d", entry[:offset])} 00000 n\n" }
53
+ subsection.each { |entry| io << "#{format("%010d", entry[:offset])} 00000 n \n" }
54
54
  end
55
55
 
56
56
  io << "trailer\n"
@@ -17,19 +17,25 @@ module Rubrik
17
17
  sig {returns(PDF::Reader::ObjectHash)}
18
18
  attr_accessor :objects
19
19
 
20
+ sig {returns(Integer)}
21
+ attr_accessor :first_free_object_id
22
+
20
23
  sig {returns(T::Array[{id: PDF::Reader::Reference, value: T.untyped}])}
21
24
  attr_accessor :modified_objects
22
25
 
23
26
  sig {returns(Integer)}
24
27
  attr_accessor :last_object_id
25
28
 
26
- private :io=, :objects=, :modified_objects=, :last_object_id=
29
+ private :io=, :objects=, :first_free_object_id=, :modified_objects=, :last_object_id=
27
30
 
28
31
  sig {params(input: T.any(File, Tempfile, StringIO)).void}
29
32
  def initialize(input)
30
33
  self.io = input
31
34
  self.objects = PDF::Reader::ObjectHash.new(input)
32
- self.last_object_id = objects.size
35
+
36
+ self.last_object_id = objects.trailer[:Size] - 1
37
+ self.first_free_object_id = find_first_free_object_id
38
+
33
39
  self.modified_objects = []
34
40
 
35
41
  fetch_or_create_interactive_form!
@@ -87,6 +93,16 @@ module Rubrik
87
93
  T.must(modified_objects.first).fetch(:value)
88
94
  end
89
95
 
96
+ sig{returns(Integer)}
97
+ def find_first_free_object_id
98
+ return 0 if last_object_id == objects.size
99
+
100
+ xref = objects.send(:xref).instance_variable_get(:@xref)
101
+ missing_ids = (1..last_object_id).to_a - xref.keys
102
+
103
+ T.must(missing_ids.min)
104
+ end
105
+
90
106
  sig {void}
91
107
  def fetch_or_create_interactive_form!
92
108
  root_ref = objects.trailer[:Root]
@@ -1,8 +1,6 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
- require "openssl"
5
-
6
4
  module Rubrik
7
5
  module FillSignature
8
6
  extend T::Sig
@@ -13,13 +11,13 @@ module Rubrik
13
11
  io: T.any(File, StringIO, Tempfile),
14
12
  signature_value_ref: PDF::Reader::Reference,
15
13
  private_key: OpenSSL::PKey::RSA,
16
- public_key: OpenSSL::X509::Certificate,
14
+ certificate: OpenSSL::X509::Certificate,
17
15
  certificate_chain: T::Array[OpenSSL::X509::Certificate])
18
16
  .void}
19
17
 
20
18
  FIRST_OFFSET = 0
21
19
 
22
- def call(io, signature_value_ref:, private_key:, public_key:, certificate_chain: [])
20
+ def call(io, signature_value_ref:, private_key:, certificate:, certificate_chain: [])
23
21
  io.rewind
24
22
 
25
23
  signature_value_offset = PDF::Reader::XRef.new(io)[signature_value_ref]
@@ -55,8 +53,7 @@ module Rubrik
55
53
  io.pos = second_offset
56
54
  data_to_sign += T.must(io.read(second_length))
57
55
 
58
- signature = OpenSSL::PKCS7.sign(public_key, private_key, data_to_sign, certificate_chain,
59
- OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY).to_der
56
+ signature = PKCS7Signature.call(data_to_sign, private_key:, certificate:)
60
57
  hex_signature = T.let(signature, String).unpack1("H*")
61
58
 
62
59
  padded_contents_field = "<#{hex_signature.ljust(Document::SIGNATURE_SIZE, "0")}>"
@@ -0,0 +1,24 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require "openssl"
5
+
6
+ module Rubrik
7
+ module PKCS7Signature
8
+ extend T::Sig
9
+ extend self
10
+
11
+ OPEN_SSL_FLAGS = OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY
12
+
13
+ sig {params(
14
+ data: String,
15
+ private_key: OpenSSL::PKey::RSA,
16
+ certificate: OpenSSL::X509::Certificate,
17
+ certificate_chain: T::Array[OpenSSL::X509::Certificate]
18
+ ).returns(String)
19
+ }
20
+ def call(data, private_key:, certificate:, certificate_chain: [])
21
+ OpenSSL::PKCS7.sign(certificate, private_key, data, certificate_chain, OPEN_SSL_FLAGS).to_der
22
+ end
23
+ end
24
+ end
data/lib/rubrik/sign.rb CHANGED
@@ -9,10 +9,10 @@ module Rubrik
9
9
  input: T.any(File, Tempfile, StringIO),
10
10
  output: T.any(File, Tempfile, StringIO),
11
11
  private_key: OpenSSL::PKey::RSA,
12
- public_key: OpenSSL::X509::Certificate,
12
+ certificate: OpenSSL::X509::Certificate,
13
13
  certificate_chain: T::Array[OpenSSL::X509::Certificate])
14
14
  .void}
15
- def self.call(input, output, private_key:, public_key:, certificate_chain: [])
15
+ def self.call(input, output, private_key:, certificate:, certificate_chain: [])
16
16
  input.binmode
17
17
  output.reopen(T.unsafe(output), "wb+") if !output.is_a?(StringIO)
18
18
 
@@ -22,7 +22,7 @@ module Rubrik
22
22
 
23
23
  Document::Increment.call(document, io: output)
24
24
 
25
- FillSignature.call(output, signature_value_ref:, private_key:, public_key:, certificate_chain:)
25
+ FillSignature.call(output, signature_value_ref:, private_key:, certificate:, certificate_chain:)
26
26
  end
27
27
  end
28
28
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rubrik
4
- VERSION = "0.2.1"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/rubrik.rb CHANGED
@@ -12,4 +12,5 @@ require_relative "rubrik/document"
12
12
  require_relative "rubrik/document/increment"
13
13
  require_relative "rubrik/document/serialize_object"
14
14
  require_relative "rubrik/fill_signature"
15
+ require_relative "rubrik/pkcs7_signature"
15
16
  require_relative "rubrik/sign"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubrik
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomás Coêlho
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-20 00:00:00.000000000 Z
11
+ date: 2023-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pdf-reader
@@ -66,6 +66,7 @@ files:
66
66
  - lib/rubrik/document/increment.rb
67
67
  - lib/rubrik/document/serialize_object.rb
68
68
  - lib/rubrik/fill_signature.rb
69
+ - lib/rubrik/pkcs7_signature.rb
69
70
  - lib/rubrik/sign.rb
70
71
  - lib/rubrik/version.rb
71
72
  homepage: https://github.com/tomascco/rubrik