有人使用过unidoc数字签名吗
公司要做上传合同电子签章,我的证书是用的阿里云买的ssl证书,下载下来的pfx文件,签名后打开一直显示文件签名后被修改或者已损坏,下面是我最后改来改去的最终版,如果不使用pfx证书,用generateKeys生成就不会显示被修改。
package main
import (
"bytes"
"crypto"
"crypto/rsa"
"crypto/x509"
"fmt"
"image"
"log"
"os"
"time"
"github.com/unidoc/unipdf/v3/annotator"
"github.com/unidoc/unipdf/v3/common/license"
"github.com/unidoc/unipdf/v3/core"
"github.com/unidoc/unipdf/v3/model"
"github.com/unidoc/unipdf/v3/model/sighandler"
"golang.org/x/crypto/pkcs12"
)
func init() {
// Make sure to load your metered License API key prior to using the library.
// If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
err := license.SetMeteredKey(`8258c687d5bea0b89cb736d762de6937661d8f4562529b67b4ef478a2963d409`)
if err != nil {
panic(err)
}
}
var now = time.Now()
func main() {
inputPath := `template_new.pdf`
imageFile := `image.png`
//watermarkImageFile := args[3]
outputPath := `template_new2.pdf`
// 读取PFX文件
pfxPath := "tanghuacomforthome.com.pfx"
pfxPassword := "0gfn69iu"
pfxData, err := os.ReadFile(pfxPath)
if err != nil {
log.Fatalf("无法读取PFX文件: %v", err)
}
// 解码PFX文件
priv, cert, err := DecodePFX(pfxData, pfxPassword)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
// Create reader.
file, err := os.Open(inputPath)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
defer file.Close()
reader, err := model.NewPdfReader(file)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
// Create the image
imgFile, err := os.Open(imageFile)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
defer imgFile.Close()
signatureImage, _, err := image.Decode(imgFile)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
// Create appender.
appender, err := model.NewPdfAppender(reader)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
// Create signature handler.
timestampServerURL := "https://freetsa.org/tsr"
handler, err := sighandler.NewEtsiPAdESLevelLT(priv, cert, nil, timestampServerURL, appender)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
// Create signature.
signature := model.NewPdfSignature(handler)
signature.SetName("TangHua")
signature.SetReason("Signature Appearance Reason")
signature.SetDate(time.Now(), "")
if err := signature.Initialize(); err != nil {
log.Fatalf("Fail: %v\n", err)
}
// numPages, err := reader.GetNumPages()
// if err != nil {
// log.Fatal("Fail: %v\n", err)
// }
opts := annotator.NewSignatureFieldOpts()
opts.FontSize = 10
opts.Rect = []float64{10, 25, 110, 75}
opts.Image = signatureImage
opts.ImagePosition = annotator.SignatureImageRight
field, err := annotator.NewSignatureField(
signature,
[]*annotator.SignatureLine{},
opts,
)
if err != nil {
log.Fatalf("Fail: %v\n", err)
}
field.T = core.MakeString(fmt.Sprintf("Signature %d", 1))
if err = appender.Sign(1, field); err != nil {
log.Fatalf("Fail: %v\n", err)
}
// Write to buffer
buffer := bytes.NewBuffer(nil)
err = appender.Write(buffer)
if err != nil {
log.Fatalf("Error writing to buffer: %v\n", err)
}
// Second pass to save DSS/VRI information
pdf2, err := model.NewPdfReader(bytes.NewReader(buffer.Bytes()))
if err != nil {
log.Fatalf("Error creating PDF reader for second pass: %v\n", err)
}
appender2, err := model.NewPdfAppender(pdf2)
if err != nil {
log.Fatalf("Error creating PDF appender for second pass: %v\n", err)
}
appender2.SetDSS(appender.GetDSS())
buf2 := bytes.NewBuffer(nil)
err = appender2.Write(buf2)
if err != nil {
log.Fatalf("Error writing second pass buffer: %v\n", err)
}
// Document timestamp for B-LTA compatibility
pdf3, err := model.NewPdfReader(bytes.NewReader(buf2.Bytes()))
if err != nil {
log.Fatalf("Error creating PDF reader for timestamp: %v\n", err)
}
appender3, err := model.NewPdfAppender(pdf3)
if err != nil {
log.Fatalf("Error creating PDF appender for timestamp: %v\n", err)
}
handler, err = sighandler.NewDocTimeStamp(timestampServerURL, crypto.SHA512)
if err != nil {
log.Fatalf("Error creating timestamp handler: %v\n", err)
}
signature = model.NewPdfSignature(handler)
signature.SetName("Test Signature")
signature.SetDate(time.Now(), "")
err = signature.Initialize()
if err != nil {
log.Fatalf("Error initializing timestamp signature: %v\n", err)
}
opts = annotator.NewSignatureFieldOpts()
opts.Rect = []float64{10, 25, 110, 75}
opts.Image = signatureImage
sigField, err := annotator.NewSignatureField(
signature,
[]*annotator.SignatureLine{},
opts,
)
if err != nil {
log.Fatalf("Error creating timestamp signature field: %v\n", err)
}
err = appender3.Sign(1, sigField)
if err != nil {
log.Fatalf("Error signing with timestamp: %v\n", err)
}
err = appender3.WriteToFile(outputPath)
if err != nil {
log.Fatalf("Error writing final output file: %v\n", err)
}
log.Printf("PDF file successfully signed. Output path: %s\n", outputPath)
}
// func generateKeys() (*rsa.PrivateKey, *x509.Certificate, error) {
// // Generate private key.
// priv, err := rsa.GenerateKey(rand.Reader, 2048)
// if err != nil {
// return nil, nil, err
// }
// // Initialize X509 certificate template.
// template := x509.Certificate{
// SerialNumber: big.NewInt(1),
// Subject: pkix.Name{
// Organization: []string{"Tanghua"},
// },
// NotBefore: now.Add(-time.Hour),
// NotAfter: now.Add(time.Hour * 24 * 365),
// KeyUsage: x509.KeyUsageDigitalSignature,
// ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
// BasicConstraintsValid: true,
// }
// // Generate X509 certificate.
// certData, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv)
// if err != nil {
// return nil, nil, err
// }
// cert, err := x509.ParseCertificate(certData)
// if err != nil {
// return nil, nil, err
// }
// return priv, cert, nil
// }
// DecodePFX 解码PFX文件并返回私钥和证书
func DecodePFX(pfxData []byte, password string) (*rsa.PrivateKey, *x509.Certificate, error) {
// 使用pkcs12包解码PFX数据
blocks, err := pkcs12.ToPEM(pfxData, password)
if err != nil {
return nil, nil, err
}
var privateKey *rsa.PrivateKey
var certificate *x509.Certificate
for _, block := range blocks {
switch block.Type {
case "PRIVATE KEY":
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, nil, err
}
privateKey = key
case "CERTIFICATE":
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, nil, err
}
certificate = cert
}
}
if privateKey == nil || certificate == nil {
return nil, nil, fmt.Errorf("未找到私钥或证书")
}
return privateKey, certificate, nil
}
那估计就是证书有些问题吧,确认下pfx读取的证书这些跟自己生成的有哪些区别