Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Cryptography in .NET

, 9 Oct 2002
Cryptography in .NET using the Windows PKI
using System;
using System.Text;
using System.Diagnostics;
using System.Security.Cryptography;
using Microsoft.WSDK.Security.Cryptography.X509Certificates;

namespace Codeproject.Cryptography
{
	class CryptographyApp
	{
		[STAThread]
		static void Main(string[] args)
		{
			try
			{
				//
				// GENERAL CODE TO READ THE CERTIFICATES FROM THE WINDOWS PKI INFRASTRUCTURE
				//
				// 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 );
				store.OpenRead();

				// 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 CODE
				//

				// 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() );

				//
				// TODO: TRANSFER DATA OVER UNSECURE CHANNEL...
				//

				// 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....
				// ANY HELP TO THIS POINT IS MORE THAN WELCOME
				//
				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..." );
				}
				else
					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() );
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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

Share

About the Author

Manuel Permuy
Web Developer
Switzerland Switzerland
No Biography provided

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