Check errors

This commit is contained in:
Paul van Brouwershaven
2022-06-30 18:04:25 +02:00
parent 0e77069efa
commit 44ac3c7806
8 changed files with 87 additions and 54 deletions

View File

@@ -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 { 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. // Create a small buffer for proper IO handling.
max_chunk_length := int64(1024) max_chunk_length := int64(1024)

View File

@@ -124,35 +124,35 @@ func TestWritePartFromSourceFileToTargetFile(t *testing.T) {
return return
} }
writePartFromSourceFileToTargetFile(input_file, writer, 0, 0) _ = writePartFromSourceFileToTargetFile(input_file, writer, 0, 0)
writer.Flush() writer.Flush()
if writer.Buffered() != 0 { if writer.Buffered() != 0 {
t.Errorf("Content was copied while length was 0") t.Errorf("Content was copied while length was 0")
} }
writePartFromSourceFileToTargetFile(input_file, writer, 0, -20) _ = writePartFromSourceFileToTargetFile(input_file, writer, 0, -20)
writer.Flush() writer.Flush()
if writer.Buffered() != 0 { if writer.Buffered() != 0 {
t.Errorf("Content was copied while length was smaller than 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() writer.Flush()
if string(b.Bytes()) != "%PDF-2.0" { if b.String() != "%PDF-2.0" {
t.Errorf("Wrong content was copied, got %s but expected %s", string(b.Bytes()), "%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() writer.Flush()
if 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", string(b.Bytes()), "%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 { if writer.Buffered() != 1200 {
t.Errorf("Requested 1200 bytes but only got %d", writer.Buffered()) t.Errorf("Requested 1200 bytes but only got %d", writer.Buffered())

View File

@@ -6,7 +6,9 @@ import (
) )
func (context *SignContext) updateByteRange() error { 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()) output_file_size := int64(context.OutputBuffer.Buff.Len())
// Calculate ByteRange values to replace them. // 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. // Make sure our ByteRange string didn't shrink in length.
new_byte_range += strings.Repeat(" ", len(signatureByteRangePlaceholder)-len(new_byte_range)) 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() 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. // Write new ByteRange.
if _, err := context.OutputBuffer.Write([]byte(new_byte_range)); err != nil { if _, err := context.OutputBuffer.Write([]byte(new_byte_range)); err != nil {
return err 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 return nil
} }

View File

@@ -11,7 +11,9 @@ func (context *SignContext) writeTrailer() error {
trailer_length := context.PDFReader.XrefInformation.IncludingTrailerEndPos - context.PDFReader.XrefInformation.EndPos trailer_length := context.PDFReader.XrefInformation.IncludingTrailerEndPos - context.PDFReader.XrefInformation.EndPos
// Read the trailer so we can replace the size. // 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) trailer_buf := make([]byte, trailer_length)
if _, err := context.InputFile.Read(trailer_buf); err != nil { if _, err := context.InputFile.Read(trailer_buf); err != nil {
return err return err

View File

@@ -84,8 +84,8 @@ func (context *SignContext) writeXrefStream() error {
predictor := context.PDFReader.Trailer().Key("DecodeParms").Key("Predictor").Int64() predictor := context.PDFReader.Trailer().Key("DecodeParms").Key("Predictor").Int64()
streamBytes := []byte{} var streamBytes []byte
err := errors.New("") var err error
writeXrefStreamLine(buffer, 1, int(context.Filesize), 0) writeXrefStreamLine(buffer, 1, int(context.Filesize), 0)
writeXrefStreamLine(buffer, 1, int(context.Filesize+context.VisualSignData.Length), 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 var b bytes.Buffer
w := zlib.NewWriter(&b) w := zlib.NewWriter(&b)
w.Write(data) if _, err := w.Write(data); err != nil {
return nil, err
}
w.Close() w.Close()
return b.Bytes(), nil return b.Bytes(), nil
@@ -209,7 +211,9 @@ func EncodePNGUPBytes(columns int, data []byte) ([]byte, error) {
var b bytes.Buffer var b bytes.Buffer
w := zlib.NewWriter(&b) w := zlib.NewWriter(&b)
w.Write(data) if _, err := w.Write(data); err != nil {
return nil, err
}
w.Close() w.Close()
return b.Bytes(), nil return b.Bytes(), nil

View File

@@ -4,6 +4,7 @@ import (
"crypto" "crypto"
"crypto/x509" "crypto/x509"
"encoding/hex" "encoding/hex"
"fmt"
"io" "io"
"os" "os"
"time" "time"
@@ -164,7 +165,10 @@ func (context *SignContext) SignPDF() error {
context.OutputBuffer = filebuffer.New([]byte{}) context.OutputBuffer = filebuffer.New([]byte{})
// Copy old file into new file. // 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 { if _, err := io.Copy(context.OutputBuffer, context.InputFile); err != nil {
return err return err
} }
@@ -182,26 +186,22 @@ func (context *SignContext) SignPDF() error {
case "ECDSA-SHA1": case "ECDSA-SHA1":
case "DSA-SHA1": case "DSA-SHA1":
context.SignatureMaxLength += uint32(hex.EncodedLen(128)) context.SignatureMaxLength += uint32(hex.EncodedLen(128))
break
case "SHA256-RSA": case "SHA256-RSA":
case "ECDSA-SHA256": case "ECDSA-SHA256":
case "DSA-SHA256": case "DSA-SHA256":
context.SignatureMaxLength += uint32(hex.EncodedLen(256)) context.SignatureMaxLength += uint32(hex.EncodedLen(256))
break
case "SHA384-RSA": case "SHA384-RSA":
case "ECDSA-SHA384": case "ECDSA-SHA384":
context.SignatureMaxLength += uint32(hex.EncodedLen(384)) context.SignatureMaxLength += uint32(hex.EncodedLen(384))
break
case "SHA512-RSA": case "SHA512-RSA":
case "ECDSA-SHA512": case "ECDSA-SHA512":
context.SignatureMaxLength += uint32(hex.EncodedLen(512)) context.SignatureMaxLength += uint32(hex.EncodedLen(512))
break
} }
// Add size for my certificate. // Add size for my certificate.
degenerated, err := pkcs7.DegenerateCertificate(context.SignData.Certificate.Raw) degenerated, err := pkcs7.DegenerateCertificate(context.SignData.Certificate.Raw)
if err != nil { if err != nil {
return err return fmt.Errorf("failed to degenerate certificate: %w", err)
} }
context.SignatureMaxLength += uint32(hex.EncodedLen(len(degenerated))) context.SignatureMaxLength += uint32(hex.EncodedLen(len(degenerated)))
@@ -216,7 +216,7 @@ func (context *SignContext) SignPDF() error {
for _, cert := range certificate_chain { for _, cert := range certificate_chain {
degenerated, err := pkcs7.DegenerateCertificate(cert.Raw) degenerated, err := pkcs7.DegenerateCertificate(cert.Raw)
if err != nil { if err != nil {
return err return fmt.Errorf("failed to degenerate certificate in chain: %w", err)
} }
context.SignatureMaxLength += uint32(hex.EncodedLen(len(degenerated))) context.SignatureMaxLength += uint32(hex.EncodedLen(len(degenerated)))
@@ -225,17 +225,22 @@ func (context *SignContext) SignPDF() error {
// Add estimated size for TSA. // Add estimated size for TSA.
// We can't kow actual size of TSA until after signing. // 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 != "" { if context.SignData.TSA.URL != "" {
context.SignatureMaxLength += uint32(hex.EncodedLen(6000)) context.SignatureMaxLength += uint32(hex.EncodedLen(9000))
} }
// Fetch revocation data before adding signature placeholder. // Fetch revocation data before adding signature placeholder.
// Revocation data can be quite large and we need to create enough space in the 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() visual_signature, err := context.createVisualSignature()
if err != nil { if err != nil {
return err return fmt.Errorf("failed to create visual signature: %w", err)
} }
context.VisualSignData.Length = int64(len(visual_signature)) context.VisualSignData.Length = int64(len(visual_signature))
@@ -247,14 +252,14 @@ func (context *SignContext) SignPDF() error {
catalog, err := context.createCatalog() catalog, err := context.createCatalog()
if err != nil { if err != nil {
return err return fmt.Errorf("failed to create catalog: %w", err)
} }
context.CatalogData.Length = int64(len(catalog)) context.CatalogData.Length = int64(len(catalog))
// Write the new catalog object. // Write the new catalog object.
if _, err := context.OutputBuffer.Write([]byte(catalog)); err != nil { if _, err := context.OutputBuffer.Write([]byte(catalog)); err != nil {
return err return fmt.Errorf("failed to write catalog: %w", err)
} }
// Create the signature object // Create the signature object
@@ -262,14 +267,14 @@ func (context *SignContext) SignPDF() error {
info, err := context.createInfo() info, err := context.createInfo()
if err != nil { if err != nil {
return err return fmt.Errorf("failed to create info: %w", err)
} }
context.InfoData.Length = int64(len(info)) context.InfoData.Length = int64(len(info))
// Write the new catalog object. // Write the new catalog object.
if _, err := context.OutputBuffer.Write([]byte(info)); err != nil { 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)) 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. // Write the new signature object.
if _, err := context.OutputBuffer.Write([]byte(signature_object)); err != nil { 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. // Calculate the new start position of the xref table.
context.NewXrefStart = appended_bytes + int64(len(signature_object)) context.NewXrefStart = appended_bytes + int64(len(signature_object))
if err := context.writeXref(); err != nil { if err := context.writeXref(); err != nil {
return err return fmt.Errorf("failed to write xref: %w", err)
} }
if err := context.writeTrailer(); err != nil { if err := context.writeTrailer(); err != nil {
return err return fmt.Errorf("failed to write trailer: %w", err)
} }
if err := context.updateByteRange(); err != nil { if err := context.updateByteRange(); err != nil {
return err return fmt.Errorf("failed to update byte range: %w", err)
} }
if err := context.replaceSignature(); err != nil { 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() 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 return nil
} }

View File

@@ -65,7 +65,6 @@ func TestReaderCanReadPDF(t *testing.T) {
for _, f := range files { for _, f := range files {
ext := filepath.Ext(f.Name()) ext := filepath.Ext(f.Name())
if ext != ".pdf" { if ext != ".pdf" {
t.Log("Skipping file", f.Name())
continue continue
} }
@@ -100,8 +99,8 @@ func TestReaderCanReadPDF(t *testing.T) {
} }
func TestSignPDF(t *testing.T) { func TestSignPDF(t *testing.T) {
os.RemoveAll("../testfiles/failed/") _ = os.RemoveAll("../testfiles/failed/")
os.MkdirAll("../testfiles/failed/", 0777) _ = os.MkdirAll("../testfiles/failed/", 0777)
files, err := ioutil.ReadDir("../testfiles") files, err := ioutil.ReadDir("../testfiles")
if err != nil { if err != nil {
@@ -140,7 +139,6 @@ func TestSignPDF(t *testing.T) {
ext := filepath.Ext(f.Name()) ext := filepath.Ext(f.Name())
if ext != ".pdf" { if ext != ".pdf" {
t.Log("Skipping file", f.Name())
continue continue
} }
@@ -171,6 +169,10 @@ func TestSignPDF(t *testing.T) {
} }
outputFile, err := ioutil.TempFile("", "pdfsign_test") outputFile, err := ioutil.TempFile("", "pdfsign_test")
if err != nil {
t.Errorf("%s", err.Error())
return
}
err = Sign(input_file, outputFile, rdr, size, SignData{ err = Sign(input_file, outputFile, rdr, size, SignData{
Signature: SignDataSignature{ Signature: SignDataSignature{
@@ -196,7 +198,7 @@ func TestSignPDF(t *testing.T) {
if err != nil { if err != nil {
input_file.Close() input_file.Close()
os.Remove(outputFile.Name()) _ = os.Remove(outputFile.Name())
st.Errorf("%s: %s", f.Name(), err.Error()) st.Errorf("%s: %s", f.Name(), err.Error())
return return
} }
@@ -244,6 +246,10 @@ func TestSignPDFFile(t *testing.T) {
certificate_chains := make([][]*x509.Certificate, 0) certificate_chains := make([][]*x509.Certificate, 0)
tmpfile, err := ioutil.TempFile("", "pdfsign_test") tmpfile, err := ioutil.TempFile("", "pdfsign_test")
if err != nil {
t.Errorf("%s", err.Error())
return
}
err = SignFile("../testfiles/testfile20.pdf", tmpfile.Name(), SignData{ err = SignFile("../testfiles/testfile20.pdf", tmpfile.Name(), SignData{
Signature: SignDataSignature{ Signature: SignDataSignature{
@@ -322,7 +328,10 @@ func BenchmarkSignPDF(b *testing.B) {
} }
for n := 0; n < b.N; n++ { 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{ err = Sign(input_file, ioutil.Discard, rdr, size, SignData{
Signature: SignDataSignature{ Signature: SignDataSignature{

View File

@@ -71,7 +71,9 @@ type DocumentInfo struct {
func File(file *os.File) (apiResp *Response, err error) { func File(file *os.File) (apiResp *Response, err error) {
finfo, _ := file.Stat() finfo, _ := file.Stat()
file.Seek(0, 0) if _, err := file.Seek(0, 0); err != nil {
return nil, err
}
return Reader(file, finfo.Size()) return Reader(file, finfo.Size())
} }
@@ -155,9 +157,9 @@ func Reader(file io.ReaderAt, size int64) (apiResp *Response, err error) {
// Signer certificate // Signer certificate
// http://www.alvestrand.no/objectid/1.2.840.113549.1.9.html // 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 // http://www.alvestrand.no/objectid/1.2.840.113583.1.1.8.html
var isn []byte //var isn []byte
for _, s := range p7.Signers { for _, s := range p7.Signers {
isn = s.IssuerAndSerialNumber.IssuerName.FullBytes //isn = s.IssuerAndSerialNumber.IssuerName.FullBytes
//for _, a := range s.AuthenticatedAttributes { //for _, a := range s.AuthenticatedAttributes {
//fmt.Printf("A: %v, %#v\n", s.IssuerAndSerialNumber.SerialNumber, a.Type) //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 // Directory of certificates, including OCSP
//var ica *x509.Certificate
certPool := x509.NewCertPool() certPool := x509.NewCertPool()
for _, cert := range p7.Certificates { for _, cert := range p7.Certificates {
certPool.AddCert(cert) certPool.AddCert(cert)
if bytes.Equal(isn, cert.RawSubject) {
//ica = cert
}
} }
// Verify the digital signature of the pdf file. // 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) // PDF signature certificate revocation information attribute (1.2.840.113583.1.1.8)
var revInfo revocation.InfoArchival 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 // Parse OCSP response
var ocspStatus = make(map[string]*ocsp.Response) var ocspStatus = make(map[string]*ocsp.Response)