日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

在Go語言中簽署PDF文件是一項常見的需求,而使用digitalorus/pdfsign庫可以輕松實現這一功能。php小編柚子為您介紹該庫的使用方法。無論是在業務應用中還是在個人項目中,簽署PDF文件都是一個常見的操作。digitalorus/pdfsign庫提供了簡潔易用的接口,使得在Go語言中簽署PDF文件變得簡單快捷。通過本文,您將了解到如何在Go語言中使用digitalorus/pdfsign庫來完成PDF文件的簽署操作。讓我們一起來探索吧!

問題內容

在 go (golang) 中,我需要簽署 pdf 文檔,但與其他語言不同的是,沒有任何庫可以使工作變得更容易。我找到了幾個付費的,但它們不是一個選擇。

首先,我有一個 PKCS 證書 (.p12),我已經使用此包從中提取私鑰和 x509 證書:https://pkg.go.dev/software.sslmate.com/src/go -pkcs12

但是當我想簽署 pdf 文檔時,我陷入了困境,因為我不知道如何正確地將參數傳遞給執行此類操作的函數。使用的包是https://pkg.go.dev/github.com/digitorus/pdfsign

我的完整代碼是:

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")
    }
}

登錄后復制

確切地說,它們是我的問題的Signer和CertificateChains參數。我不知道如何正確使用 privateKey 和 chainCerts 變量。

消息錯誤是:

無法使用 privateKey(interface{} 類型的變量)作為結構文字中的 crypto.Signer 值:interface{} 未實現 crypto.Signer(缺少 Public 方法)
無法使用 chainCertificates([]*x509.Certificate 類型的變量)作為結構體文字中的 [][]*x509.Certificate 值

我是這門語言的新手,所以我仍然不了解深入的概念和數據類型。

感謝您告訴我還應該做什么或缺少哪些步驟才能取得成功。或者如果有人知道我如何根據 pkcs 證書簽署 pdf。

解決方法

使用數字簽名對 PDF 進行簽名包括使用公鑰加密技術生成一對密鑰。私鑰用于加密與簽名相關的數據,只有簽名者才能訪問它,而公鑰則用于解密簽名數據以進行驗證,如果不是由受信任的證書頒發機構頒發,則所述公鑰證書必須將其添加到證書存儲中以使其受到信任。
在給定的示例中,此簽名數據存儲在名為 sign.SignData 的結構內,該結構是 pdfsign 庫的一部分,需要 x509 證書和實現 crypto.Signer 接口的簽名者。

第一步是使用 Go 標準庫中的 crypto/ecdsa 包生成一對密鑰。 GenerateKey 將把私鑰和公鑰保存到 privateKey 變量中。這個返回的 privateKey 變量實現了 crypto.Signer 接口,這是解決您當前面臨的問題所必需的。

您可以通過閱讀 ecdsa.go 代碼第 142 行來檢查這一點。

https://github.com/golang /go/blob/master/src/crypto/ecdsa/ecdsa.go

您當前正在使用 gopkcs12.DecodeChain 返回私鑰,但它沒有實現 crypto.Signer 接口,因此會出現錯誤。您可能需要實現一個自定義的,但這是另一個問題。

概念:

ECDSA 代表橢圓曲線數字簽名算法。它是一種用于數字簽名的公鑰加密算法。請參閱 Go 標準庫文檔和 NIST 網站了解更多信息。

https://pkg.go.dev/crypto/[電子郵件受保護]
https://www.php.cn/link/813b6a28cc4ac72d244266161e3e2eb4

NIST P-384:P-384 是美國國家標準與技術研究院 (NIST) 推薦的橢圓曲線之一,密鑰長度為 384 位。有關數字簽名和更多推薦的橢圓曲線的更多信息,請參閱 NIST 網站。我使用 P-384 作為工作解決方案。

https://nvlpubs.nist.gov/nistpubs /FIPS/NIST.FIPS.186-4.pdf
https://www.php.cn/link/73c66ed635c83ba1316b28524a31b12f
https://csrc.nist.gov/pubs/fips/186 -4/國際泳聯

第二步是使用Go標準庫中的crypto/x509包通過其鏈生成器生成x509證書和證書鏈。這些是您在問題中尋求幫助的特定變量,但不屬于您在錯誤消息中可以清楚看到的預期類型。只需遵循 lib 指令并使用 x509.Certificate.Verify() 就像我在工作解決方案中所做的那樣,這將返回正確的類型 [][]*x509.Certificate。

請參閱 Go 標準庫文檔以獲取更多信息。

https://www.php.cn/link/92d1e1eb1cd6f9fba3227870bb6d7f07
https://www.php.cn/link/54d2e69c08f60ae7c37f509f962c59a8
https://www.php.cn/link/6afd3a1bbb557f8e05f45ded7bf96836

第三步是打開輸入 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

登錄后復制

分享到:
標簽:Go語言 標準庫
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定