返回顶部
首页 > 资讯 > 后端开发 > GO >使用 digitalorus/pdfsign 在 Go (Golang) 中签署 pdf 文件
  • 958
分享到

使用 digitalorus/pdfsign 在 Go (Golang) 中签署 pdf 文件

go语言标准库 2024-02-09 10:02:27 958人浏览 安东尼
摘要

在Go语言中签署pdf文件是一项常见的需求,而使用digitalorus/pdfsign库可以轻松实现这一功能。PHP小编柚子为您介绍该库的使用方法。无论是在业务应用中还是在个人项目中

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 标准库文档以获取更多信息。

第三步是打开输入 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

以上就是使用 digitalorus/pdfsign 在 Go (Golang) 中签署 pdf 文件的详细内容,更多请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: 使用 digitalorus/pdfsign 在 Go (Golang) 中签署 pdf 文件

本文链接: https://lsjlt.com/news/562377.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 使用 digitalorus/pdfsign 在 Go (Golang) 中签署 pdf 文件
    在Go语言中签署PDF文件是一项常见的需求,而使用digitalorus/pdfsign库可以轻松实现这一功能。php小编柚子为您介绍该库的使用方法。无论是在业务应用中还是在个人项目中...
    99+
    2024-02-09
    go语言 标准库
  • 使用 PHP 在 HTML 中下载 PDF 文件
    本篇文章将讨论使用 PHP 在 HTML 链接中下载 PDF 文件的步骤。 我们将使用 PHP header() 函数来提示用户保存我们的 PDF 文件。 PHP 中 header() 函数的语法...
    99+
    2024-02-27
  • 如何在vue中使用pdfjs预览pdf文件
    目录前言 思考 库目录解析和下载 使用方法 文件位置 实际调用 问题 总结 前言 在写项目的过程中,偶尔会有使用到pdf的文件,当我们想看pdf文件的时候,你的操作是不是先把pdf...
    99+
    2024-04-02
  • 如何使用Vue3+Vue-PDF实现PDF文件在线预览
    这篇文章主要介绍“如何使用Vue3+Vue-PDF实现PDF文件在线预览”,在日常操作中,相信很多人在如何使用Vue3+Vue-PDF实现PDF文件在线预览问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使...
    99+
    2023-07-06
  • 在 Go 中使用动态图像生成 PDF
    积累知识,胜过积蓄金银!毕竟在Golang开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《在 Go 中使用动态图像生成 PD...
    99+
    2024-04-04
  • 如何使用PDF.JS插件实现在HTML中预览PDF文件
    这篇文章给大家分享的是有关如何使用PDF.JS插件实现在HTML中预览PDF文件的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。PDF.js是一款基于HTML5建立的PDF阅读器,...
    99+
    2024-04-02
  • 在 Go (Golang) 中查找文件系统对象
    对于一个Golang开发者来说,牢固扎实的基础是十分重要的,编程网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《在 Go (Golang) 中查找文件系统对象》,主要介绍了,希望对大家的...
    99+
    2024-04-04
  • php利用tcpdf生成签名盖章的pdf文件并支持中文
    下载tcpdf github 代码: ...
    99+
    2023-09-29
    pdf php
  • 在 gitlab-ci/cd 中制作 golang deb 时,...中没有 Go 文件
    php小编西瓜将为您介绍在gitlab-ci/cd中制作golang deb时的一个常见问题。有时候,当我们尝试在gitlab-ci/cd中制作golang deb包时,可能会遇到一个...
    99+
    2024-02-13
  • 如何在golang中使用WebSocket进行文件传输
    如何在golang中使用WebSocket进行文件传输WebSocket是一种支持双向通信的网络协议,能够在浏览器和服务器之间建立持久的连接。在golang中,我们可以使用第三方库gorilla/websocket来实现WebSocket功...
    99+
    2023-12-18
    Golang websocket 文件传输
  • 如何在 Golang 中使用 RPC 实现文件上传?
    使用 rpc 实现文件上传:创建 rpc 服务器来处理文件上传请求,使用 net/rpc 包创建。创建 rpc 客户端来向服务器发起文件上传请求,使用 net/rpc 包创建,将文件序列...
    99+
    2024-05-13
    文件上传 rpc golang
  • 如何在 Golang 中使用 gRPC 实现文件上传?
    如何使用 grpc 实现文件上传?创建配套服务定义,包括请求和响应消息。在客户端,打开要上传的文件并将其分成块,然后通过 grpc 流流式传输发送到服务端。在服务端,接收文件块并将其存储...
    99+
    2024-05-13
    文件上传 grpc git golang
  • 如何在 Golang 中使用 WebSockets 实现文件上传?
    在 golang 中使用 websockets 实现文件上传,需要引入 "github.com/gorilla/websocket" 包,设置 websocket 路由和处理函数。使用 ...
    99+
    2024-05-13
    golang git
  • 本地pdf文件如何在Android应用中打开
    本地pdf文件如何在Android应用中打开?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.下载android-pdfview库2. android-pdfview的简单...
    99+
    2023-05-31
    android pdf roi
  • 如何在Go语言中使用Path索引文件?
    Go语言作为一门高效、简洁的编程语言,其应用范围越来越广泛。在Go语言中,使用Path索引文件是一项重要的操作,本文将介绍如何在Go语言中使用Path索引文件,包括相关概念、基本用法以及示例代码。 一、什么是Path索引文件? Path索引...
    99+
    2023-10-05
    path 索引 文件
  • 如何使用 Go 接口在 Bash 中加载文件?
    在本文中,我们将介绍如何使用 Go 接口在 Bash 中加载文件。Go 是一种高效的编程语言,它可以通过接口实现多态,同时 Bash 是一种常用的 shell 脚本语言,它可以用于处理文本和文件。通过结合使用这两种语言,我们可以实现在 Ba...
    99+
    2023-08-03
    接口 bash load
  • 如何在 Windows 系统中使用 Go 文件对象?
    在 Go 语言中,文件是一种常见的数据源和数据输出方式。Go 语言提供了一些操作文件的基本函数和类型,其中最基本的就是文件对象。文件对象是在程序中表示一个文件的结构体,通过文件对象可以进行文件的读取、写入、关闭等操作。本文将介绍如何在 W...
    99+
    2023-10-29
    文件 windows 对象
  • 如何在GO中使用API处理文件路径?
    在GO语言中,文件处理是一个常见的需求,而处理文件路径则是其中一个重要的部分。在本文中,我们将会介绍如何在GO语言中使用API处理文件路径。 GO语言中提供了path和filepath两个包来处理文件路径。path包提供了一些跨平台的路径处...
    99+
    2023-11-13
    api 文件 path
  • 在 golang 中使用一些未知标签解组 XML?
    在golang中,我们经常需要处理XML数据。然而,有时候我们可能会遇到一些未知的标签,这给解组XML数据带来了一些困难。那么,如何在golang中处理这些未知标签呢?在本文中,php...
    99+
    2024-02-08
    overflow
  • 如何在 Golang 中使用管道实现文件读写?
    通过管道进行文件读写:创建一个管道从文件读取数据并通过管道传递从管道中接收数据并处理将处理后的数据写入文件使用 goroutine 并发执行这些操作以提高性能 如何在 Golang 中...
    99+
    2024-05-15
    golang 管道 文件读写
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作