Click here to Skip to main content
12,300,245 members (55,303 online)
Click here to Skip to main content
Add your own
alternative version


63 bookmarked

Cryptography in .NET

, 9 Oct 2002
Rate this:
Please Sign up or sign in to vote.
Cryptography in .NET using the Windows PKI


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 );
    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.


   // BEGINNER-TIP: Start MMC (=Microsoft Management Console) and select "Add-in/remove Snapin"
   // from the "Console" menu. Now press "Add.." button. Select "Certificates" in the list and
   // press "Add" button. You have the choise to select "My user account" or "Computer account".
   // Then press "Finish" and "Close" and start exploring the installed certificates... 
   // Each store has a "Personal" section with is BTW represented by the letters "MY".
   // Also interessting is the "Trusted root" certificates, there you see all the Certificate
   // Issuer that you trust, there is quite a lot and sometimes it's a good idea to delete
   // all of them and only add the one you need or really trust, for security resasons.

   // Open private certificate store of current user

   X509CertificateStore store = 
               X509CertificateStore.CurrentUserStore( X509CertificateStore.MyStore );

   // Read e.g. the first two certificate
   X509Certificate sender = (X509Certificate)store.Certificates[0];
   X509Certificate receiver = (X509Certificate)store.Certificates[1];

   // Let's see who we are dealing with... - ps: not nessesary for the following code
   string sender_serial = sender.GetName();
   string receiver_serial = receiver.GetName();


   // SENDER-SIDE: Extract own private keys and receiver's public key

   RSAParameters sender_private = sender.Key.ExportParameters( true );
   RSAParameters receiver_public = receiver.Key.ExportParameters( false );

   // SENDER-SIDE: Asymmetric encryption with receivers's public key
   RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
   rsa.ImportParameters( receiver_public ); 
   byte[] cleartext = ASCIIEncoding.ASCII.GetBytes("test");
   byte[] cipher = rsa.Encrypt( cleartext, false );
   // SENDER-SIDE: Sign the cipher with own private key
   rsa = new RSACryptoServiceProvider();
   rsa.ImportParameters( sender_private );
   byte[] signature = rsa.SignData( cipher, new SHA1CryptoServiceProvider() );


   // RECEIVER-SIDE: Get own private key and sender's public key

   RSAParameters receiver_private = receiver.Key.ExportParameters( true );
   RSAParameters sender_public = sender.Key.ExportParameters( false );

   // RECEIVER-SIDE: Verify signature with sender's public key
   // Note: You are ONLY verifying the signature and NOT verifying the Certificate!
   // It's corresponding to the CAPICOM call SignedData.Verify( CAPICOM_VERIFY_SIGNATURE_ONLY )
   // I did not yet find out how we can use the .NET library to verify the Certificate
   // against the issuer-chain. If someone knows how to do this, and not using interop
   // and the SignedData.Verify( CAPICOM_VERIFY_SIGNATURE_AND_CERTIFICATE ), I would be
   // very, very, very happy - because this is a requirement in the software I'm developing
   // currently and if we can't do that I have to do CAPI-interop :-(
   // At the moment I think that there is no simple function call for this and this s***s.
   // Maybe it's possible to walk throw the chain-of-issuers and validate the fingerprint
   // this the public key of the issuer. But I don't know enough about that....

   rsa = new RSACryptoServiceProvider();
   rsa.ImportParameters( sender_public );
   if( rsa.VerifyData( cipher, new SHA1CryptoServiceProvider(), signature ) )
      // RECEIVER-SIDE: Asmymetirc decryption with own private key
      rsa.ImportParameters( receiver_private );
      byte[] cleartext_after_decription = rsa.Decrypt( cipher, false );

      // Check result
      Debug.Assert( ASCIIEncoding.ASCII.GetString( cleartext ) ==
         ASCIIEncoding.ASCII.GetString( cleartext_after_decription ),
         "Ups, the cleartext input is not equal the cleartext output..." );
      Debug.Assert( false, "Ups, check signature failed!" );
catch( Exception e )

   // NOTE: the following exception, that may occure during 'ExportParameters( true )'
   //   System.Security.Cryptography.CryptographicException
   //   "Key information could not be exported from the cryptographic service 
   //    provider (CSP) for this implementation." }"
   // Can have one of the following reasons:
   // + The certificate was NOT imported with the flag "Mark the private key as exportable"
   // + The type "SSL Server Authentication(40)" and is in a CurrentUser store and not in
   //   the LocalComputer store. See certificate details in the MMC under "NetscapeCertType".
   //   IMHO: This reason is very wicked and I don't understand it!!

   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!


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Manuel Permuy
Web Developer
Switzerland Switzerland
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralRe: CAPCIOM+CDO SendSignedMail Pin
rayback_221-Apr-05 21:19
memberrayback_221-Apr-05 21:19 
GeneralRe: CAPCIOM+CDO SendSignedMail Pin
NoradYeh26-Apr-05 22:12
memberNoradYeh26-Apr-05 22:12 
GeneralRe: CAPCIOM+CDO SendSignedMail Pin
rayback_226-Apr-05 22:26
memberrayback_226-Apr-05 22:26 

Yes as u said the StrConv is the built in of VB 6.0 and it wont work for vbscript and (though in you have counterpart for that function doing the same thing).
I sent the vbscript version of the function too in the code I submitted previously (at the bottom of the page maybe u missed that). What it does is this : using the ADODB stream it converts the unicode characters to ascii and back. You should use that custom function in vbscript code because the built in StrConv is not available in vbscript (at least its how I know it to be)

