diff --git a/sign/helpers.go b/sign/helpers.go index 6084c75..48edb89 100644 --- a/sign/helpers.go +++ b/sign/helpers.go @@ -80,7 +80,10 @@ func leftPad(s string, padStr string, pLen int) string { } func writePartFromSourceFileToTargetFile(input_file io.ReadSeeker, output_file io.Writer, offset int64, length int64) error { - input_file.Seek(offset, 0) + _, err := input_file.Seek(offset, 0) + if err != nil { + return err + } // Create a small buffer for proper IO handling. max_chunk_length := int64(1024) diff --git a/sign/helpers_test.go b/sign/helpers_test.go index 22bc9ad..339c040 100644 --- a/sign/helpers_test.go +++ b/sign/helpers_test.go @@ -124,35 +124,35 @@ func TestWritePartFromSourceFileToTargetFile(t *testing.T) { return } - writePartFromSourceFileToTargetFile(input_file, writer, 0, 0) + _ = writePartFromSourceFileToTargetFile(input_file, writer, 0, 0) writer.Flush() if writer.Buffered() != 0 { t.Errorf("Content was copied while length was 0") } - writePartFromSourceFileToTargetFile(input_file, writer, 0, -20) + _ = writePartFromSourceFileToTargetFile(input_file, writer, 0, -20) writer.Flush() if writer.Buffered() != 0 { t.Errorf("Content was copied while length was smaller than 0") } - writePartFromSourceFileToTargetFile(input_file, writer, 0, 8) + _ = writePartFromSourceFileToTargetFile(input_file, writer, 0, 8) writer.Flush() - if string(b.Bytes()) != "%PDF-2.0" { - t.Errorf("Wrong content was copied, got %s but expected %s", string(b.Bytes()), "%PDF-2.0") + if b.String() != "%PDF-2.0" { + t.Errorf("Wrong content was copied, got %s but expected %s", b.String(), "%PDF-2.0") } - writePartFromSourceFileToTargetFile(input_file, writer, 33, 8) + _ = writePartFromSourceFileToTargetFile(input_file, writer, 33, 8) writer.Flush() - if string(b.Bytes()) != "%PDF-2.0/Catalog" { - t.Errorf("Wrong content was copied, got %s but expected %s", string(b.Bytes()), "%PDF-2.0/Catalog") + if b.String() != "%PDF-2.0/Catalog" { + t.Errorf("Wrong content was copied, got %s but expected %s", b.String(), "%PDF-2.0/Catalog") } - writePartFromSourceFileToTargetFile(input_file, writer, 0, 1200) + _ = writePartFromSourceFileToTargetFile(input_file, writer, 0, 1200) if writer.Buffered() != 1200 { t.Errorf("Requested 1200 bytes but only got %d", writer.Buffered()) diff --git a/sign/pdfbyterange.go b/sign/pdfbyterange.go index 2df939d..381b904 100644 --- a/sign/pdfbyterange.go +++ b/sign/pdfbyterange.go @@ -6,7 +6,9 @@ import ( ) func (context *SignContext) updateByteRange() error { - context.OutputBuffer.Seek(0, 0) + if _, err := context.OutputBuffer.Seek(0, 0); err != nil { + return err + } output_file_size := int64(context.OutputBuffer.Buff.Len()) // Calculate ByteRange values to replace them. @@ -29,17 +31,23 @@ func (context *SignContext) updateByteRange() error { // Make sure our ByteRange string didn't shrink in length. new_byte_range += strings.Repeat(" ", len(signatureByteRangePlaceholder)-len(new_byte_range)) - context.OutputBuffer.Seek(0, 0) + if _, err := context.OutputBuffer.Seek(0, 0); err != nil { + return err + } file_content := context.OutputBuffer.Buff.Bytes() - context.OutputBuffer.Write(file_content[:context.ByteRangeStartByte]) + if _, err := context.OutputBuffer.Write(file_content[:context.ByteRangeStartByte]); err != nil { + return err + } // Write new ByteRange. if _, err := context.OutputBuffer.Write([]byte(new_byte_range)); err != nil { return err } - context.OutputBuffer.Write(file_content[context.ByteRangeStartByte+int64(len(new_byte_range)):]) + if _, err := context.OutputBuffer.Write(file_content[context.ByteRangeStartByte+int64(len(new_byte_range)):]); err != nil { + return err + } return nil } diff --git a/sign/pdftrailer.go b/sign/pdftrailer.go index 7b8b6eb..b75fb46 100644 --- a/sign/pdftrailer.go +++ b/sign/pdftrailer.go @@ -11,7 +11,9 @@ func (context *SignContext) writeTrailer() error { trailer_length := context.PDFReader.XrefInformation.IncludingTrailerEndPos - context.PDFReader.XrefInformation.EndPos // Read the trailer so we can replace the size. - context.InputFile.Seek(context.PDFReader.XrefInformation.EndPos+1, 0) + if _, err := context.InputFile.Seek(context.PDFReader.XrefInformation.EndPos+1, 0); err != nil { + return err + } trailer_buf := make([]byte, trailer_length) if _, err := context.InputFile.Read(trailer_buf); err != nil { return err diff --git a/sign/pdfxref.go b/sign/pdfxref.go index 1a87919..9baa15b 100644 --- a/sign/pdfxref.go +++ b/sign/pdfxref.go @@ -84,8 +84,8 @@ func (context *SignContext) writeXrefStream() error { predictor := context.PDFReader.Trailer().Key("DecodeParms").Key("Predictor").Int64() - streamBytes := []byte{} - err := errors.New("") + var streamBytes []byte + var err error writeXrefStreamLine(buffer, 1, int(context.Filesize), 0) writeXrefStreamLine(buffer, 1, int(context.Filesize+context.VisualSignData.Length), 0) @@ -171,7 +171,9 @@ func EncodePNGSUBBytes(columns int, data []byte) ([]byte, error) { var b bytes.Buffer w := zlib.NewWriter(&b) - w.Write(data) + if _, err := w.Write(data); err != nil { + return nil, err + } w.Close() return b.Bytes(), nil @@ -209,7 +211,9 @@ func EncodePNGUPBytes(columns int, data []byte) ([]byte, error) { var b bytes.Buffer w := zlib.NewWriter(&b) - w.Write(data) + if _, err := w.Write(data); err != nil { + return nil, err + } w.Close() return b.Bytes(), nil diff --git a/sign/sign.go b/sign/sign.go index cd496e4..6c6aea9 100644 --- a/sign/sign.go +++ b/sign/sign.go @@ -4,6 +4,7 @@ import ( "crypto" "crypto/x509" "encoding/hex" + "fmt" "io" "os" "time" @@ -164,7 +165,10 @@ func (context *SignContext) SignPDF() error { context.OutputBuffer = filebuffer.New([]byte{}) // Copy old file into new file. - context.InputFile.Seek(0, 0) + _, err := context.InputFile.Seek(0, 0) + if err != nil { + return err + } if _, err := io.Copy(context.OutputBuffer, context.InputFile); err != nil { return err } @@ -182,26 +186,22 @@ func (context *SignContext) SignPDF() error { case "ECDSA-SHA1": case "DSA-SHA1": context.SignatureMaxLength += uint32(hex.EncodedLen(128)) - break case "SHA256-RSA": case "ECDSA-SHA256": case "DSA-SHA256": context.SignatureMaxLength += uint32(hex.EncodedLen(256)) - break case "SHA384-RSA": case "ECDSA-SHA384": context.SignatureMaxLength += uint32(hex.EncodedLen(384)) - break case "SHA512-RSA": case "ECDSA-SHA512": context.SignatureMaxLength += uint32(hex.EncodedLen(512)) - break } // Add size for my certificate. degenerated, err := pkcs7.DegenerateCertificate(context.SignData.Certificate.Raw) if err != nil { - return err + return fmt.Errorf("failed to degenerate certificate: %w", err) } context.SignatureMaxLength += uint32(hex.EncodedLen(len(degenerated))) @@ -216,7 +216,7 @@ func (context *SignContext) SignPDF() error { for _, cert := range certificate_chain { degenerated, err := pkcs7.DegenerateCertificate(cert.Raw) if err != nil { - return err + return fmt.Errorf("failed to degenerate certificate in chain: %w", err) } context.SignatureMaxLength += uint32(hex.EncodedLen(len(degenerated))) @@ -225,17 +225,22 @@ func (context *SignContext) SignPDF() error { // Add estimated size for TSA. // We can't kow actual size of TSA until after signing. + // + // Different TSA servers provide different response sizes, we + // might need to make this configurable or detect and store. if context.SignData.TSA.URL != "" { - context.SignatureMaxLength += uint32(hex.EncodedLen(6000)) + context.SignatureMaxLength += uint32(hex.EncodedLen(9000)) } // Fetch revocation data before adding signature placeholder. // Revocation data can be quite large and we need to create enough space in the placeholder. - context.fetchRevocationData() + if err := context.fetchRevocationData(); err != nil { + return fmt.Errorf("failed to fetch revocation data: %w", err) + } visual_signature, err := context.createVisualSignature() if err != nil { - return err + return fmt.Errorf("failed to create visual signature: %w", err) } context.VisualSignData.Length = int64(len(visual_signature)) @@ -247,14 +252,14 @@ func (context *SignContext) SignPDF() error { catalog, err := context.createCatalog() if err != nil { - return err + return fmt.Errorf("failed to create catalog: %w", err) } context.CatalogData.Length = int64(len(catalog)) // Write the new catalog object. if _, err := context.OutputBuffer.Write([]byte(catalog)); err != nil { - return err + return fmt.Errorf("failed to write catalog: %w", err) } // Create the signature object @@ -262,14 +267,14 @@ func (context *SignContext) SignPDF() error { info, err := context.createInfo() if err != nil { - return err + return fmt.Errorf("failed to create info: %w", err) } context.InfoData.Length = int64(len(info)) // Write the new catalog object. if _, err := context.OutputBuffer.Write([]byte(info)); err != nil { - return err + return fmt.Errorf("failed to write info: %w", err) } appended_bytes := context.Filesize + int64(len(catalog)) + int64(len(visual_signature)) + int64(len(info)) @@ -283,32 +288,36 @@ func (context *SignContext) SignPDF() error { // Write the new signature object. if _, err := context.OutputBuffer.Write([]byte(signature_object)); err != nil { - return err + return fmt.Errorf("failed to create the new signature object: %w", err) } // Calculate the new start position of the xref table. context.NewXrefStart = appended_bytes + int64(len(signature_object)) if err := context.writeXref(); err != nil { - return err + return fmt.Errorf("failed to write xref: %w", err) } if err := context.writeTrailer(); err != nil { - return err + return fmt.Errorf("failed to write trailer: %w", err) } if err := context.updateByteRange(); err != nil { - return err + return fmt.Errorf("failed to update byte range: %w", err) } if err := context.replaceSignature(); err != nil { - return err + return fmt.Errorf("failed to replace signature: %w", err) } - context.OutputBuffer.Seek(0, 0) + if _, err := context.OutputBuffer.Seek(0, 0); err != nil { + return err + } file_content := context.OutputBuffer.Buff.Bytes() - context.OutputFile.Write(file_content) + if _, err := context.OutputFile.Write(file_content); err != nil { + return fmt.Errorf("failed to write to output file: %w", err) + } return nil } diff --git a/sign/sign_test.go b/sign/sign_test.go index c48033c..a110c3c 100644 --- a/sign/sign_test.go +++ b/sign/sign_test.go @@ -65,7 +65,6 @@ func TestReaderCanReadPDF(t *testing.T) { for _, f := range files { ext := filepath.Ext(f.Name()) if ext != ".pdf" { - t.Log("Skipping file", f.Name()) continue } @@ -100,8 +99,8 @@ func TestReaderCanReadPDF(t *testing.T) { } func TestSignPDF(t *testing.T) { - os.RemoveAll("../testfiles/failed/") - os.MkdirAll("../testfiles/failed/", 0777) + _ = os.RemoveAll("../testfiles/failed/") + _ = os.MkdirAll("../testfiles/failed/", 0777) files, err := ioutil.ReadDir("../testfiles") if err != nil { @@ -140,7 +139,6 @@ func TestSignPDF(t *testing.T) { ext := filepath.Ext(f.Name()) if ext != ".pdf" { - t.Log("Skipping file", f.Name()) continue } @@ -171,6 +169,10 @@ func TestSignPDF(t *testing.T) { } outputFile, err := ioutil.TempFile("", "pdfsign_test") + if err != nil { + t.Errorf("%s", err.Error()) + return + } err = Sign(input_file, outputFile, rdr, size, SignData{ Signature: SignDataSignature{ @@ -196,7 +198,7 @@ func TestSignPDF(t *testing.T) { if err != nil { input_file.Close() - os.Remove(outputFile.Name()) + _ = os.Remove(outputFile.Name()) st.Errorf("%s: %s", f.Name(), err.Error()) return } @@ -244,6 +246,10 @@ func TestSignPDFFile(t *testing.T) { certificate_chains := make([][]*x509.Certificate, 0) tmpfile, err := ioutil.TempFile("", "pdfsign_test") + if err != nil { + t.Errorf("%s", err.Error()) + return + } err = SignFile("../testfiles/testfile20.pdf", tmpfile.Name(), SignData{ Signature: SignDataSignature{ @@ -322,7 +328,10 @@ func BenchmarkSignPDF(b *testing.B) { } for n := 0; n < b.N; n++ { - input_file.Seek(0, 0) + if _, err := input_file.Seek(0, 0); err != nil { + b.Errorf("%s: %s", "testfile20.pdf", err.Error()) + return + } err = Sign(input_file, ioutil.Discard, rdr, size, SignData{ Signature: SignDataSignature{ diff --git a/verify/verify.go b/verify/verify.go index b4d7f60..91d8e0a 100644 --- a/verify/verify.go +++ b/verify/verify.go @@ -71,7 +71,9 @@ type DocumentInfo struct { func File(file *os.File) (apiResp *Response, err error) { finfo, _ := file.Stat() - file.Seek(0, 0) + if _, err := file.Seek(0, 0); err != nil { + return nil, err + } return Reader(file, finfo.Size()) } @@ -155,9 +157,9 @@ func Reader(file io.ReaderAt, size int64) (apiResp *Response, err error) { // Signer certificate // http://www.alvestrand.no/objectid/1.2.840.113549.1.9.html // http://www.alvestrand.no/objectid/1.2.840.113583.1.1.8.html - var isn []byte + //var isn []byte for _, s := range p7.Signers { - isn = s.IssuerAndSerialNumber.IssuerName.FullBytes + //isn = s.IssuerAndSerialNumber.IssuerName.FullBytes //for _, a := range s.AuthenticatedAttributes { //fmt.Printf("A: %v, %#v\n", s.IssuerAndSerialNumber.SerialNumber, a.Type) //} @@ -199,13 +201,9 @@ func Reader(file io.ReaderAt, size int64) (apiResp *Response, err error) { } // Directory of certificates, including OCSP - //var ica *x509.Certificate certPool := x509.NewCertPool() for _, cert := range p7.Certificates { certPool.AddCert(cert) - if bytes.Equal(isn, cert.RawSubject) { - //ica = cert - } } // Verify the digital signature of the pdf file. @@ -225,7 +223,7 @@ func Reader(file io.ReaderAt, size int64) (apiResp *Response, err error) { // PDF signature certificate revocation information attribute (1.2.840.113583.1.1.8) var revInfo revocation.InfoArchival - p7.UnmarshalSignedAttribute(asn1.ObjectIdentifier{1, 2, 840, 113583, 1, 1, 8}, &revInfo) + _ = p7.UnmarshalSignedAttribute(asn1.ObjectIdentifier{1, 2, 840, 113583, 1, 1, 8}, &revInfo) // Parse OCSP response var ocspStatus = make(map[string]*ocsp.Response)