Search code examples
x509certificate2capicom

CAPICOM and X509


I have a web application form. The aim is to create a xml of data from web form and sign it with the user usb certificate. I am using CAPICOM.store to successfully open all user certificate. When I click on one that I want I exported it. After that I am importing selected certificate in X509Cetificate2 to sign xml. But in my code I am getting error on line signedXml.ComputeSignature() and message is 'Signing key is not loaded.' Please any help or suggestion to fix this.

    Function SignXML(uppXML As String) As String

    Dim bResult As Boolean = False
    Dim pCertContext As IntPtr = IntPtr.Zero
    Dim doc As XmlDocument = Nothing
    Dim signedXml As SignedXml = Nothing
    Dim reference As Reference = Nothing
    Dim trns As XmlDsigC14NTransform = Nothing
    Dim env As XmlDsigEnvelopedSignatureTransform = Nothing
    Dim keyInfo As KeyInfo = Nothing
    Dim xmlDigitalSignature As XmlElement = Nothing 

    Dim hideFiledCapicom As String = Replace(txtCapicom.Text, " ", "+")
    Dim certificate As New X509Certificate2(Convert.FromBase64String(hideFiledCapicom)) 
        Dim key As AsymmetricAlgorithm = certificate.PrivateKey

        doc = New XmlDocument
        doc.PreserveWhitespace = True
        doc.LoadXml(uppXML)

        signedXml = New SignedXml(doc)
        signedXml.SigningKey = key

        reference = New Reference
        reference.Uri = ""

        trns = New XmlDsigC14NTransform

        reference.AddTransform(trns)

        env = New XmlDsigEnvelopedSignatureTransform

        reference.AddTransform(env)

        signedXml.AddReference(reference)

        keyInfo = New KeyInfo()
        keyInfo.AddClause(New KeyInfoX509Data(certificate))

        signedXml.KeyInfo = keyInfo
        signedXml.ComputeSignature()

        xmlDigitalSignature = signedXml.GetXml()

        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))

        If TypeOf doc.FirstChild Is XmlDeclaration Then
            doc.RemoveChild(doc.FirstChild)
        End If

        uppXML = doc.OuterXml

    Return uppXML

End Function

Solution

  • I found solution for this.

    In JavaScript where I use CAPICOM to choose and export certificate I am also getting and the private key from certificate and putting it in hidden fields.

     var privateKey = certificates.Item(1).PrivateKey.KeySpec
    
     var exportKey = document.getElementById("<%=hideFieldKey.ClientID%>");
         exportKey = privateKey
         document.getElementById('HiddenKey').value = exportKey;
    

    In my vb code I use CspParameters() to get private key and RSACryptoServiceProvider() to proceed further for signing xml document.