### Verify Command Examples Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/configuration.md Examples demonstrating various ways to use the pdfsign verify command. ```bash # Basic verification ./pdfsign verify document.pdf ``` ```bash # With external revocation checking ./pdfsign verify -external document.pdf ``` ```bash # Highest security (Non-Repudiation required) ./pdfsign verify -require-non-repudiation -external document.pdf ``` ```bash # Custom timeout ./pdfsign verify -external -http-timeout=30s document.pdf ``` ```bash # Self-signed certificate ./pdfsign verify -allow-untrusted-roots self-signed.pdf ``` -------------------------------- ### Basic Signing Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md A straightforward example of signing a PDF with essential parameters. ```bash pdfsign sign -name "John Doe" document.pdf signed.pdf certificate.crt private_key.key ``` -------------------------------- ### DefaultVerifyOptions() Usage Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/configuration.md Demonstrates how to get default verification options and customize them. ```go package main import ( "os" "time" "github.com/digitorus/pdfsign/verify" ) func main() { // Get default options options := verify.DefaultVerifyOptions() // Customize options options.EnableExternalRevocationCheck = true options.RequireNonRepudiation = true options.HTTPTimeout = 30 * time.Second // Open PDF file file, _ := os.Open("document.pdf") defer file.Close() // Verify with custom options response, err := verify.VerifyFileWithOptions(file, options) if err != nil { panic(err) } // Process response if response.Error != "" { println("Verification error:", response.Error) } for _, signer := range response.Signers { println("Signer:", signer.Name) println("Valid:", signer.ValidSignature) } } ``` -------------------------------- ### Sign() Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/sign.md Example demonstrating how to use the Sign function for custom I/O handling with in-memory buffers. ```go package main import ( "bytes" "crypto" "github.com/digitorus/pdf" "github.com/digitorus/pdfsign/sign" ) func main() { // Read input PDF inputData, _ := os.ReadFile("input.pdf") inputBuffer := bytes.NewReader(inputData) // Create PDF reader rdr, _ := pdf.NewReader(inputBuffer, int64(len(inputData))) // Output buffer outputBuffer := &bytes.Buffer{} // Sign err := sign.Sign( inputBuffer, outputBuffer, rdr, int64(len(inputData)), sign.SignData{ Signature: sign.SignDataSignature{ CertType: sign.ApprovalSignature, Info: sign.SignDataSignatureInfo{ Name: "Jane Smith", }, }, Signer: privateKey, Certificate: cert, }, ) if err != nil { panic(err) } // outputBuffer now contains the signed PDF } ``` -------------------------------- ### Sign Command Examples Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/configuration.md Examples demonstrating various ways to use the `pdfsign sign` command, from basic signing to including metadata and custom TSA. ```bash # Basic signing ./pdfsign sign -name "John Doe" input.pdf output.pdf cert.crt key.key # With metadata ./pdfsign sign \ -name "John Doe" \ -location "New York" \ -reason "Document approval" \ -contact "john@example.com" \ input.pdf output.pdf cert.crt key.key # With custom TSA ./pdfsign sign -tsa "http://timestamp.digicert.com" \ input.pdf output.pdf cert.crt key.key # TimeStamp only ./pdfsign sign -certType TimeStampSignature \ input.pdf output.pdf ``` -------------------------------- ### Appearance Visible Signature Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/sign.md Complete example of creating a visible signature with an image. ```Go package main import ( "crypto" "os" "github.com/digitorus/pdfsign/sign" ) func main() { // Load certificate and key cert := loadCertificate("cert.crt") signer := loadPrivateKey("key.key") // Read signature image signatureImage, _ := os.ReadFile("signature.png") // Create signed PDF with visible signature err := sign.SignFile("input.pdf", "output.pdf", sign.SignData{ Signature: sign.SignDataSignature{ CertType: sign.ApprovalSignature, DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesPerms, Info: sign.SignDataSignatureInfo{ Name: "John Doe", Location: "New York", Reason: "Signed with image", ContactInfo: "john@example.com", }, }, Appearance: sign.Appearance{ Visible: true, Page: 1, LowerLeftX: 350, LowerLeftY: 50, UpperRightX: 550, UpperRightY: 150, Image: signatureImage, ImageAsWatermark: false, // Draw signer name below image }, Signer: signer, DigestAlgorithm: crypto.SHA512, Certificate: cert, TSA: sign.TSA{ URL: "https://freetsa.org/tsr", }, }) if err != nil { panic(err) } } ``` -------------------------------- ### SignFile() Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/sign.md Example demonstrating how to use the SignFile function to sign a PDF with certificate, private key, and TSA details. ```go package main import ( "crypto" "crypto/x509" "os" time" "github.com/digitorus/pdfsign/sign" ) func main() { // Load certificate and private key certData, _ := os.ReadFile("certificate.crt") cert, _ := x509.ParseCertificate(certData) keyData, _ := os.ReadFile("private_key.key") // Parse key (implementation depends on key format) // Sign the PDF err := sign.SignFile("input.pdf", "output.pdf", sign.SignData{ Signature: sign.SignDataSignature{ CertType: sign.CertificationSignature, DocMDPPerm: sign.DoNotAllowAnyChangesPerms, Info: sign.SignDataSignatureInfo{ Name: "John Doe", Location: "New York", Reason: "Document approval", ContactInfo: "john@example.com", Date: time.Now(), }, }, Signer: privateKey, DigestAlgorithm: crypto.SHA256, Certificate: cert, TSA: sign.TSA{ URL: "https://freetsa.org/tsr", }, }) if err != nil { panic(err) } } ``` -------------------------------- ### AddOCSP() Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/revocation.md Example demonstrating how to fetch an OCSP response and add it to the revocation archival. ```go package main import ( "crypto/x509" "io" "net/http" "golang.org/x/crypto/ocsp" "github.com/digitorus/pdfsign/revocation" "github.com/digitorus/pdfsign/sign" ) func fetchOCSP(issuer, cert *x509.Certificate) ([]byte, error) { ocspURL := cert.OCSPServer[0] ocspReq, _ := ocsp.CreateRequest(cert, issuer, nil) resp, _ := http.Post(ocspURL, "application/ocsp-request", bytes.NewReader(ocspReq)) defer resp.Body.Close() return io.ReadAll(resp.Body) } func main() { cert := loadCertificate("cert.crt") issuer := loadCertificate("issuer.crt") // Fetch OCSP response ocspBytes, _ := fetchOCSP(issuer, cert) // Create revocation info var revInfo revocation.InfoArchival revInfo.AddOCSP(ocspBytes) // Use in signature sign.SignFile("input.pdf", "output.pdf", sign.SignData{ Certificate: cert, RevocationData: revInfo, // ... other fields }) } ``` -------------------------------- ### Example: Reading Response Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/verify.md This Go code example demonstrates how to open a PDF file, verify it using `VerifyFile`, and then process and display the verification results, including document information and details about each signer. It also shows how to convert the full response to JSON. ```go package main import ( "encoding/json" "fmt" "os" "github.com/digitorus/pdfsign/verify" ) func main() { file, _ := os.Open("document.pdf") defer file.Close() resp, err := verify.VerifyFile(file) if err != nil { fmt.Printf("Verification error: %v\n", err) return } // Check for overall error if resp.Error != "" { fmt.Printf("Response error: %s\n", resp.Error) } // Display document info fmt.Printf("Document: %s\n", resp.DocumentInfo.Title) fmt.Printf("Pages: %d\n", resp.DocumentInfo.Pages) fmt.Printf("Created: %v\n", resp.DocumentInfo.CreationDate) // Check each signature for i, signer := range resp.Signers { fmt.Printf("\nSignature #%d: %s\n", i+1, signer.Name) fmt.Printf(" Valid Signature: %v\n", signer.ValidSignature) fmt.Printf(" Trusted Issuer: %v\n", signer.TrustedIssuer) fmt.Printf(" Revoked: %v\n", signer.RevokedCertificate) fmt.Printf(" Timestamp Status: %s\n", signer.TimestampStatus) fmt.Printf(" Time Source: %s\n", signer.TimeSource) if len(signer.TimeWarnings) > 0 { fmt.Println(" Time Warnings:") for _, w := range signer.TimeWarnings { fmt.Printf(" - %s\n", w) } } } // Convert to JSON jsonData, _ := json.MarshalIndent(resp, "", " ") fmt.Println("\nFull Response:") fmt.Println(string(jsonData)) } ``` -------------------------------- ### Complete Revocation Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/revocation.md Full example showing how to embed both CRL and OCSP in a signature. ```go package main import ( "crypto" "crypto/x509" "io" "net/http" "bytes" "golang.org/x/crypto/ocsp" "github.com/digitorus/pdfsign/revocation" "github.com/digitorus/pdfsign/sign" ) func fetchCRL(cert *x509.Certificate) ([]byte, error) { for _, url := range cert.CRLDistributionPoints { resp, err := http.Get(url) if err != nil { continue } defer resp.Body.Close() if resp.StatusCode == 200 { return io.ReadAll(resp.Body) } } return nil, nil // No CRL available } func fetchOCSP(issuer, cert *x509.Certificate) ([]byte, error) { if len(cert.OCSPServer) == 0 { return nil, nil } ocspReq, err := ocsp.CreateRequest(cert, issuer, nil) if err != nil { return nil, err } resp, err := http.Post(cert.OCSPServer[0], "application/ocsp-request", bytes.NewReader(ocspReq)) if err != nil { return nil, err } defer resp.Body.Close() return io.ReadAll(resp.Body) } func main() { // Load certificate certData, _ := ioutil.ReadFile("cert.crt") cert, _ := x509.ParseCertificate(certData) // Load issuer issuerData, _ := ioutil.ReadFile("issuer.crt") issuer, _ := x509.ParseCertificate(issuerData) // Create revocation info var revInfo revocation.InfoArchival // Add CRL if available if crlData, err := fetchCRL(cert); err == nil && crlData != nil { revInfo.AddCRL(crlData) } // Add OCSP if available if ocspData, err := fetchOCSP(issuer, cert); err == nil && ocspData != nil { revInfo.AddOCSP(ocspData) } // Sign with embedded revocation info signer := loadPrivateKey("key.key") sign.SignFile("input.pdf", "output.pdf", sign.SignData{ Signature: sign.SignDataSignature{ CertType: sign.CertificationSignature, Info: sign.SignDataSignatureInfo{ Name: "John Doe", Reason: "Document approval", }, }, Signer: signer, DigestAlgorithm: crypto.SHA256, Certificate: cert, RevocationData: revInfo, CertificateChains: [][]*x509.Certificate{ {cert, issuer}, }, }) } ``` -------------------------------- ### Quick Start CLI Commands Source: https://github.com/digitorus/pdfsign/blob/main/README.md Basic commands for signing, verifying, and accessing help for the pdfsign tool. ```bash # Sign a PDF ./pdfsign sign -name "John Doe" input.pdf output.pdf certificate.crt private_key.key # Verify a PDF signature ./pdfsign verify document.pdf # Get help for specific commands ./pdfsign sign -h ./pdfsign verify -h ``` -------------------------------- ### OCSP Parsing Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/revocation.md An example showing how to parse OCSP response data and check the status of a certificate. ```go package main import ( "golang.org/x/crypto/ocsp" "github.com/digitorus/pdfsign/revocation" ) func parseOCSP(revInfo revocation.InfoArchival) error { for _, rawOCSP := range revInfo.OCSP { // Parse OCSP response resp, err := ocsp.ParseResponse(rawOCSP.FullBytes, nil) if err != nil { return err } // Check response status switch resp.Status { case ocsp.Good: println("Certificate is good") case ocsp.Revoked: println("Certificate is revoked as of", resp.RevokedAt) case ocsp.Unknown: println("Certificate status is unknown") } } return nil } ``` -------------------------------- ### Example Usage Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/sign.md Examples of configuring a TSA, including using a public server, an authenticated server, and disabling timestamping. ```Go // Free public TSA SignData{ TSA: sign.TSA{ URL: "https://freetsa.org/tsr", }, // ... } // Authenticated TSA SignData{ TSA: sign.TSA{ URL: "http://internal-tsa.example.com/tsr", Username: "username", Password: "password", }, // ... } // Disable timestamping SignData{ TSA: sign.TSA{}, // Empty struct, no URL // ... } ``` -------------------------------- ### CertType Constants Example Usage Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/sign.md Examples demonstrating the usage of CertType constants for different signature types. ```go // Certification signature (default) SignData{ Signature: SignDataSignature{ CertType: sign.CertificationSignature, }, // ... } // Approval with visible appearance SignData{ Signature: SignDataSignature{ CertType: sign.ApprovalSignature, }, Appearance: sign.Appearance{ Visible: true, LowerLeftX: 50, LowerLeftY: 50, UpperRightX: 200, UpperRightY: 100, }, // ... } // Timestamp only SignData{ Signature: SignDataSignature{ CertType: sign.TimeStampSignature, }, TSA: sign.TSA{ URL: "https://freetsa.org/tsr", }, // Don't need Signer or Certificate } ``` -------------------------------- ### AddCRL() Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/revocation.md Example demonstrating how to fetch a CRL from a distribution point and add it to the revocation archival. ```go package main import ( "crypto/x509" "io" "net/http" "github.com/digitorus/pdfsign/revocation" "github.com/digitorus/pdfsign/sign" ) func fetchCRL(url string) ([]byte, error) { resp, err := http.Get(url) if err != nil { return nil, err } defer resp.Body.Close() return io.ReadAll(resp.Body) } func main() { // Fetch CRL from distribution point cert := loadCertificate("cert.crt") var crlData []byte // Get CRL distribution point URL from certificate if len(cert.CRLDistributionPoints) > 0 { url := cert.CRLDistributionPoints[0] crlData, _ = fetchCRL(url) } // Create revocation info var revInfo revocation.InfoArchival revInfo.AddCRL(crlData) // Use in signature sign.SignFile("input.pdf", "output.pdf", sign.SignData{ Certificate: cert, RevocationData: revInfo, // ... other fields }) } ``` -------------------------------- ### File I/O Errors Example (Verify) Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/errors.md Example demonstrating how to handle file I/O errors when verifying a PDF signature. ```go file, err := os.Open("document.pdf") if err != nil { println("Failed to open PDF:", err) return } defer file.Close() response, err := verify.VerifyFile(file) if err != nil { println("Verification error:", err) return } ``` -------------------------------- ### CertificationSignature Configuration Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/configuration.md Example configuration for a Certification Signature. ```go SignData{ Signature: SignDataSignature{ CertType: sign.CertificationSignature, DocMDPPerm: sign.DoNotAllowAnyChangesPerms, // No changes after signing Info: SignDataSignatureInfo{ Name: "John Doe", Location: "New York", Reason: "Document approval", ContactInfo: "john@example.com", Date: time.Now(), }, }, Signer: privateKey, DigestAlgorithm: crypto.SHA256, Certificate: certificate, TSA: sign.TSA{ URL: "https://freetsa.org/tsr", }, } ``` -------------------------------- ### Example Usage Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/sign.md Demonstrates different permission levels for document modification after signing. ```Go // Most restrictive - lock document SignData{ Signature: SignDataSignature{ DocMDPPerm: sign.DoNotAllowAnyChangesPerms, }, // ... } // Allow form filling SignData{ Signature: SignDataSignature{ DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesPerms, }, // ... } // Most permissive - allow annotations too SignData{ Signature: SignDataSignature{ DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesAndCRUDAnnotationsPerms, }, // ... } ``` -------------------------------- ### Revocation Checking Errors Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/errors.md Example Go code demonstrating how to enable external revocation checks and process revocation warnings or times. ```go options := verify.DefaultVerifyOptions() options.EnableExternalRevocationCheck = true response, _ := verify.VerifyFileWithOptions(file, options) for _, signer := range response.Signers { for _, cert := range signer.Certificates { if cert.RevocationWarning != "" { fmt.Printf("Revocation warning: %s\n", cert.RevocationWarning) } if cert.RevokedBeforeSigning { fmt.Printf("Certificate revoked BEFORE signing: %v\n", cert.RevocationTime) } else if cert.RevocationTime != nil { fmt.Printf("Certificate revoked AFTER signing: %v\n", cert.RevocationTime) } } } ``` -------------------------------- ### UsageRightsSignature Configuration Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/configuration.md Example configuration for a Usage Rights Signature. ```go SignData{ Signature: SignDataSignature{ CertType: sign.UsageRightsSignature, Info: SignDataSignatureInfo{ Name: "Rights Owner", }, }, Signer: privateKey, Certificate: certificate, } ``` -------------------------------- ### PDF Signing Examples Source: https://github.com/digitorus/pdfsign/blob/main/README.md Common signing scenarios including basic usage, metadata inclusion, and timestamp-only signatures. ```bash # Basic signing ./pdfsign sign -name "John Doe" input.pdf output.pdf cert.crt key.key # Signing with additional metadata ./pdfsign sign -name "John Doe" -location "New York" -reason "Document approval" input.pdf output.pdf cert.crt key.key # Timestamp-only signature ./pdfsign sign -certType "TimeStampSignature" input.pdf output.pdf ``` -------------------------------- ### VerifyFile() Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/verify.md Demonstrates how to use the VerifyFile function to verify a PDF with default options and print the results. ```go package main import ( "encoding/json" "fmt" "os" "github.com/digitorus/pdfsign/verify" ) func main() { // Open PDF file file, err := os.Open("document.pdf") if err != nil { panic(err) } defer file.Close() // Verify with defaults response, err := verify.VerifyFile(file) if err != nil { panic(err) } // Print results as JSON jsonData, _ := json.MarshalIndent(response, "", " ") fmt.Println(string(jsonData)) // Check signature validity if response.Error != "" { fmt.Printf("Verification error: %s\n", response.Error) return } for _, signer := range response.Signers { fmt.Printf("Signer: %s\n", signer.Name) fmt.Printf("Valid Signature: %v\n", signer.ValidSignature) fmt.Printf("Trusted Issuer: %v\n", signer.TrustedIssuer) fmt.Printf("Timestamp Status: %s\n", signer.TimestampStatus) } } ``` -------------------------------- ### Signing with Full Metadata Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example demonstrating signing a PDF with comprehensive metadata including name, location, reason, and contact. ```bash pdfsign sign \ -name "John Doe" \ -location "New York" \ -reason "Document approval" \ -contact "john@example.com" \ document.pdf signed.pdf cert.crt key.key ``` -------------------------------- ### Add Custom Revocation Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/revocation.md An example demonstrating how to add custom, non-standard revocation information using the 'Other' type. ```go package main import ( "encoding/asn1" "github.com/digitorus/pdfsign/revocation" ) func addCustomRevocation(revInfo *revocation.InfoArchival, oid asn1.ObjectIdentifier, data []byte) { revInfo.Other = revocation.Other{ Type: oid, Value: data, } } ``` -------------------------------- ### CRL Parsing Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/revocation.md An example demonstrating how to parse CRL data from revocation information and check for revoked certificates. ```go package main import ( "crypto/x509" "github.com/digitorus/pdfsign/revocation" ) func parseCRL(revInfo revocation.InfoArchival) error { for _, rawCRL := range revInfo.CRL { // Parse each CRL entry crl, err := x509.ParseCRL(rawCRL.FullBytes) if err != nil { return err } // Check for revoked certificates for _, revoked := range crl.RevokedCertificates { println("Revoked serial:", revoked.SerialNumber.String()) } } return nil } ``` -------------------------------- ### Example: Verification Decision Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/verify.md This Go code example shows how to iterate through the signers in a verification response and make a decision about the validity of each signature based on multiple criteria, printing the outcome and specific reasons for invalidity. ```go package main import ( "fmt" "os" "github.com/digitorus/pdfsign/verify" ) func main() { file, _ := os.Open("document.pdf") resp, _ := verify.VerifyFile(file) for _, signer := range resp.Signers { // Require all conditions for acceptance valid := signer.ValidSignature && signer.TrustedIssuer && !signer.RevokedCertificate && signer.TimestampStatus == "valid" && signer.TimestampTrusted && len(signer.TimeWarnings) == 0 fmt.Printf("Signer %s: %v\n", signer.Name, valid) if !signer.ValidSignature { fmt.Println(" ✗ Signature is invalid") } if !signer.TrustedIssuer { fmt.Println(" ✗ Issuer not trusted") } if signer.RevokedCertificate { fmt.Println(" ✗ Certificate is revoked") } if signer.TimestampStatus != "valid" { fmt.Println(" ✗ No valid timestamp") } } } ``` -------------------------------- ### Certificate Validation Errors Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/errors.md Example Go code for iterating through certificates and checking for various validation errors like chain issues, key usage, and EKU. ```go for _, signer := range response.Signers { for i, cert := range signer.Certificates { if cert.VerifyError != "" { fmt.Printf("Certificate %d verify error: %s\n", i, cert.VerifyError) } if !cert.KeyUsageValid && cert.KeyUsageError != "" { fmt.Printf("Key usage error: %s\n", cert.KeyUsageError) } if !cert.ExtKeyUsageValid && cert.ExtKeyUsageError != "" { fmt.Printf("EKU error: %s\n", cert.ExtKeyUsageError) } } } ``` -------------------------------- ### Verify() Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/verify.md Illustrates how to verify a PDF using an io.ReaderAt and its size, suitable for in-memory data or custom readers. ```go package main import ( "bytes" "os" "github.com/digitorus/pdfsign/verify" ) func main() { // Read entire PDF into memory pdfData, _ := os.ReadFile("document.pdf") reader := bytes.NewReader(pdfData) // Verify response, _ := verify.Verify(reader, int64(len(pdfData))) for _, signer := range response.Signers { println("Valid:", signer.ValidSignature) } } ``` -------------------------------- ### Signing with Certificate Chain Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example of signing a PDF that includes a certificate chain file. ```bash pdfsign sign \ -name "Jane Smith" \ document.pdf signed.pdf cert.crt key.key chain.crt ``` -------------------------------- ### VerifyFileWithOptions() Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/verify.md Shows how to verify a PDF with custom verification options, including enabling external revocation checks and setting HTTP timeouts. ```go package main import ( "net/http" "os" "time" "github.com/digitorus/pdfsign/verify" ) func main() { file, _ := os.Open("document.pdf") defer file.Close() // Create custom options options := verify.DefaultVerifyOptions() options.EnableExternalRevocationCheck = true options.RequireNonRepudiation = true options.TrustSignatureTime = true options.HTTPTimeout = 30 * time.Second options.HTTPClient = &http.Client{ Timeout: 30 * time.Second, } // Verify with custom options response, err := verify.VerifyFileWithOptions(file, options) if err != nil { panic(err) } // Process response for _, signer := range response.Signers { fmt.Printf("Signer: %s\n", signer.Name) fmt.Printf("Valid: %v\n", signer.ValidSignature) // Check certificate revocation for _, cert := range signer.Certificates { if cert.RevokedBeforeSigning { fmt.Printf("WARNING: Certificate revoked before signing!\n") } } // Check timestamp if signer.TimestampStatus == "valid" { fmt.Printf("Timestamp: %v (trusted: %v)\n", signer.VerificationTime, signer.TimestampTrusted) } } } ``` -------------------------------- ### ApprovalSignature Configuration Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/configuration.md Example configuration for an Approval Signature with a visible signature. ```go SignData{ Signature: SignDataSignature{ CertType: sign.ApprovalSignature, DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesPerms, Info: SignDataSignatureInfo{ Name: "John Doe", }, }, Signer: privateKey, Certificate: certificate, Appearance: sign.Appearance{ Visible: true, Page: 1, LowerLeftX: 50, LowerLeftY: 50, UpperRightX: 200, UpperRightY: 100, Image: imageData, // JPG or PNG bytes }, } ``` -------------------------------- ### Signature Verification Errors Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/errors.md Example Go code demonstrating how to check for general signature verification errors and individual signer states. ```go response, _ := verify.VerifyFile(file) if response.Error != "" { println("Verification error:", response.Error) return } for _, signer := range response.Signers { if !signer.ValidSignature { println("Signature is mathematically invalid") } if !signer.TrustedIssuer { println("Certificate issuer is not trusted") } if signer.RevokedCertificate { println("Certificate was revoked") } } ``` -------------------------------- ### PDF Verification Examples Source: https://github.com/digitorus/pdfsign/blob/main/README.md Various verification scenarios ranging from basic checks to high-security configurations. ```bash # Basic verification (always uses embedded timestamps when present) ./pdfsign verify document.pdf # Verification with external revocation checking ./pdfsign verify -external -http-timeout=30s document.pdf # Verification trusting signature time as fallback ./pdfsign verify -trust-signature-time document.pdf # Highest security verification (requires Non-Repudiation key usage) ./pdfsign verify -require-non-repudiation -external document.pdf # Verification allowing self-signed certificates ./pdfsign verify -allow-untrusted-roots self-signed.pdf ``` -------------------------------- ### Handling Missing Certificate Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/errors.md Example demonstrating how to handle missing certificates, considering timestamp signatures. ```go // For timestamp signatures, certificate is not needed if certType == sign.TimeStampSignature { // OK to have nil certificate } else { // Certificate is required if signData.Certificate == nil { println("Error: certificate required for this signature type") } } ``` -------------------------------- ### Future Revocation Check Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/revocation.md An example demonstrating how the revocation check will function once fully implemented, including adding CRL and OCSP data and checking a certificate's status. ```go package main import ( "crypto/x509" "github.com/digitorus/pdfsign/revocation" ) func main() { // Create revocation info with CRL and OCSP var revInfo revocation.InfoArchival revInfo.AddCRL(crlBytes) revInfo.AddOCSP(ocspBytes) // Load certificate to check cert := loadCertificate("cert.crt") // Check revocation status if revInfo.IsRevoked(cert) { println("Certificate is revoked") } else { println("Certificate is not revoked") } } ``` -------------------------------- ### PDF Parse Errors Example (Verify) Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/errors.md Example of handling PDF parsing errors and checking for the presence of digital signatures. ```go response, err := verify.VerifyFile(file) if err != nil { if strings.Contains(err.Error(), "no digital signature") { println("This PDF is not signed") } else { println("PDF parse error:", err) } return } if len(response.Signers) == 0 { println("No verifiable signatures found") } ``` -------------------------------- ### Sign a PDF Document in Go Source: https://github.com/digitorus/pdfsign/blob/main/README.md Use this snippet to perform basic PDF signing. Ensure you have your certificate and private key loaded. This example uses SHA256 for hashing and a public TSA for timestamping. ```go package main import ( "crypto" "os" "time" "github.com/digitorus/pdf" "github.com/digitorus/pdfsign/sign" ) func main() { inputFile, err := os.Open("input.pdf") if err != nil { panic(err) } defer inputFile.Close() outputFile, err := os.Create("output.pdf") if err != nil { panic(err) } defer outputFile.Close() // Load certificate and private key certificate := loadCertificate("cert.crt") privateKey := loadPrivateKey("key.key") err = sign.SignFile("input.pdf", "output.pdf", sign.SignData{ Signature: sign.SignDataSignature{ Info: sign.SignDataSignatureInfo{ Name: "John Doe", Location: "New York", Reason: "Document approval", ContactInfo: "john@example.com", Date: time.Now().Local(), }, CertType: sign.CertificationSignature, DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesPerms, }, Signer: privateKey, DigestAlgorithm: crypto.SHA256, Certificate: certificate, TSA: sign.TSA{ URL: "https://freetsa.org/tsr", }, }) if err != nil { panic(err) } } ``` -------------------------------- ### Sign Command with -reason option Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example of signing a PDF with a specified reason for signing. ```bash pdfsign sign -reason "Document approval" input.pdf output.pdf cert.crt key.key ``` -------------------------------- ### Timestamp Verification Errors Example Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/errors.md Example Go code to check timestamp status, including missing, invalid, or untrusted timestamps, and any associated time warnings. ```go for _, signer := range response.Signers { if signer.TimestampStatus == "missing" { fmt.Printf("No embedded timestamp for %s\n", signer.Name) } else if signer.TimestampStatus == "invalid" { fmt.Printf("Timestamp validation failed\n") } else if !signer.TimestampTrusted { fmt.Printf("Timestamp certificate chain not trusted\n") } for _, warning := range signer.TimeWarnings { fmt.Printf("Time warning: %s\n", warning) } } ``` -------------------------------- ### TimeStampSignature Configuration Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/configuration.md Example configuration for a Time Stamp Signature (no certificate needed). ```go SignData{ Signature: SignDataSignature{ CertType: sign.TimeStampSignature, Info: SignDataSignatureInfo{}, }, TSA: sign.TSA{ URL: "https://freetsa.org/tsr", }, } ``` -------------------------------- ### Custom Revocation Fetcher Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/configuration.md Example of a custom function to fetch revocation information (OCSP/CRL) dynamically. ```go func customRevocationFetcher(cert, issuer *x509.Certificate, i *revocation.InfoArchival) error { // Fetch OCSP ocspResponse, err := fetchFromOCSPServer(cert, issuer) if err == nil { i.AddOCSP(ocspResponse) } // Fetch CRL crlData, err := fetchFromCRLServer(cert) if err == nil { i.AddCRL(crlData) } return nil } SignData{ Certificate: certificate, RevocationFunction: customRevocationFetcher, // ... other fields } ``` -------------------------------- ### Sign Command with -contact option Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example of signing a PDF with specified contact information. ```bash pdfsign sign -contact "john@example.com" input.pdf output.pdf cert.crt key.key ``` -------------------------------- ### Sign Command with -location option Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example of signing a PDF with a specified signing location. ```bash pdfsign sign -location "New York" input.pdf output.pdf cert.crt key.key ``` -------------------------------- ### Simple Signature Usage Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/README.md Example of how to perform a simple signature on a PDF file. ```go sign.SignFile("input.pdf", "output.pdf", sign.SignData{ Signature: sign.SignDataSignature{ CertType: sign.CertificationSignature, Info: sign.SignDataSignatureInfo{Name: "Signer"}, }, Signer: key, Certificate: cert, }) ``` -------------------------------- ### Sign Command with -certType option Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example of signing a PDF with a specific certificate type. ```bash pdfsign sign -certType "ApprovalSignature" input.pdf output.pdf cert.crt key.key ``` -------------------------------- ### Get Default Verification Options and Customize Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/verify.md Shows how to obtain default verification options using `DefaultVerifyOptions`, inspect their settings, customize them, and then use them for verification. ```go package main import ( "fmt" "os" "github.com/digitorus/pdfsign/verify" ) func main() { // Get defaults options := verify.DefaultVerifyOptions() // Inspect settings fmt.Printf("Require Digital Signature KU: %v\n", options.RequireDigitalSignatureKU) fmt.Printf("Require Non-Repudiation: %v\n", options.RequireNonRepudiation) fmt.Printf("Allow Untrusted Roots: %v\n", options.AllowUntrustedRoots) fmt.Printf("External Revocation Check: %v\n", options.EnableExternalRevocationCheck) // Customize as needed options.RequireNonRepudiation = true options.EnableExternalRevocationCheck = true // Use customized options file, _ := os.Open("document.pdf") defer file.Close() response, _ := verify.VerifyFileWithOptions(file, options) fmt.Printf("Valid signatures: %d\n", len(response.Signers)) } ``` -------------------------------- ### Sign Command with -name option Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example of signing a PDF with a specified signer's name. ```bash pdfsign sign -name "John Doe" input.pdf output.pdf cert.crt key.key ``` -------------------------------- ### Signing with Custom TSA Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example of signing a PDF and using a custom Time-Stamp Authority (TSA) URL. ```bash pdfsign sign -tsa "http://internal-tsa.example.com/tsr" \ document.pdf signed.pdf cert.crt key.key ``` -------------------------------- ### Timestamp-Only Signature Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example of creating a timestamp-only signature without a certificate or private key. ```bash pdfsign sign -certType "TimeStampSignature" \ document.pdf signed.pdf ``` -------------------------------- ### Error Handling Best Practice 1: Check Both Error Return and Response Fields Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/errors.md Example Go code illustrating the best practice of checking both the returned error and the response fields for verification issues. ```go response, err := verify.VerifyFileWithOptions(file, options) if err != nil { // Handle I/O or parse errors println("Failed to verify:", err) return } // Check response-level error if response.Error != "" { println("Verification error:", response.Error) return } // Check individual signature results for _, signer := range response.Signers { // Handle individual signature issues if !signer.ValidSignature { println("Signature invalid") } } ``` -------------------------------- ### File I/O Errors Handling Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/errors.md Example of how to handle file I/O errors when signing a PDF. ```go err := sign.SignFile("input.pdf", "output.pdf", signData) if err != nil { if os.IsNotExist(err) { println("Input PDF not found") } else if os.IsPermission(err) { println("Permission denied for output file") } else { println("Error:", err) } } ``` -------------------------------- ### Sign a PDF (Library) Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/README.md Example of signing a PDF document using the pdfsign library in Go. ```go package main import ( "crypto" "os" "time" "github.com/digitorus/pdfsign/sign" ) func main() { err := sign.SignFile("input.pdf", "output.pdf", sign.SignData{ Signature: sign.SignDataSignature{ CertType: sign.CertificationSignature, Info: sign.SignDataSignatureInfo{ Name: "John Doe", Date: time.Now(), }, }, Signer: privateKey, Certificate: certificate, DigestAlgorithm: crypto.SHA256, TSA: sign.TSA{ URL: "https://freetsa.org/tsr", }, }) if err != nil { panic(err) } } ``` -------------------------------- ### Verify a PDF (Library) Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/README.md Example of verifying a PDF document using the pdfsign library in Go. ```go package main import ( "os" "github.com/digitorus/pdfsign/verify" ) func main() { file, _ := os.Open("document.pdf") defer file.Close() response, _ := verify.VerifyFile(file) for _, signer := range response.Signers { println("Signer:", signer.Name) println("Valid:", signer.ValidSignature) println("Trusted:", signer.TrustedIssuer) } } ``` -------------------------------- ### Advanced PDF Verification with Timestamp and External Checking in Go Source: https://github.com/digitorus/pdfsign/blob/main/README.md Perform advanced PDF verification with options for external revocation checking, timestamp validation, and custom HTTP timeouts. This example also shows how to configure a custom HTTP client for proxy support. ```go package main import ( "net/http" "time" "github.com/digitorus/pdfsign/verify" ) func main() { file, err := os.Open("document.pdf") if err != nil { panic(err) } defer file.Close() options := verify.DefaultVerifyOptions() options.EnableExternalRevocationCheck = true options.TrustSignatureTime = true // Allow fallback to signature time options.ValidateTimestampCertificates = true // Always validate timestamp certs options.HTTPTimeout = 15 * time.Second // Optional: Custom HTTP client for proxy support options.HTTPClient = &http.Client{ Timeout: 20 * time.Second, } response, err := verify.VerifyFileWithOptions(file, options) if err != nil { panic(err) } // Check timestamp validation results for _, signer := range response.Signers { fmt.Printf("Time source: %s\n", signer.TimeSource) fmt.Printf("Timestamp status: %s\n", signer.TimestampStatus) fmt.Printf("Timestamp trusted: %v\n", signer.TimestampTrusted) if len(signer.TimeWarnings) > 0 { fmt.Println("Time warnings:") for _, warning := range signer.TimeWarnings { fmt.Printf(" - %s\n", warning) } } } } ``` -------------------------------- ### Sign Command with -tsa option Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example of signing a PDF and embedding a timestamp from a specified TSA. ```bash pdfsign sign -tsa "https://freetsa.org/tsr" input.pdf output.pdf cert.crt key.key ``` -------------------------------- ### Visible Approval Usage Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/README.md Example demonstrating how to add a visible approval signature with an image to a PDF. ```go sign.SignFile("input.pdf", "output.pdf", sign.SignData{ Signature: sign.SignDataSignature{ CertType: sign.ApprovalSignature, Info: sign.SignDataSignatureInfo{Name: "Approved"}, }, Appearance: sign.Appearance{ Visible: true, LowerLeftX: 50, LowerLeftY: 50, UpperRightX: 200, UpperRightY: 100, Image: imageData, }, Signer: key, Certificate: cert, }) ``` -------------------------------- ### Verification Output Structure Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Example JSON output structure for the pdfsign verify command, detailing error messages, document information, and signer details. ```json { "error": "", "document_info": { "author": "...", "title": "...", "pages": 5, "creation_date": "...", "mod_date": "..." }, "signers": [ { "name": "John Doe", "reason": "Document approval", "location": "New York", "contact_info": "john@example.com", "valid_signature": true, "trusted_issuer": true, "revoked_certificate": false, "timestamp_status": "valid", "timestamp_trusted": true, "verification_time": "2024-01-15T10:30:00Z", "time_source": "embedded_timestamp", "certificates": [ { "certificate": {...}, "verify_error": "", "key_usage_valid": true, "ext_key_usage_valid": true, "ocsp_embedded": false, "ocsp_external": false, "crl_embedded": false, "crl_external": false, "revoked_before_signing": false } ] } ] } ``` -------------------------------- ### Error Handling Best Practice 2: Distinguish Between Different Error Conditions Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/errors.md Example Go code showing how to differentiate between various error conditions like signature validity, issuer trust, and revocation status. ```go for _, signer := range response.Signers { valid := signer.ValidSignature && signer.TrustedIssuer && !signer.RevokedCertificate && signer.TimestampStatus == "valid" if !signer.ValidSignature { // Signature tampered or forged println("CRITICAL: Signature is mathematically invalid") } else if !signer.TrustedIssuer { // Check if this is acceptable in your use case println("WARNING: Issuer not in trusted root list") } else if signer.RevokedCertificate { // Check if revocation happened before or after signing for _, cert := range signer.Certificates { if cert.RevokedBeforeSigning { println("CRITICAL: Certificate was revoked before signing") } else { println("INFO: Certificate revoked after signing (still valid at signing time)") } } } } ``` -------------------------------- ### Secure Verification Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/README.md Example of verifying a file with security options, including external revocation checks and non-repudiation. ```go options := verify.DefaultVerifyOptions() options.RequireNonRepudiation = true options.EnableExternalRevocationCheck = true response, _ := verify.VerifyFileWithOptions(file, options) // Check all conditions for _, signer := range response.Signers { valid := signer.ValidSignature && signer.TrustedIssuer && !signer.RevokedCertificate && signer.TimestampTrusted if valid { println("Signature accepted") } } ``` -------------------------------- ### Global Usage Source: https://github.com/digitorus/pdfsign/blob/main/_autodocs/api-reference/cli.md Shows how to display help information for the pdfsign CLI. ```bash pdfsign [options] pdfsign -h # Show help pdfsign --help # Show help pdfsign help # Show help ```