Using X509 certificates with a password

A

awrightus

I'm writing a program that uses
System.Security.Cryptography.X509Certificates to sign an email. Most
of it's cobbled up from examples I found on MSDN. Everything's
working, provided the certificate (in the local store) isn't protected
by a password. If it has a password, I get an exception saying the
key doesn't exist. If it doesn't have a password, no problems. I
would have thought that by virtue of calling the cert with .net, I
would get the standard Windows dialog to authenticate the certificate,
but that doesn't happen. I don't see anything in the X509Certificates
namepsace that would be used to for a prompt for the certificate
password. Any ideas appreciated. Code attached.

Imports System
Imports System.Text
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Pkcs
Imports System.Security.Cryptography.X509Certificates

Module PKI

Public Function GetSignerCert(ByVal signerName As String) As
X509Certificate2
'Open the My certificate store.
Dim storeMy As New X509Store(StoreName.My,
StoreLocation.CurrentUser)
storeMy.Open(OpenFlags.[ReadOnly])

' Display certificates
Console.WriteLine("Found certs with the following subject " &
"names in the {0} store:", storeMy.Name)
For Each cert As X509Certificate2 In storeMy.Certificates
Console.WriteLine(vbTab & "{0}", cert.SubjectName.Name)
Next

' Create a collection of available certs that have the digital
signature key usage extension.
Dim certColl As X509Certificate2Collection =
storeMy.Certificates.Find(X509FindType.FindByKeyUsage,
"DigitalSignature", True)
'Dim certColl As X509Certificate2Collection =
storeMy.Certificates

' Create a new AsnEncodedDataCollection object.
Dim asncoll As New AsnEncodedDataCollection()
Dim intASNCollCounter As Integer
For intASNCollCounter = 0 To certColl.Count - 1
' Display extensions information.
'Dim extension As X509Extension
Dim strASNData As String = ""
For Each extension In certColl
(intASNCollCounter).Extensions
' Create an AsnEncodedData object using the extensions
information.
Dim asndata As New AsnEncodedData(extension.Oid,
extension.RawData)
If extension.Oid.FriendlyName = "Subject Alternative
Name" Then
strASNData = asndata.Format(False).ToString.Trim
Dim strASNDataArray() As String = Split
(strASNData, ",")
Dim strRFC822Address As String = ""
Dim intASNArrayCounter As Integer = 0
For intASNArrayCounter = 0 To UBound
(strASNDataArray)
If strASNDataArray
(intASNArrayCounter).StartsWith("RFC822 Name=") Then
Console.WriteLine("Certificate Name: " &
certColl(intASNCollCounter).SubjectName.Name)
strRFC822Address = strASNDataArray
(intASNArrayCounter).Substring(12)
If strRFC822Address = signerName Then
Console.WriteLine("Found cert with
email address " & strRFC822Address)
Return certColl(intASNCollCounter)
Exit Function
End If
End If
Next
End If
' Add the AsnEncodedData object to the
AsnEncodedDataCollection object.
asncoll.Add(asndata)
Next extension
Next intASNCollCounter

' Check to see if no certs
If certColl.Count = 0 Then
Console.WriteLine("No certs found.")
End If

storeMy.Close()

Console.WriteLine("No certs matching " & signerName)
Return Nothing
End Function

' Sign the message with the private key of the signer.
Public Function SignMsg(ByVal msg As Byte(), ByVal signerCert As
X509Certificate2) As Byte()
' Place message in a ContentInfo object.
' This is required to build a SignedCms object.
Dim contentInfo As New ContentInfo(msg)

' Instantiate SignedCms object with the ContentInfo above.
' Has default SubjectIdentifierType IssuerAndSerialNumber.
' Has default Detached property value false, so message is
' included in the encoded SignedCms.
Dim signedCms As New SignedCms(contentInfo)

' Formulate a CmsSigner object for the signer.
Dim cmsSigner As New CmsSigner(signerCert)

' Sign the CMS/PKCS #7 message.
'Console.WriteLine("This is the private key: " &
cmsSigner.Certificate.GetPublicKey.ToString)

Console.Write("Computing signature with signer subject " &
"name {0} ... ", signerCert.SubjectName.Name)
signedCms.ComputeSignature(cmsSigner)
Console.WriteLine("Done.")

' Encode the CMS/PKCS #7 message.
Return signedCms.Encode()
End Function

Public Function VerifyMsg(ByVal encodedSignedCms As Byte()) As
Boolean
' Prepare an object in which to decode and verify.
Dim signedCms As New SignedCms()

signedCms.Decode(encodedSignedCms)

' Catch a verification exception if you want to
' advise the message recipient that
' security actions might be appropriate.
Try
' Verify signature. Do not validate signer
' certificate for the purposes of this example.
' Note that in a production environment, validating
' the signer certificate chain will probably
' be necessary.
Console.Write("Checking signature on message ... ")
signedCms.CheckSignature(True)
Console.WriteLine("Done.")
Catch e As System.Security.Cryptography.CryptographicException
Console.WriteLine("VerifyMsg caught exception: {0}",
e.Message)
Console.WriteLine("Verification of the signed PKCS #7 " &
"failed. The message, signatures, or " & "countersignatures may have
been modified " & "in transit or storage. The message signers or " &
"countersigners may not be who they claim to be. " & "The message's
authenticity or integrity, " & "or both, are not guaranteed.")
Return False
End Try

Return True
End Function

End Module
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top