Search code examples
javascriptxmlsignverifycapicom

Verify private key in signed XML with public key


I use javascript to open CAPICOM store to choose certificate. After that I export selected certificate, public key and private key of that certificate and put them in three hidden fields.

    var privateKey = certificates.Item(1).PrivateKey;
    var cert = certificates.Item(1);
    var publicKey = cert.PublicKey().EncodedKey.Value

When signing xml I used:

To take certificate

    Dim hideCertCapicom As String = Replace(HiddenCert.Value, " ", "+")
    Dim certificate As New X509Certificate2(Convert.FromBase64String(hideCertCapicom))

For defining private key I used

    Dim keyC As String = hideKey 

    Dim cspp As New CspParameters()
    cspp.KeyContainerName = keyC

    Dim tmpRsa As New RSACryptoServiceProvider(cspp)
    tmpRsa.PersistKeyInCsp = True

This will successfully signed my xml.

For verifying xml I used:

    Dim hidePublicKey As String = HiddenPublicKey.Value

    Dim keyC As String = hidePublicKey

    Dim cspp As New CspParameters()
    cspp.KeyContainerName = keyC 

    Dim tmpRsa As New RSACryptoServiceProvider(cspp)
    tmpRsa.PersistKeyInCsp = True

But this doesn't work. It works only if I use the private key again.

Is it good practice to sign and verify with the same private key or to do both with public key?


Solution

  • I was able to sign with private key and verify the signature with public key, and I want to share with you.

    In SignXml() function I exported public key from private key:

     Dim publicKey as String = tmpRsa.ToXmlString(False) 
    

    Then in the same function I call verifyXml() function:

     Dim verifySign As Boolean
    
     verifySign = VerifyXml(doc, publicKey)
    

    In verifyXml() function I took public key on this way:

    Public Function VerifyXml(Doc As XmlDocument, Key As String) As Boolean
    
     Dim tmpRsa As New RSACryptoServiceProvider()
     tmpRsa.FromXmlString(Key)
    
     Dim signedXml As New SignedXml(Doc)
    
     Dim nodeList As XmlNodeList = Doc.GetElementsByTagName("Signature")
    
     If nodeList.Count <= 0 Then
        Throw New CryptographicException("Verification failed: No Signature was found in the document.")
     End If
    
     If nodeList.Count >= 2 Then
        Throw New CryptographicException("Verification failed: More that one signature was found for the document.")
     End If
    
     signedXml.LoadXml(DirectCast(nodeList(0), XmlElement))
    
     Return signedXml.CheckSignature(tmpRsa)
    
    End Function