65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET 中的密码学

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.58/5 (17投票s)

2002 年 9 月 25 日

1分钟阅读

viewsIcon

552525

downloadIcon

2182

.NET 中使用 Windows PKI 的密码学

概述

Windows 提供了一个公钥基础设施 (PKI),允许我们存储用于加密目的的证书。为了访问此存储,在未托管的过去,我们有两种可能性:CryptoAPI 和 CAPICOM。

框架类库(= FCL)提供了大量的加密功能,但当前版本没有提供任何用于访问证书存储的类。幸运的是,Web 服务开发工具包 (WSDK) 技术预览版添加了此功能; 稍后这将包含在 FCL 本身中。 但在此期间,您需要下载 WSDK。

枚举证书存储

文章 使用 Web 服务开发工具包技术预览版中的 WS-Security 提供了这个很好的示例
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() );
    }
}

非对称加密/签名示例

以下代码是我提交的示例的功能。 它假定您的个人证书存储中至少有两个证书(带有私钥!)。

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

注意:X509Certificate 类提供了 ExportParameters 函数,并且布尔参数定义是否需要将私钥也提交。

快速说明

用于加密示例的常用人名是 Alice、Bob 和 mean Steve。 如果您想了解他们在 .NET 中的表现,请在 MSDN 示例中搜索名为 PublicKey.cs 的优秀示例文件!

© . All rights reserved.