Overview
Windows provides a Public Key Infrastructure (PKI) that allows us to store
certificates for encryption purposes. To access the this store we had two
possibilities in the unmanaged past: The CryptoAPI and the CAPICOM.
The Framework Class Library (= FCL) provies a lot of function
for encryption, but the current release doesn't provide any classes for
accessing the the certificate store. Fortunately a the
Web Services Development Kit (WSDK) Technology Preview adds this
functionality; later this will be included in the FCL itself. But in the mean
time you have to download the WSDK.
Enumerating The Certificate Store
The article
Using WS-Security with the Web Services Development Kit Technology Preview
has this nice example:
using Microsoft.WSDK.Security.Cryptography;
using Microsoft.WSDK.Security.Cryptography.X509Certificates;
...
private X509CertificateStore store;
...
private void Form1_Load( object sender, System.EventArgs e )
{
store = X509CertificateStore.CurrentUserStore( X509CertificateStore.MyStore );
store.OpenRead();
foreach( X509Certificate cert in store.Certificates )
{
listBox1.Items.Add( cert.GetName() );
}
}
Asymmetric Encryption/Signature Example
The following code is the funcionallity of my submitted example. It assumes
that you have at least two certificates (with private key!) in your Personal
Certificate Store.
try
{
X509CertificateStore store =
X509CertificateStore.CurrentUserStore( X509CertificateStore.MyStore );
store.OpenRead();
X509Certificate sender = (X509Certificate)store.Certificates[0];
X509Certificate receiver = (X509Certificate)store.Certificates[1];
string sender_serial = sender.GetName();
string receiver_serial = receiver.GetName();
RSAParameters sender_private = sender.Key.ExportParameters( true );
RSAParameters receiver_public = receiver.Key.ExportParameters( false );
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters( receiver_public );
byte[] cleartext = ASCIIEncoding.ASCII.GetBytes("test");
byte[] cipher = rsa.Encrypt( cleartext, false );
rsa = new RSACryptoServiceProvider();
rsa.ImportParameters( sender_private );
byte[] signature = rsa.SignData( cipher, new SHA1CryptoServiceProvider() );
RSAParameters receiver_private = receiver.Key.ExportParameters( true );
RSAParameters sender_public = sender.Key.ExportParameters( false );
rsa = new RSACryptoServiceProvider();
rsa.ImportParameters( sender_public );
if( rsa.VerifyData( cipher, new SHA1CryptoServiceProvider(), signature ) )
{
rsa.ImportParameters( receiver_private );
byte[] cleartext_after_decription = rsa.Decrypt( cipher, false );
Debug.Assert( ASCIIEncoding.ASCII.GetString( cleartext ) ==
ASCIIEncoding.ASCII.GetString( cleartext_after_decription ),
"Ups, the cleartext input is not equal the cleartext output..." );
}
else
Debug.Assert( false, "Ups, check signature failed!" );
}
catch( Exception e )
{
Debug.Assert( false, e.ToString() );
}
Note: The X509Certificate class provides the function ExportParameters and the
boolean parameter defines if the private key has to be submitted as well.
A quick note
Favorite person names for encryption examples are Alice, Bob and mean
Steve. If you like to see how they are doing in .NET, search your
MSDN examples
for the excellent example file called PublicKey.cs!