密钥在BouncyCastle的指定状态CryptographicException中无效

时间:2013-12-19 15:42:45

标签: vb.net security exception cryptography itextsharp

一直在搜索网页和博客,并在这里和那里找到废料,并尝试将它们放在一起,以便能够使用System.Security.Cryptography.X509Certificates使用iTextSharp库对PDF文件进行数字签名。

我有一个签名按钮,后面有以下代码:

    Dim m As New PdfManipulation
    Dim store As New X509Store("MY", StoreLocation.CurrentUser)
    store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)

    Dim collection As X509Certificate2Collection = CType(store.Certificates, X509Certificate2Collection)
    Dim fcollection As X509Certificate2Collection = CType(collection.Find(X509FindType.FindByTimeValid, DateTime.Now, False), X509Certificate2Collection)
    Dim scollection As X509Certificate2Collection = X509Certificate2UI.SelectFromCollection(fcollection, "Test Certificate Select", "Select a certificate from the following list to get information on that certificate", X509SelectionFlag.SingleSelection)

    For Each x509 As X509Certificate2 In scollection
        m.DigitallySignPdf("C:\Users\my\Desktop\populates.pdf", "C:\Users\my\Desktop\A.pdf", "topmostSubform[0].Page1[0].SignatureField1[0]", x509)
    Next x509

    store.Close()

以上代码有效,它打开了我的证书商店并选择了证书。然后它将证书传递给下面的PdfManiuplation类进行签名。

PdfManipulation代码:

Public Class PdfManipulation

Public Sub DigitallySignPdf(ByVal sourceDocument As String, _
                            ByVal destinationPath As String, _
                            ByVal fieldNameToSign As String, _
                            ByVal signature As X509Certificate2)

    Dim reader As New PdfReader(sourceDocument)
    Using fout As New FileStream(destinationPath, FileMode.Create, FileAccess.ReadWrite)
        Using stamper As PdfStamper = PdfStamper.CreateSignature(reader, fout, ControlChars.NullChar)
            ' appearance
            Dim appearance As PdfSignatureAppearance = stamper.SignatureAppearance
            appearance.SetVisibleSignature(fieldNameToSign)

            ' digital signature
            Dim akp = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(signature.PrivateKey).Private
            Dim es As IExternalSignature = New PrivateKeySignature(akp, "SHA-256")
            Dim cp As New Org.BouncyCastle.X509.X509CertificateParser()


            MakeSignature.SignDetached(appearance, es, New Org.BouncyCastle.X509.X509Certificate() {cp.ReadCertificate(signature.RawData)}, Nothing, Nothing, Nothing, 0, CryptoStandard.CMS)

            stamper.Close()

        End Using
    End Using

End Sub

End Class

当它到达

Dim akp = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(signature.PrivateKey).Private

抛出异常时的那些。我选择的证书与我在机器上签署的所有证书相同,所以我知道它很好。任何帮助,为什么这将抛出这个错误将非常感激,或指向正确的方向。

此处还有我的进口清单:

Imports System.Security.Cryptography
Imports System.Security.Permissions
Imports System.IO
Imports System.Security.Cryptography.X509Certificates
Imports iTextSharp.text.pdf.security
Imports iTextSharp.text
Imports iTextSharp.text.pdf

并且必须添加对:

的引用
System.Security

堆栈跟踪:

    System.Security.Cryptography.CryptographicException was unhandled
  HResult=-2146893813
  Message=Key not valid for use in specified state.

  Source=mscorlib
  StackTrace:
       at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
       at System.Security.Cryptography.Utils._ExportKey(SafeKeyHandle hKey, Int32 blobType, Object cspObject)
       at System.Security.Cryptography.RSACryptoServiceProvider.ExportParameters(Boolean includePrivateParameters)
       at Org.BouncyCastle.Security.DotNetUtilities.GetRsaKeyPair(RSA rsa)
       at Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(AsymmetricAlgorithm privateKey)
       at AccessRequest.PdfManipulation.DigitallySignPdf(String sourceDocument, String destinationPath, String fieldNameToSign, X509Certificate2 signature) in C:\PdfManipulation.vb:line 237
       at Form.btnSubmit_Click(Object sender, EventArgs e) in C:\Form.vb:line 251
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(ApplicationContext context)
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       at app.My.MyApplication.Main(String[] Args) in 11111.vb:line 81
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

在进一步测试并通过IDE查看私钥后,我注意到了

signature.privatekey.CspKeyContainerInfo.Exportable = False

这可能是错误的原因,如果是这样,如何使选定的证书可导出?我通过搜索看到的唯一事实是创建一个新证书并将StorageFlag设置为Exportable,我不是要创建一个新证书。我只是想使用所选的证书。

1 个答案:

答案 0 :(得分:4)

错误是由于私人证书可导出。

我一直在想我的所有测试为什么我的智能卡引脚都没有被提示我选择的证书。这导致我最终选择了一个我知道不会要求销售的证书,而且中提琴,pdf导出并签名。甚至单步执行代码来查看证书privatekey属性,这次它读取

signature.privatekey.CspKeyContainerInfo.Exportable = True

最终与我发现的另一种形式相匹配,表示他们通过使私钥可导出来修复错误。现在我所要做的就是弄清楚如何使用证书来完成这项工作,这些证书应该让我知道我的销钉。如果我发现这个问题,我会在这里回复。