Here I resent the function definition for StrConv

Const vbFromUnicode = 128
Const vbUnicode = 64

'*********** From Unicode to ASCII and Back**************
Public function StrConv(ByRef stringData, ByRef conversion)
Dim Stream
Set Stream = CreateObject("ADODB.Stream")

Const UnicodeCharaset = "Windows-1252"
Const BinaryCharset = "X-ANSI"
Select Case conversion
Case vbFromUnicode
' from unicode to ascii
With Stream
.Charset = UnicodeCharaset
.Type = 2
.WriteText stringData
.Position = 0
.Charset = BinaryCharset
.Type = 1
StrConv = MidB(.Read, 1)
End With

Case vbUnicode
' from ascii to unicode
Dim Length
Dim Buffer

if TypeName(stringData) = "Null" Then
CStrU = ""
Exit function
End if

stringData = MidB(stringData, 1)

Length = LenB(stringData)
Dim Rs
Set Rs = CreateObject("ADODB.Recordset")
Call Rs.Fields.Append("BinaryData", adLongVarBinary, Length)
Rs.Fields("BinaryData").AppendChunk(stringData & ChrB(0))
Buffer = Rs.Fields("BinaryData").GetChunk(Length)
Set Rs = Nothing
With Stream
.Charset = BinaryCharset
.Type = 1
Call .Write(Buffer)
.Position = 0
.Type = 2
.Charset = UnicodeCharaset
End With

StrConv = Stream.ReadText(-1)
End Select
Set Stream = Nothing
End function

Sincerely Ray

P.S: also u can convert the code to but, theres a big but in that not technically but in principle. If you are writing a web application the certificate you are trying to access is on client machine and not server. So the only solution I saw is to write a script for it, because theres no way of bringing the certificate (wth the private key) to server (its not right thing to do ). So I guess if u are writing the web application you should do it in script.

GeneralRe: CAPCIOM+CDO SendSignedMail Pin
abygm2-Nov-07 2:15
memberabygm2-Nov-07 2:15 
Generaluse phone number Pin
smail belmokhtar19-Nov-03 1:51
membersmail belmokhtar19-Nov-03 1:51 
QuestionWhich page is main source? Pin
Stefan Pedersen3-Oct-03 11:07
memberStefan Pedersen3-Oct-03 11:07 
AnswerRe: Which page is main source? Pin
Manuel Permuy5-Oct-03 7:03
memberManuel Permuy5-Oct-03 7:03 
Generalyour URL to WSDK is broken Pin
norm25-Aug-03 21:29
membernorm25-Aug-03 21:29 
GeneralWSDK becomes WSE Pin
.Net wannabe6-Jun-03 14:53
suss.Net wannabe6-Jun-03 14:53 
GeneralHelp needed Pin
MBuuri22-May-03 3:07
memberMBuuri22-May-03 3:07 
GeneralRe: Help needed Pin
Marcello Drewanz18-Jun-03 7:25
memberMarcello Drewanz18-Jun-03 7:25 
GeneralYou get a 5... Pin
Chris Maunder25-Feb-03 9:00
adminChris Maunder25-Feb-03 9:00 
General"I am Emmet Smith!" Pin
rflagg24-Feb-03 17:35
memberrflagg24-Feb-03 17:35 
GeneralRe: "I am Emmet Smith!" Pin
Manuel Permuy4-Feb-04 13:48
memberManuel Permuy4-Feb-04 13:48 
GeneralCertificate issuer chain... Pin
Fred James11-Feb-03 2:13
memberFred James11-Feb-03 2:13 
GeneralVerify the Certificate Pin
Fred James11-Feb-03 2:12
memberFred James11-Feb-03 2:12 
GeneralRe: Verify the Certificate Pin
WhyIamhere30-Apr-04 9:12
memberWhyIamhere30-Apr-04 9:12 
GeneralCAPICOM Pin
poojavedi29-Jan-03 0:00
memberpoojavedi29-Jan-03 0:00 
QuestionCAPICOM Necessary? Pin
SteveC881-Oct-02 8:45
memberSteveC881-Oct-02 8:45 
AnswerRe: CAPICOM Necessary? Pin
Manuel Permuy4-Oct-02 13:01
memberManuel Permuy4-Oct-02 13:01 
GeneralThe X509Certificate class provides the function ExportParameters Pin
Anonymous28-Sep-02 7:20
sussAnonymous28-Sep-02 7:20 
GeneralRe: The X509Certificate class provides the function ExportParameters Pin
Manuel Permuy30-Sep-02 11:16
memberManuel Permuy30-Sep-02 11:16 
GeneralRe: The X509Certificate class provides the function ExportParameters Pin
Anonymous6-Oct-02 3:56
sussAnonymous6-Oct-02 3:56 
GeneralRe: The X509Certificate class provides the function ExportParameters Pin
Manuel Permuy6-Oct-02 13:38
memberManuel Permuy6-Oct-02 13:38 
GeneralRe: The X509Certificate class provides the function ExportParameters Pin
Alex Butcher22-Dec-02 22:28
sussAlex Butcher22-Dec-02 22:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.160525.2 | Last Updated 10 Oct 2002
Article Copyright 2002 by Manuel Permuy
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid