【问题标题】:MissingMethodException when signing a Pdf with iText7 and Vb.Net使用 iText7 和 Vb.Net 签署 Pdf 时出现 MissingMethodException
【发布时间】:2020-03-17 18:38:09
【问题描述】:

我正在尝试测试翻译成 Vb.Net 的 iText 文档示例,但在执行 pdfSigner.SignDetached(...) 时我得到下一个奇怪的异常

MissingMethodException:'System.Collections.IEnumerator Org.BouncyCastle.Asn1.Asn1Sequence.GetObjects()'

代码成功读取 pfx 证书和源文件,并创建目标文件,但在最后一步失败,导致目标文件损坏:

Imports System.IO
Imports Org.BouncyCastle.Crypto
Imports Org.BouncyCastle.X509
Imports iText.Kernel.Geom
Imports iText.Kernel.Pdf
Imports iText.Signatures
Imports Org.BouncyCastle.Pkcs

Public Class SignHelloWorld
        Public Shared ReadOnly root As String = Environment.GetFolderPath(Environment.SpecialFolder.Personal) & "\tmp\itext7\"
        Public Shared ReadOnly DEST As String = root & "results\signatures\chapter01\"
        Public Shared ReadOnly KEYSTORE As String = root & "resources\encryption\myCert.pfx"
        Public Shared ReadOnly SRC As String = root & "resources\pdfs\hello.pdf"
        Public Shared ReadOnly PASSWORD As Char() = "1234".ToCharArray()
        Public Shared ReadOnly RESULT_FILES As String() = {"hello_signed1.pdf", "hello_signed2.pdf", "hello_signed3.pdf", "hello_signed4.pdf"}

        Public Sub Sign(ByVal src As String, ByVal dest As String, ByVal chain As X509Certificate(), ByVal pk As ICipherParameters, ByVal digestAlgorithm As String, ByVal subfilter As PdfSigner.CryptoStandard, ByVal reason As String, ByVal location As String)
            Dim reader As PdfReader = New PdfReader(src)
            Dim signer As PdfSigner = New PdfSigner(reader, New FileStream(dest, FileMode.Create), New StampingProperties())
            Dim rect As Rectangle = New Rectangle(36, 648, 200, 100)
            Dim appearance As PdfSignatureAppearance = signer.GetSignatureAppearance()
            appearance.SetReason(reason).SetLocation(location).SetReuseAppearance(False).SetPageRect(rect).SetPageNumber(1)
            signer.SetFieldName("sig")
            Dim pks As IExternalSignature = New PrivateKeySignature(pk, digestAlgorithm)
            signer.SignDetached(pks, chain, Nothing, Nothing, Nothing, 0, subfilter)
            reader.Close()
        End Sub

        Public Shared Sub Main(ByVal args As String())
            Dim directory As DirectoryInfo = New DirectoryInfo(DEST)
            directory.Create()

            Dim pk12 As Pkcs12Store = New Pkcs12Store(New FileStream(KEYSTORE, FileMode.Open, FileAccess.Read), PASSWORD)
            Dim [alias] As String = Nothing

            For Each a In pk12.Aliases
                [alias] = (CStr(a))
                If pk12.IsKeyEntry([alias]) Then Exit For
            Next

            Dim pk As ICipherParameters = pk12.GetKey([alias]).Key
            Dim ce As X509CertificateEntry() = pk12.GetCertificateChain([alias])
            Dim chain As X509Certificate() = New X509Certificate(ce.Length - 1) {}

            For k As Integer = 0 To ce.Length - 1
                chain(k) = ce(k).Certificate
            Next

            Dim app As SignHelloWorld = New SignHelloWorld()
            app.Sign(SRC, DEST & RESULT_FILES(0), chain, pk, DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS, "Test 1", "Ghent")
            app.Sign(SRC, DEST & RESULT_FILES(1), chain, pk, DigestAlgorithms.SHA512, PdfSigner.CryptoStandard.CMS, "Test 2", "Ghent")
            app.Sign(SRC, DEST & RESULT_FILES(2), chain, pk, DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CADES, "Test 3", "Ghent")
            app.Sign(SRC, DEST & RESULT_FILES(3), chain, pk, DigestAlgorithms.RIPEMD160, PdfSigner.CryptoStandard.CADES, "Test 4", "Ghent")
        End Sub
End Class

【问题讨论】:

  • 通常在使用与构建代码不同版本的 DLL 时会出现此问题,运行时发现的 DLL 没有引用的方法。您是否使用任何绑定重定向来平息有关“定位的程序集与清单不匹配”的错误消息?
  • 我的 App.Config 有一个用于 BouncyCastle.Crypto 的 'bindingRedirect oldVersion="0.0.0.0-1.8.6.0" newVersion="1.8.6.0"',它确实已经是 1.8.6.0 版本。我试图删除它,但我遇到了同样的异常。
  • 好的,当它得到这个异常时,这段代码在哪里运行?在整台机器上搜索包含 bouncy castle crypto 的 DLL 名称(您可以在参考资料中查看) - 您找到了哪些版本的 dll?有旧的吗?可能其中一个旧版本(例如 1.7)会导致问题,因为它们不包含该方法,但应用程序正在查找并尝试使用旧 dll?
  • 你是对的,代码在另一台装有过时版本的 BouncyCastle 的计算机上运行成功

标签: vb.net itext bouncycastle


【解决方案1】:

据我所知,当前的 iText 7 开发版本 (7.1.11-SNAPSHOT) 是针对 BouncyCastle 1.8.5 编译的,实际上,在 BC 1.8.5 中,您可以在 Asn1Sequence.cs 中找到

    [Obsolete("Use GetEnumerator() instead")]
    public IEnumerator GetObjects()
    {
        return GetEnumerator();
    }

但在 BC 1.8.6 中,该方法已从 Asn1Sequence.cs 中删除。

因此,目前在使用 iText 7 v7.1.10 或更早版本进行开发时,请仍使用 BouncyCastle 1.8.5。


顺便说一句,BouncyCastle 以仅在微版本更改中引入 API 重大更改而闻名。大多数其他项目只会在一个版本中删除方法(即使标记为过时),如果没有在主要版本中,至少在次要版本中进行了更改。

因此,在使用 BC 时,您必须非常注意使用哪个确切版本。

【讨论】:

  • @ButaniVijay 我对那里的元数据细节知之甚少。如果您分析并显示了 pdf 文件中的实际差异,我可能会帮助使 itext 输出类似于 acrobat 输出。但是只有那个网站的输出,我不知道需要改变什么。
  • 感谢您的回复。我刚刚更新了我的问题并附上了两个 PDF。
  • 你检查了吗?
  • 我目前正忙于一个项目。可能我下周会找时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-06
  • 1970-01-01
  • 2020-05-05
相关资源
最近更新 更多