.NET 中的密码学






4.58/5 (17投票s)
2002 年 9 月 25 日
1分钟阅读

552525

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 的优秀示例文件!