From 657fe00a78f9dc94740fd55b630c662103ed969c Mon Sep 17 00:00:00 2001 From: Adrian-George Bostan Date: Thu, 21 Feb 2019 00:20:47 +0200 Subject: [PATCH] Fix signature validation --- pdf/annotator/form_field.go | 23 ++++++++++------------- pdf/model/appender.go | 13 +++---------- pdf/model/appender_test.go | 18 ++++++++++++++++++ pdf/model/fields.go | 21 ++++++++++++++------- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/pdf/annotator/form_field.go b/pdf/annotator/form_field.go index 8fecc2fc..179c58a8 100644 --- a/pdf/annotator/form_field.go +++ b/pdf/annotator/form_field.go @@ -249,21 +249,15 @@ func NewSignatureField(signature *model.PdfSignature, fields []*SignatureLine, o return nil, errors.New("signature cannot be nil") } - field := model.NewPdfFieldSignature(signature) - field.T = core.MakeString("") - apDict, err := genFieldSignatureAppearance(fields, opts) if err != nil { return nil, err } - widget := model.NewPdfAnnotationWidget() - widget.Rect = core.MakeArrayFromFloats(opts.Rect) - widget.F = core.MakeInteger(4) - widget.Parent = field.ToPdfObject() - widget.AP = apDict - - field.Annotations = append(field.Annotations, widget) + field := model.NewPdfFieldSignature(signature) + field.Rect = core.MakeArrayFromFloats(opts.Rect) + field.F = core.MakeInteger(132) + field.AP = apDict return field, nil } @@ -380,10 +374,13 @@ func genFieldSignatureAppearance(fields []*SignatureLine, opts *SignatureFieldOp opts.FillColor = model.NewPdfColorDeviceGray(1) } - cc.Add_q().Add_re(rect[0], rect[1], rectWidth, rectHeight). - Add_w(opts.BorderSize).SetStrokingColor(opts.BorderColor). + cc.Add_q(). + Add_re(rect[0], rect[1], rectWidth, rectHeight). + Add_w(opts.BorderSize). + SetStrokingColor(opts.BorderColor). SetNonStrokingColor(opts.FillColor). - Add_B().Add_Q() + Add_B(). + Add_Q() // Draw signature. cc.Add_q() diff --git a/pdf/model/appender.go b/pdf/model/appender.go index 70b05974..2ec60621 100644 --- a/pdf/model/appender.go +++ b/pdf/model/appender.go @@ -394,6 +394,7 @@ func (a *PdfAppender) Sign(pageNum int, field *PdfFieldSignature) error { if signature == nil { return errors.New("signature dictionary cannot be nil") } + a.addNewObjects(signature.container) // Get a copy of the selected page. pageIndex := pageNum - 1 @@ -402,17 +403,9 @@ func (a *PdfAppender) Sign(pageNum int, field *PdfFieldSignature) error { } page := a.pages[pageIndex].Duplicate() - // Initialize signature. - if err := signature.Initialize(); err != nil { - return err - } - a.addNewObjects(signature.container) - // Add signature field annotations to the page annotations. - for _, annotation := range field.Annotations { - annotation.P = page.ToPdfObject() - page.Annotations = append(page.Annotations, annotation.PdfAnnotation) - } + field.P = page.ToPdfObject() + page.Annotations = append(page.Annotations, field.PdfAnnotationWidget.PdfAnnotation) // Add signature field to the form. acroForm := a.Reader.AcroForm diff --git a/pdf/model/appender_test.go b/pdf/model/appender_test.go index f41d68fa..8bb4c564 100644 --- a/pdf/model/appender_test.go +++ b/pdf/model/appender_test.go @@ -457,6 +457,10 @@ func TestAppenderSignPage4(t *testing.T) { signature.SetReason("TestAppenderSignPage4") signature.SetDate(time.Now(), "") + if err := signature.Initialize(); err != nil { + return + } + sigField := model.NewPdfFieldSignature(signature) sigField.T = core.MakeString("Signature1") @@ -541,6 +545,10 @@ func TestAppenderSignMultiple(t *testing.T) { signature.SetReason("TestAppenderSignPage4") signature.SetDate(time.Now(), "") + if err := signature.Initialize(); err != nil { + return + } + sigField := model.NewPdfFieldSignature(signature) sigField.T = core.MakeString("Signature1") @@ -619,6 +627,10 @@ func TestSignatureAppearance(t *testing.T) { signature.SetReason("TestSignatureAppearance Reason") signature.SetDate(time.Now(), "") + if err := signature.Initialize(); err != nil { + return + } + numPages, err := pdfReader.GetNumPages() if err != nil { t.Errorf("Fail: %v\n", err) @@ -644,6 +656,8 @@ func TestSignatureAppearance(t *testing.T) { }, opts, ) + sigField.T = core.MakeString(fmt.Sprintf("Signature %d", pageNum)) + sigField.F = core.MakeInteger(132) if err = appender.Sign(pageNum, sigField); err != nil { t.Errorf("Fail: %v\n", err) @@ -667,6 +681,8 @@ func TestSignatureAppearance(t *testing.T) { }, opts, ) + sigField.T = core.MakeString(fmt.Sprintf("Signature2 %d", pageNum)) + sigField.F = core.MakeInteger(132) if err = appender.Sign(pageNum, sigField); err != nil { log.Fatalf("Fail: %v\n", err) @@ -691,6 +707,8 @@ func TestSignatureAppearance(t *testing.T) { }, opts, ) + sigField.T = core.MakeString(fmt.Sprintf("Signature3 %d", pageNum)) + sigField.F = core.MakeInteger(132) if err = appender.Sign(pageNum, sigField); err != nil { log.Fatalf("Fail: %v\n", err) diff --git a/pdf/model/fields.go b/pdf/model/fields.go index 70b2dac2..69f0cebb 100644 --- a/pdf/model/fields.go +++ b/pdf/model/fields.go @@ -433,6 +433,7 @@ func (ch *PdfFieldChoice) ToPdfObject() core.PdfObject { // the name of the signer and verifying document contents. type PdfFieldSignature struct { *PdfField + *PdfAnnotationWidget V *PdfSignature Lock *core.PdfIndirectObject @@ -441,22 +442,28 @@ type PdfFieldSignature struct { // NewPdfFieldSignature returns an initialized signature field. func NewPdfFieldSignature(signature *PdfSignature) *PdfFieldSignature { - field := &PdfFieldSignature{ - PdfField: NewPdfField(), - V: signature, - } + field := &PdfFieldSignature{} + field.PdfField = NewPdfField() field.PdfField.SetContext(field) - field.FT = core.MakeName("Sig") + field.PdfAnnotationWidget = NewPdfAnnotationWidget() + field.PdfAnnotationWidget.SetContext(field) + field.PdfAnnotationWidget.container = field.PdfField.container + + field.T = core.MakeString("") + field.V = signature return field } // ToPdfObject returns an indirect object containing the signature field dictionary. func (sig *PdfFieldSignature) ToPdfObject() core.PdfObject { - // Set general field attributes + // Set general field attributes. + if sig.PdfAnnotationWidget != nil { + sig.PdfAnnotationWidget.ToPdfObject() + } sig.PdfField.ToPdfObject() - // Handle signature field specific attributes + // Handle signature field specific attributes. container := sig.container d := container.PdfObject.(*core.PdfObjectDictionary)