Skip to content

signature dictionary "Contents" must not be encrypted #794

@fancycode

Description

@fancycode

For signature fields in encrypted documents, all entries in the /Sig dictionary are currently kept encrypted:

pdfcpu/pkg/pdfcpu/crypto.go

Lines 1199 to 1200 in 793c509

if ftv, ok := ft.(types.Name); ok && ftv == "Sig" {
return nil

According to the PDF specification, only the /Contents entry must be kept as-is. All other fields must be decrypted.

See "7.6.2 Application of encryption":

Encryption applies to all strings and streams in the document's PDF file, with the following exceptions:
• The values for the ID entry in the trailer
• Any strings in an Encrypt dictionary
• Any strings that are inside streams such as content streams and compressed object streams, which
themselves are encrypted
• Any hexadecimal strings representing the value of the Contents key in a Signature dictionary

Simple patch:

diff --git a/pkg/pdfcpu/crypto.go b/pkg/pdfcpu/crypto.go
index 7412bfd..8a56549 100644
--- a/pkg/pdfcpu/crypto.go
+++ b/pkg/pdfcpu/crypto.go
@@ -1191,16 +1191,20 @@ func encryptDeepObject(objIn types.Object, objNr, genNr int, key []byte, needAES
 }
 
 func decryptDict(d types.Dict, objNr, genNr int, key []byte, needAES bool, r int) error {
+       isSignature := false
        ft := d["FT"]
        if ft == nil {
                ft = d["Type"]
        }
        if ft != nil {
                if ftv, ok := ft.(types.Name); ok && ftv == "Sig" {
-                       return nil
+                       isSignature = true
                }
        }
        for k, v := range d {
+               if isSignature && k == "Contents" {
+                       continue
+               }
                s, err := decryptDeepObject(v, objNr, genNr, key, needAES, r)
                if err != nil {
                        return err

I'm happy to provide this as MR if interested.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions