Check errors
This commit is contained in:
@@ -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)
|
||||
|
@@ -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())
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
51
sign/sign.go
51
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
|
||||
}
|
||||
|
@@ -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{
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user