Valid signature
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package sign
|
package sign
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bitbucket.org/digitorus/pdf"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
@@ -9,6 +11,20 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func findFirstPage(parent pdf.Value) (pdf.Value, error) {
|
||||||
|
value_type := parent.Key("Type").String()
|
||||||
|
if value_type == "/Pages" {
|
||||||
|
recurse_parent, recurse_err := findFirstPage(parent.Key("Kids").Index(0))
|
||||||
|
return recurse_parent, recurse_err
|
||||||
|
}
|
||||||
|
|
||||||
|
if value_type == "/Page" {
|
||||||
|
return parent, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent, errors.New("Could not find first page.")
|
||||||
|
}
|
||||||
|
|
||||||
func pdfString(text string) string {
|
func pdfString(text string) string {
|
||||||
text = strings.Replace(text, "\\", "\\\\", -1)
|
text = strings.Replace(text, "\\", "\\\\", -1)
|
||||||
text = strings.Replace(text, ")", "\\)", -1)
|
text = strings.Replace(text, ")", "\\)", -1)
|
||||||
|
@@ -46,9 +46,9 @@ func (context *SignContext) createCatalog() (catalog string, err error) {
|
|||||||
|
|
||||||
if !context.SignData.Signature.Approval {
|
if !context.SignData.Signature.Approval {
|
||||||
if context.SignData.Signature.CertType > 0 {
|
if context.SignData.Signature.CertType > 0 {
|
||||||
catalog += " /Perms << /DocMDP " + strconv.Itoa(int(context.SignData.ObjectId)) + " 0 R >>";
|
catalog += " /Perms << /DocMDP " + strconv.Itoa(int(context.SignData.ObjectId)) + " 0 R >>"
|
||||||
} else {
|
} else {
|
||||||
catalog += " /Perms << /UR3 " + strconv.Itoa(int(context.SignData.ObjectId)) + " 0 R >>";
|
catalog += " /Perms << /UR3 " + strconv.Itoa(int(context.SignData.ObjectId)) + " 0 R >>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
sign/pdfinfo.go
Normal file
25
sign/pdfinfo.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package sign
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (context *SignContext) createInfo() (info string, err error) {
|
||||||
|
original_info := context.PDFReader.Trailer().Key("Info")
|
||||||
|
info = strconv.Itoa(int(context.InfoData.ObjectId)) + " 0 obj\n"
|
||||||
|
info += "<<"
|
||||||
|
|
||||||
|
info_keys := original_info.Keys()
|
||||||
|
for _, key := range info_keys {
|
||||||
|
info += "/" + key
|
||||||
|
if key == "ModDate" {
|
||||||
|
info += pdfDateTime(context.SignData.Signature.Info.Date)
|
||||||
|
} else {
|
||||||
|
info += pdfString(original_info.Key(key).RawString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info += ">>"
|
||||||
|
info += "\nendobj\n"
|
||||||
|
return info, nil
|
||||||
|
}
|
@@ -108,7 +108,7 @@ func (context *SignContext) replaceSignature() error {
|
|||||||
dst := make([]byte, hex.EncodedLen(len(signature)))
|
dst := make([]byte, hex.EncodedLen(len(signature)))
|
||||||
hex.Encode(dst, signature)
|
hex.Encode(dst, signature)
|
||||||
|
|
||||||
context.OutputFile.WriteAt(dst, context.ByteRangeValues[0] + context.ByteRangeValues[1] + 1)
|
context.OutputFile.WriteAt(dst, context.ByteRangeValues[0]+context.ByteRangeValues[1]+1)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -19,11 +19,18 @@ func (context *SignContext) writeTrailer() error {
|
|||||||
new_root := "Root " + strconv.FormatInt(int64(context.CatalogData.ObjectId), 10) + " 0 R"
|
new_root := "Root " + strconv.FormatInt(int64(context.CatalogData.ObjectId), 10) + " 0 R"
|
||||||
|
|
||||||
size_string := "Size " + strconv.FormatInt(context.PDFReader.XrefInformation.ItemCount, 10)
|
size_string := "Size " + strconv.FormatInt(context.PDFReader.XrefInformation.ItemCount, 10)
|
||||||
new_size := "Size " + strconv.FormatInt(context.PDFReader.XrefInformation.ItemCount+3, 10)
|
new_size := "Size " + strconv.FormatInt(context.PDFReader.XrefInformation.ItemCount+4, 10)
|
||||||
|
|
||||||
|
info := context.PDFReader.Trailer().Key("Info")
|
||||||
|
infoPtr := info.GetPtr()
|
||||||
|
|
||||||
|
info_string := "Info " + strconv.Itoa(int(infoPtr.GetID())) + " " + strconv.Itoa(int(infoPtr.GetGen())) + " R"
|
||||||
|
new_info := "Info " + strconv.FormatInt(int64(context.InfoData.ObjectId), 10) + " 0 R"
|
||||||
|
|
||||||
trailer_string := string(trailer_buf)
|
trailer_string := string(trailer_buf)
|
||||||
trailer_string = strings.Replace(trailer_string, root_string, new_root, -1)
|
trailer_string = strings.Replace(trailer_string, root_string, new_root, -1)
|
||||||
trailer_string = strings.Replace(trailer_string, size_string, new_size, -1)
|
trailer_string = strings.Replace(trailer_string, size_string, new_size, -1)
|
||||||
|
trailer_string = strings.Replace(trailer_string, info_string, new_info, -1)
|
||||||
|
|
||||||
// Write the new trailer.
|
// Write the new trailer.
|
||||||
if _, err := context.OutputFile.Write([]byte(trailer_string)); err != nil {
|
if _, err := context.OutputFile.Write([]byte(trailer_string)); err != nil {
|
||||||
|
@@ -28,10 +28,16 @@ func (context *SignContext) createVisualSignature() (visual_signature string, er
|
|||||||
rootPtr := root.GetPtr()
|
rootPtr := root.GetPtr()
|
||||||
context.CatalogData.RootString = strconv.Itoa(int(rootPtr.GetID())) + " " + strconv.Itoa(int(rootPtr.GetGen())) + " R"
|
context.CatalogData.RootString = strconv.Itoa(int(rootPtr.GetID())) + " " + strconv.Itoa(int(rootPtr.GetGen())) + " R"
|
||||||
|
|
||||||
page := root.Key("Pages").Key("Kids").Index(0).GetPtr()
|
first_page, err := findFirstPage(root.Key("Pages"))
|
||||||
visual_signature += " /P " + strconv.Itoa(int(page.GetID())) + " " + strconv.Itoa(int(page.GetGen())) + " R"
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
visual_signature += " /F 4"
|
first_page_ptr := first_page.GetPtr()
|
||||||
|
|
||||||
|
visual_signature += " /P " + strconv.Itoa(int(first_page_ptr.GetID())) + " " + strconv.Itoa(int(first_page_ptr.GetGen())) + " R"
|
||||||
|
|
||||||
|
visual_signature += " /F 132"
|
||||||
visual_signature += " /FT /Sig"
|
visual_signature += " /FT /Sig"
|
||||||
visual_signature += " /T " + pdfString("Signature")
|
visual_signature += " /T " + pdfString("Signature")
|
||||||
visual_signature += " /Ff 0"
|
visual_signature += " /Ff 0"
|
||||||
|
@@ -22,7 +22,7 @@ func (context *SignContext) writeXref() error {
|
|||||||
|
|
||||||
func (context *SignContext) writeXrefTable() error {
|
func (context *SignContext) writeXrefTable() error {
|
||||||
xref_size := "xref\n0 " + strconv.FormatInt(context.PDFReader.XrefInformation.ItemCount, 10)
|
xref_size := "xref\n0 " + strconv.FormatInt(context.PDFReader.XrefInformation.ItemCount, 10)
|
||||||
new_xref_size := "xref\n0 " + strconv.FormatInt(context.PDFReader.XrefInformation.ItemCount+3, 10)
|
new_xref_size := "xref\n0 " + strconv.FormatInt(context.PDFReader.XrefInformation.ItemCount+4, 10)
|
||||||
|
|
||||||
if _, err := context.OutputFile.Write([]byte(new_xref_size)); err != nil {
|
if _, err := context.OutputFile.Write([]byte(new_xref_size)); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -35,7 +35,7 @@ func (context *SignContext) writeXrefTable() error {
|
|||||||
|
|
||||||
// Create the new catalog xref line.
|
// Create the new catalog xref line.
|
||||||
visual_signature_object_start_position := strconv.FormatInt(context.Filesize, 10)
|
visual_signature_object_start_position := strconv.FormatInt(context.Filesize, 10)
|
||||||
visual_signature_xref_line := leftPad(visual_signature_object_start_position, "0", 10-len(visual_signature_object_start_position)) + " 00000 n\n"
|
visual_signature_xref_line := leftPad(visual_signature_object_start_position, "0", 10-len(visual_signature_object_start_position)) + " 00000 n \n"
|
||||||
|
|
||||||
// Write the new catalog xref line.
|
// Write the new catalog xref line.
|
||||||
if _, err := context.OutputFile.Write([]byte(visual_signature_xref_line)); err != nil {
|
if _, err := context.OutputFile.Write([]byte(visual_signature_xref_line)); err != nil {
|
||||||
@@ -44,7 +44,7 @@ func (context *SignContext) writeXrefTable() error {
|
|||||||
|
|
||||||
// Create the new catalog xref line.
|
// Create the new catalog xref line.
|
||||||
catalog_object_start_position := strconv.FormatInt(context.Filesize+context.VisualSignData.Length, 10)
|
catalog_object_start_position := strconv.FormatInt(context.Filesize+context.VisualSignData.Length, 10)
|
||||||
catalog_xref_line := leftPad(catalog_object_start_position, "0", 10-len(catalog_object_start_position)) + " 00000 n\n"
|
catalog_xref_line := leftPad(catalog_object_start_position, "0", 10-len(catalog_object_start_position)) + " 00000 n \n"
|
||||||
|
|
||||||
// Write the new catalog xref line.
|
// Write the new catalog xref line.
|
||||||
if _, err := context.OutputFile.Write([]byte(catalog_xref_line)); err != nil {
|
if _, err := context.OutputFile.Write([]byte(catalog_xref_line)); err != nil {
|
||||||
@@ -52,8 +52,17 @@ func (context *SignContext) writeXrefTable() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the new signature xref line.
|
// Create the new signature xref line.
|
||||||
signature_object_start_position := strconv.FormatInt(context.Filesize+context.VisualSignData.Length+context.CatalogData.Length, 10)
|
info_object_start_position := strconv.FormatInt(context.Filesize+context.VisualSignData.Length+context.CatalogData.Length, 10)
|
||||||
signature_xref_line := leftPad(signature_object_start_position, "0", 10-len(signature_object_start_position)) + " 00000 n\n"
|
info_xref_line := leftPad(info_object_start_position, "0", 10-len(info_object_start_position)) + " 00000 n \n"
|
||||||
|
|
||||||
|
// Write the new signature xref line.
|
||||||
|
if _, err := context.OutputFile.Write([]byte(info_xref_line)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the new signature xref line.
|
||||||
|
signature_object_start_position := strconv.FormatInt(context.Filesize+context.VisualSignData.Length+context.CatalogData.Length+context.InfoData.Length, 10)
|
||||||
|
signature_xref_line := leftPad(signature_object_start_position, "0", 10-len(signature_object_start_position)) + " 00000 n \n"
|
||||||
|
|
||||||
// Write the new signature xref line.
|
// Write the new signature xref line.
|
||||||
if _, err := context.OutputFile.Write([]byte(signature_xref_line)); err != nil {
|
if _, err := context.OutputFile.Write([]byte(signature_xref_line)); err != nil {
|
||||||
|
33
sign/sign.go
33
sign/sign.go
@@ -3,11 +3,11 @@ package sign
|
|||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/digitorus/pdf"
|
"bitbucket.org/digitorus/pdf"
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type CatalogData struct {
|
type CatalogData struct {
|
||||||
@@ -29,6 +29,11 @@ type VisualSignData struct {
|
|||||||
Length int64
|
Length int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InfoData struct {
|
||||||
|
ObjectId uint32
|
||||||
|
Length int64
|
||||||
|
}
|
||||||
|
|
||||||
type SignDataSignature struct {
|
type SignDataSignature struct {
|
||||||
Approval bool
|
Approval bool
|
||||||
CertType uint32
|
CertType uint32
|
||||||
@@ -50,6 +55,7 @@ type SignContext struct {
|
|||||||
SignData SignData
|
SignData SignData
|
||||||
CatalogData CatalogData
|
CatalogData CatalogData
|
||||||
VisualSignData VisualSignData
|
VisualSignData VisualSignData
|
||||||
|
InfoData InfoData
|
||||||
PDFReader *pdf.Reader
|
PDFReader *pdf.Reader
|
||||||
NewXrefStart int64
|
NewXrefStart int64
|
||||||
ByteRangeStartByte int64
|
ByteRangeStartByte int64
|
||||||
@@ -81,7 +87,7 @@ func SignFile(input string, output string, sign_data SignData) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sign_data.ObjectId = uint32(rdr.XrefInformation.ItemCount) + 2
|
sign_data.ObjectId = uint32(rdr.XrefInformation.ItemCount) + 3
|
||||||
|
|
||||||
// We do size+1 because we insert a newline.
|
// We do size+1 because we insert a newline.
|
||||||
context := SignContext{
|
context := SignContext{
|
||||||
@@ -95,6 +101,9 @@ func SignFile(input string, output string, sign_data SignData) error {
|
|||||||
CatalogData: CatalogData{
|
CatalogData: CatalogData{
|
||||||
ObjectId: uint32(rdr.XrefInformation.ItemCount) + 1,
|
ObjectId: uint32(rdr.XrefInformation.ItemCount) + 1,
|
||||||
},
|
},
|
||||||
|
InfoData: InfoData{
|
||||||
|
ObjectId: uint32(rdr.XrefInformation.ItemCount) + 2,
|
||||||
|
},
|
||||||
SignData: sign_data,
|
SignData: sign_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,9 +158,23 @@ func (context *SignContext) SignPDF() error {
|
|||||||
// Create the signature object
|
// Create the signature object
|
||||||
signature_object, byte_range_start_byte, signature_contents_start_byte := context.createSignaturePlaceholder()
|
signature_object, byte_range_start_byte, signature_contents_start_byte := context.createSignaturePlaceholder()
|
||||||
|
|
||||||
|
info, err := context.createInfo()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
context.InfoData.Length = int64(len(info))
|
||||||
|
|
||||||
|
// Write the new catalog object.
|
||||||
|
if _, err := context.OutputFile.Write([]byte(info)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
appended_bytes := context.Filesize + int64(len(catalog)) + int64(len(visual_signature)) + int64(len(info))
|
||||||
|
|
||||||
// Positions are relative to old start position of xref table.
|
// Positions are relative to old start position of xref table.
|
||||||
byte_range_start_byte += context.Filesize + int64(len(catalog)) + int64(len(visual_signature))
|
byte_range_start_byte += appended_bytes
|
||||||
signature_contents_start_byte += context.Filesize + int64(len(catalog)) + int64(len(visual_signature))
|
signature_contents_start_byte += appended_bytes
|
||||||
|
|
||||||
context.ByteRangeStartByte = byte_range_start_byte
|
context.ByteRangeStartByte = byte_range_start_byte
|
||||||
context.SignatureContentsStartByte = signature_contents_start_byte
|
context.SignatureContentsStartByte = signature_contents_start_byte
|
||||||
@@ -162,7 +185,7 @@ func (context *SignContext) SignPDF() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the new start position of the xref table.
|
// Calculate the new start position of the xref table.
|
||||||
context.NewXrefStart = context.Filesize + int64(len(signature_object)) + int64(len(catalog)) + int64(len(visual_signature))
|
context.NewXrefStart = appended_bytes + int64(len(signature_object))
|
||||||
|
|
||||||
if err := context.writeXref(); err != nil {
|
if err := context.writeXref(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -13,8 +13,8 @@ import (
|
|||||||
"bitbucket.org/digitorus/pdf"
|
"bitbucket.org/digitorus/pdf"
|
||||||
"github.com/digitorus/pkcs7"
|
"github.com/digitorus/pkcs7"
|
||||||
"github.com/digitorus/timestamp"
|
"github.com/digitorus/timestamp"
|
||||||
"golang.org/x/crypto/ocsp"
|
|
||||||
"go/src/log"
|
"go/src/log"
|
||||||
|
"golang.org/x/crypto/ocsp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RevocationInfoArchival struct {
|
type RevocationInfoArchival struct {
|
||||||
@@ -132,12 +132,6 @@ func Verify(file *os.File) (apiResp *Response, err error) {
|
|||||||
apiResp.Error = fmt.Sprintln("Failed to get ByteRange:", i, err)
|
apiResp.Error = fmt.Sprintln("Failed to get ByteRange:", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println(v.Key("ByteRange").Index(i-1).Int64())
|
|
||||||
log.Println(v.Key("ByteRange").Index(i).Int64())
|
|
||||||
log.Println(string(content[0:60]))
|
|
||||||
log.Println(string(content[len(content)-60:len(content)]))
|
|
||||||
log.Println(len(content))
|
|
||||||
|
|
||||||
p7.Content = append(p7.Content, content...)
|
p7.Content = append(p7.Content, content...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user