Heim >Backend-Entwicklung >Golang >Signieren Sie PDF-Dateien in Go (Golang) mit digitalorus/pdfsign
Das Signieren von PDF-Dateien in der Go-Sprache ist ein allgemeiner Bedarf, und diese Funktion kann mithilfe der Bibliothek digitalorus/pdfsign problemlos erreicht werden. Der PHP-Editor Youzi führt Sie in die Verwendung dieser Bibliothek ein. Ob bei Geschäftsanwendungen oder persönlichen Projekten: Das Signieren von PDF-Dateien ist ein häufiger Vorgang. Die digitalorus/pdfsign-Bibliothek bietet eine einfache und benutzerfreundliche Oberfläche, die das Signieren von PDF-Dateien in der Go-Sprache einfach und schnell macht. In diesem Artikel erfahren Sie, wie Sie die Bibliothek digitalorus/pdfsign in der Go-Sprache verwenden, um den Signierungsvorgang von PDF-Dateien abzuschließen. Lasst uns gemeinsam erkunden!
In Go (Golang) muss ich ein PDF-Dokument signieren, aber im Gegensatz zu anderen Sprachen gibt es keine Bibliothek, die die Arbeit erleichtert. Ich habe ein paar kostenpflichtige gefunden, aber sie waren keine Option.
Zuerst habe ich ein PKCS-Zertifikat (.p12), aus dem ich den privaten Schlüssel und das x509-Zertifikat mit diesem Paket extrahiert habe: https://pkg.go.dev/software.sslmate.com/src/go -pkcs12
Aber wenn ich ein PDF-Dokument signieren möchte, stecke ich fest, weil ich nicht weiß, wie ich Parameter richtig an eine Funktion übergebe, die einen solchen Vorgang ausführt. Das verwendete Paket ist https://pkg.go.dev/github.com/digitorus/pdfsign
Mein vollständiger Code lautet:
package main import ( "crypto" "fmt" "os" "time" "github.com/digitorus/pdf" "github.com/digitorus/pdfsign/revocation" "github.com/digitorus/pdfsign/sign" gopkcs12 "software.sslmate.com/src/go-pkcs12" ) func main() { certBytes, err := os.ReadFile("certificate.p12") if err != nil { fmt.Println(err) return } privateKey, certificate, chainCerts, err := gopkcs12.DecodeChain(certBytes, "MyPassword") if err != nil { fmt.Println(err) return } input_file, err := os.Open("input-file.pdf") if err != nil { fmt.Println(err) return } defer input_file.Close() output_file, err := os.Create("output-file.pdf") if err != nil { fmt.Println(err) return } defer output_file.Close() finfo, err := input_file.Stat() if err != nil { fmt.Println(err) return } size := finfo.Size() rdr, err := pdf.NewReader(input_file, size) if err != nil { fmt.Println(err) return } err = sign.Sign(input_file, output_file, rdr, size, sign.SignData{ Signature: sign.SignDataSignature{ Info: sign.SignDataSignatureInfo{ Name: "John Doe", Location: "Somewhere on the globe", Reason: "My season for siging this document", ContactInfo: "How you like", Date: time.Now().Local(), }, CertType: sign.CertificationSignature, DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesPerms, }, Signer: privateKey, // crypto.Signer DigestAlgorithm: crypto.SHA256, // hash algorithm for the digest creation Certificate: certificate, // x509.Certificate CertificateChains: chainCerts, // x509.Certificate.Verify() TSA: sign.TSA{ URL: "https://freetsa.org/tsr", Username: "", Password: "", }, // The follow options are likely to change in a future release // // cache revocation data when bulk signing RevocationData: revocation.InfoArchival{}, // custom revocation lookup RevocationFunction: sign.DefaultEmbedRevocationStatusFunction, }) if err != nil { fmt.Println(err) } else { fmt.Println("Signed PDF written to output.pdf") } }
Um genau zu sein, handelt es sich um die Parameter Signer und CertificateChains meiner Frage. Ich weiß nicht, wie man die Variablen privateKey und chainCerts richtig verwendet.
Der Meldungsfehler ist:
Ich bin neu in dieser Sprache und verstehe daher die detaillierten Konzepte und Datentypen immer noch nicht.
Danke, dass du mir gesagt hast, was ich sonst noch tun sollte oder welche Schritte mir fehlen, um erfolgreich zu sein. Oder ob jemand weiß, wie ich ein PDF basierend auf einem PKCS-Zertifikat signieren kann.
Das Signieren einer PDF-Datei mit einer digitalen Signatur erfordert die Generierung eines Schlüsselpaars mithilfe der Public-Key-Kryptographie. Der private Schlüssel wird zum Verschlüsseln der mit der Signatur verbundenen Daten verwendet und nur der Unterzeichner kann darauf zugreifen, während der öffentliche Schlüssel zum Entschlüsseln der Signaturdaten zur Überprüfung verwendet wird. Wenn er nicht von einer vertrauenswürdigen Zertifizierungsstelle ausgestellt wird, wird dieser öffentliche Schlüssel verwendet Das Zertifikat muss zum Zertifikatspeicher hinzugefügt werden, um es vertrauenswürdig zu machen. Im gegebenen Beispiel werden diese Signaturdaten in einer Struktur namens sign.SignData gespeichert, die Teil der pdfsign-Bibliothek ist und ein x509-Zertifikat und einen Unterzeichner erfordert, der die crypto.Signer-Schnittstelle implementiert.
Der erste Schritt besteht darin, mithilfe des crypto/ecdsa-Pakets in der Go-Standardbibliothek ein Schlüsselpaar zu generieren. GenerateKey speichert den privaten und öffentlichen Schlüssel in der Variablen privateKey. Diese zurückgegebene privateKey-Variable implementiert die crypto.Signer-Schnittstelle, die zur Lösung des Problems erforderlich ist, mit dem Sie derzeit konfrontiert sind.
Sie können dies überprüfen, indem Sie Zeile 142 des ecdsa.go-Codes lesen.
Sie verwenden derzeit gopkcs12.DecodeChain, um den privaten Schlüssel zurückzugeben, aber es implementiert nicht die crypto.Signer-Schnittstelle, daher der Fehler. Möglicherweise müssen Sie eine benutzerdefinierte Version implementieren, aber das ist eine andere Frage.
Konzept:
ECDSA steht für Elliptic Curve Digital Signature Algorithm. Es handelt sich um einen Verschlüsselungsalgorithmus mit öffentlichem Schlüssel, der für digitale Signaturen verwendet wird. Weitere Informationen finden Sie in der Dokumentation der Go-Standardbibliothek und auf der NIST-Website.
NIST P-384: P-384 ist eine der vom National Institute of Standards and Technology (NIST) empfohlenen elliptischen Kurven mit einer Schlüssellänge von 384 Bit. Weitere Informationen zu digitalen Signaturen und weitere empfohlene elliptische Kurven finden Sie auf der NIST-Website. Als Arbeitslösung verwende ich den P-384.
第二步是使用Go标准库中的crypto/x509包通过其链生成器生成x509证书和证书链。这些是您在问题中寻求帮助的特定变量,但不属于您在错误消息中可以清楚看到的预期类型。只需遵循 lib 指令并使用 x509.Certificate.Verify() 就像我在工作解决方案中所做的那样,这将返回正确的类型 [][]*x509.Certificate。
请参阅 Go 标准库文档以获取更多信息。
第三步是打开输入 pdf 文件并使用 Go 标准库中的 os 包创建输出 pdf 文件。
第四步实际上是使用 digitalorus/pdfsign 库对 pdf 文件进行签名。
这是我今天编码和测试的一个有效解决方案,旨在让您回到正轨,进行一些研究并根据您的需求进行修改:
package main import ( "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "fmt" "github.com/digitorus/pdf" "github.com/digitorus/pdfsign/revocation" "github.com/digitorus/pdfsign/sign" "log" "math/big" "os" "time" ) func main() { // First step privateKey, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) if err != nil { panic(err) } // Second step x509RootCertificate := &x509.Certificate{ SerialNumber: big.NewInt(2023), Subject: pkix.Name{ Organization: []string{"Your Organization"}, Country: []string{"Your Country"}, Province: []string{"Your Province"}, Locality: []string{"Your Locality"}, StreetAddress: []string{"Your Street Address"}, PostalCode: []string{"Your Postal Code"}, }, NotBefore: time.Now(), NotAfter: time.Now().AddDate(10, 0, 0), IsCA: true, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, } rootCertificateBytes, err := x509.CreateCertificate(rand.Reader, x509RootCertificate, x509RootCertificate, &privateKey.PublicKey, privateKey) if err != nil { panic(err) } rootCertificate, err := x509.ParseCertificate(rootCertificateBytes) if err != nil { panic(err) } roots := x509.NewCertPool() roots.AddCert(rootCertificate) certificateChain, err := rootCertificate.Verify(x509.VerifyOptions{ Roots: roots, }) if err != nil { panic(err) } // Third step outputFile, err := os.Create("output.pdf") if err != nil { panic(err) } defer func(outputFile *os.File) { err = outputFile.Close() if err != nil { log.Println(err) } fmt.Println("output file closed") }(outputFile) inputFile, err := os.Open("input.pdf") if err != nil { panic(err) } defer func(inputFile *os.File) { err = inputFile.Close() if err != nil { log.Println(err) } fmt.Println("input file closed") }(inputFile) fileInfo, err := inputFile.Stat() if err != nil { panic(err) } size := fileInfo.Size() pdfReader, err := pdf.NewReader(inputFile, size) if err != nil { panic(err) } // Fourth step err = sign.Sign(inputFile, outputFile, pdfReader, size, sign.SignData{ Signature: sign.SignDataSignature{ Info: sign.SignDataSignatureInfo{ Name: "Your name", Location: "Your location", Reason: "Your reason", ContactInfo: "Your contact info", Date: time.Now().Local(), }, CertType: sign.CertificationSignature, DocMDPPerm: sign.AllowFillingExistingFormFieldsAndSignaturesPerms, }, Signer: privateKey, // crypto.Signer DigestAlgorithm: crypto.SHA256, // hash algorithm for the digest creation Certificate: rootCertificate, // x509.Certificate CertificateChains: certificateChain, // x509.Certificate.Verify() TSA: sign.TSA{ URL: "", Username: "", Password: "", }, // The follow options are likely to change in a future release // // cache revocation data when bulk signing RevocationData: revocation.InfoArchival{}, // custom revocation lookup RevocationFunction: sign.DefaultEmbedRevocationStatusFunction, }) if err != nil { log.Println(err) } else { log.Println("pdf signed") } }
结果:
go run main.go 2023/12/01 21:53:37 pdf signed input file closed output file closed
Das obige ist der detaillierte Inhalt vonSignieren Sie PDF-Dateien in Go (Golang) mit digitalorus/pdfsign. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!