mirror of
https://github.com/docusealco/docuseal
synced 2026-11-10 15:42:32 -05:00
only dss changes
This commit is contained in:
1 parent
5432978c0d
commit
d578ca3cc9
3 files changed
+39
-36
No files matched your search
+3
-3
@@ -9,10 +9,10 @@ RUN apk --no-cache add wget unzip && \
|
|||||||
wget https://raw.githubusercontent.com/impallari/DancingScript/master/OFL.txt && \
|
wget https://raw.githubusercontent.com/impallari/DancingScript/master/OFL.txt && \
|
||||||
wget https://raw.githubusercontent.com/notofonts/noto-fonts/refs/heads/main/LICENSE && \
|
wget https://raw.githubusercontent.com/notofonts/noto-fonts/refs/heads/main/LICENSE && \
|
||||||
wget -O /model.onnx "https://github.com/docusealco/fields-detection/releases/download/2.0.0/model_704_int8.onnx" && \
|
wget -O /model.onnx "https://github.com/docusealco/fields-detection/releases/download/2.0.0/model_704_int8.onnx" && \
|
||||||
wget -O pdfium-linux.zip "https://github.com/docusealco/pdfium-binaries/releases/download/20260813/pdfium-musl-$(uname -m).zip" && \
|
wget -O pdfium-linux.zip "https://github.com/docusealco/pdfium-binaries/releases/download/20260920/pdfium-musl-$(uname -m).zip" && \
|
||||||
case "$(uname -m)" in \
|
case "$(uname -m)" in \
|
||||||
x86_64) echo "c5c7dde243ecb66ab0819c8193515ef38ad53549fe260f3c2dfd93ea56eda2e7 pdfium-linux.zip" ;; \
|
x86_64) echo "bbca8a648dbd1ba81f9c6c223f21dc394cf1ad381c6c17d60c6dcc4a7d3a2ae0 pdfium-linux.zip" ;; \
|
||||||
aarch64) echo "64c4483449b1b4dccc696ad0c5c96e0b7f74dcc57b4f23c676b7a70671b0bbb5 pdfium-linux.zip" ;; \
|
aarch64) echo "73b72ed79b9bfdd494dee7e863482c24971a8d4b11f6cd1289aa170d31304a1f pdfium-linux.zip" ;; \
|
||||||
esac | sha256sum -c - && \
|
esac | sha256sum -c - && \
|
||||||
mkdir -p /pdfium-linux && \
|
mkdir -p /pdfium-linux && \
|
||||||
unzip -q pdfium-linux.zip -d /pdfium-linux
|
unzip -q pdfium-linux.zip -d /pdfium-linux
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ class Pdfium
|
|||||||
attach_function :FPDF_GetLastError, [], :ulong
|
attach_function :FPDF_GetLastError, [], :ulong
|
||||||
attach_function :FPDF_GetTrailerEnds, %i[FPDF_DOCUMENT pointer ulong], :ulong
|
attach_function :FPDF_GetTrailerEnds, %i[FPDF_DOCUMENT pointer ulong], :ulong
|
||||||
attach_function :FPDF_DocumentHasValidCrossReferenceTable, [:FPDF_DOCUMENT], :int
|
attach_function :FPDF_DocumentHasValidCrossReferenceTable, [:FPDF_DOCUMENT], :int
|
||||||
|
attach_function :FPDF_HasOnlyDSSChanges, %i[FPDF_DOCUMENT FPDF_DOCUMENT], :int
|
||||||
attach_function :FPDF_GetSecurityHandlerRevision, [:FPDF_DOCUMENT], :int
|
attach_function :FPDF_GetSecurityHandlerRevision, [:FPDF_DOCUMENT], :int
|
||||||
attach_function :FPDF_GetFormType, [:FPDF_DOCUMENT], :int
|
attach_function :FPDF_GetFormType, [:FPDF_DOCUMENT], :int
|
||||||
|
|
||||||
@@ -775,6 +776,10 @@ class Pdfium
|
|||||||
Pdfium.FPDF_DocumentHasValidCrossReferenceTable(@document_ptr) == 1
|
Pdfium.FPDF_DocumentHasValidCrossReferenceTable(@document_ptr) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def only_dss_changes?(signed_document)
|
||||||
|
Pdfium.FPDF_HasOnlyDSSChanges(@document_ptr, signed_document.document_ptr) == 1
|
||||||
|
end
|
||||||
|
|
||||||
def annot_count(page_index)
|
def annot_count(page_index)
|
||||||
@annot_counts[page_index] ||= Pdfium.FPDFPage_GetAnnotCountRaw(@document_ptr, page_index)
|
@annot_counts[page_index] ||= Pdfium.FPDFPage_GetAnnotCountRaw(@document_ptr, page_index)
|
||||||
end
|
end
|
||||||
|
|||||||
+31
-33
@@ -10,20 +10,22 @@ module VerifyPdfSignature
|
|||||||
module_function
|
module_function
|
||||||
|
|
||||||
def call(io, trusted_certs)
|
def call(io, trusted_certs)
|
||||||
Pdfium::Document.open_io(io) do |document|
|
Pdfium.with_instance do
|
||||||
signatures = document.signatures.select { |e| e.byte_range.any?(&:positive?) && e.contents.present? }
|
Pdfium::Document.open_io(io) do |document|
|
||||||
|
signatures = document.signatures.select { |e| e.byte_range.any?(&:positive?) && e.contents.present? }
|
||||||
|
|
||||||
next [] if signatures.blank?
|
next [] if signatures.blank?
|
||||||
|
|
||||||
verified_signatures = signatures.select { |e| verified_signature?(e, io, trusted_certs) }
|
verified_signatures = signatures.select { |e| verified_signature?(e, io, trusted_certs) }
|
||||||
trusted_signatures = verified_signatures.select { |e| trusted_signature?(e, trusted_certs) }
|
trusted_signatures = verified_signatures.select { |e| trusted_signature?(e, trusted_certs) }
|
||||||
last_signature = (trusted_signatures.presence || verified_signatures).max_by(&:signed_end)
|
last_signature = (trusted_signatures.presence || verified_signatures).max_by(&:signed_end)
|
||||||
has_unsigned_changes = last_signature && unsigned_changes?(document, io, last_signature.signed_end)
|
has_unsigned_changes = last_signature && unsigned_changes?(document, io, last_signature.signed_end)
|
||||||
|
|
||||||
signatures.map do |signature|
|
signatures.map do |signature|
|
||||||
build_signature(signature, trusted_certs,
|
build_signature(signature, trusted_certs,
|
||||||
verified: verified_signatures.include?(signature),
|
verified: verified_signatures.include?(signature),
|
||||||
has_unsigned_changes: has_unsigned_changes && signature == last_signature)
|
has_unsigned_changes: has_unsigned_changes && signature == last_signature)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -31,11 +33,26 @@ module VerifyPdfSignature
|
|||||||
def verified_signature?(signature, io, trusted_certs)
|
def verified_signature?(signature, io, trusted_certs)
|
||||||
return false unless covers_signed_revision?(signature, io)
|
return false unless covers_signed_revision?(signature, io)
|
||||||
|
|
||||||
verify_contents(OpenSSL::PKCS7.new(signature.contents), signed_data(io, signature.byte_range), trusted_certs)
|
pkcs7 = OpenSSL::PKCS7.new(signature.contents)
|
||||||
rescue OpenSSL::PKCS7::PKCS7Error
|
|
||||||
|
if signature.sub_filter == 'ETSI.RFC3161'
|
||||||
|
verify_timestamp(pkcs7, signed_data(io, signature.byte_range))
|
||||||
|
else
|
||||||
|
verify_contents(pkcs7, signed_data(io, signature.byte_range), trusted_certs)
|
||||||
|
end
|
||||||
|
rescue OpenSSL::PKCS7::PKCS7Error, OpenSSL::Timestamp::TimestampError
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def verify_timestamp(pkcs7, signed_data)
|
||||||
|
return false unless pkcs7.verify(pkcs7.certificates, OpenSSL::X509::Store.new, nil,
|
||||||
|
OpenSSL::PKCS7::NOVERIFY | OpenSSL::PKCS7::BINARY)
|
||||||
|
|
||||||
|
token_info = OpenSSL::Timestamp::TokenInfo.new(pkcs7.data)
|
||||||
|
|
||||||
|
token_info.message_imprint == OpenSSL::Digest.digest(token_info.algorithm, signed_data)
|
||||||
|
end
|
||||||
|
|
||||||
def build_signature(signature, trusted_certs, verified:, has_unsigned_changes:)
|
def build_signature(signature, trusted_certs, verified:, has_unsigned_changes:)
|
||||||
pkcs7 = OpenSSL::PKCS7.new(signature.contents)
|
pkcs7 = OpenSSL::PKCS7.new(signature.contents)
|
||||||
|
|
||||||
@@ -173,29 +190,10 @@ module VerifyPdfSignature
|
|||||||
io.seek(0)
|
io.seek(0)
|
||||||
|
|
||||||
Pdfium::Document.open_bytes(io.read(signed_end)) do |signed_document|
|
Pdfium::Document.open_bytes(io.read(signed_end)) do |signed_document|
|
||||||
next true unless signed_document.valid_cross_reference_table?
|
!document.only_dss_changes?(signed_document)
|
||||||
|
|
||||||
serialized_document(signed_document) != serialized_document(document)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def serialized_document(document)
|
|
||||||
pages = (0...document.page_count).map do |index|
|
|
||||||
page = document.get_page(index)
|
|
||||||
objects = page.objects.map { |object| [*object.to_a, image_digest(page, object)] }
|
|
||||||
|
|
||||||
[page.rotation, objects, page.annotations, page.text]
|
|
||||||
end
|
|
||||||
|
|
||||||
[pages, document.bookmarks]
|
|
||||||
end
|
|
||||||
|
|
||||||
def image_digest(page, object)
|
|
||||||
return unless object.image?
|
|
||||||
|
|
||||||
Digest::SHA256.hexdigest(page.extract_image_bitmap(object.object_ptr)[:data])
|
|
||||||
end
|
|
||||||
|
|
||||||
def signed_data(io, byte_range)
|
def signed_data(io, byte_range)
|
||||||
byte_range.each_slice(2).map do |offset, length|
|
byte_range.each_slice(2).map do |offset, length|
|
||||||
io.seek(offset)
|
io.seek(offset)
|
||||||
|
|||||||
Reference in new issue
Block a user