创建和管理密钥是加密过程的一个重要部分。对称算法要求创建必须对不应解密数据的任何人保密的密钥和初始化向量 (IV)。不对称算法要求创建一个公钥和一个私钥。公钥可以对任何人公开,而私钥必须只为将要对用公钥加密的数据进行解密的一方知道。本节描述如何为对称算法和不对称算法生成和管理密钥。
对称密钥
.NET Framework 提供的对称加密类需要一个密钥和一个新的 IV 来加密和解密数据。每当使用默认的构造函数创建其中一个托管对称加密类的新实例时,就会自动创建新的密钥和 IV。无论您想让谁能够解密您的数据,他或她都必须拥有同样的密钥和 IV 并使用相同的加密算法。通常,应该为每个会话创建新的密钥和 IV,并且无论是密钥还是 IV 都不应存储以用于稍后的会话中。
为了将对称密钥和 IV 传送给远程方,通常使用不对称加密来加密对称密钥和 IV。通过不安全的网络发送这些值而不对这些值进行加密会极不安全,这是因为截获这些值的任何人都能够解密您的数据。有关加密和传输密钥与 IV 的过程的更多信息,请参见创建加密方案。
下面的示例显示实现 TripleDES 算法的 TripleDESCryptoServiceProvider 类的新实例的创建。
[Visual Basic] Dim TDES As TripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider() [C#] TripleDESCryptoServiceProvider TDES = new TripleDESCryptoServiceProvider();
在执行上面的代码时,将生成新的密钥和 IV 并将其分别放置在 Key 和 IV 属性中。
有时您可能需要生成多个密钥。这种情况下,可以创建实现对称算法的类的新实例,然后通过调用 GenerateKey 和 GenerateIV 方法创建新的密钥和 IV。下面的代码示例阐释如何在创建了不对称加密类的新实例后创建新的密钥和 IV。
[Visual Basic] Dim TDES As TripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider() TDES.GenerateIV() TDES.GenerateKey() [C#] TripleDESCryptoServiceProvider TDES = new TripleDESCryptoServiceProvider(); TDES.GenerateIV(); TDES.GenerateKey();
当执行上面的代码时,创建 TripleDESCryptoServiceProvider 的新实例后将生成密钥和 IV。调用 GenerateKey 和 GenerateIV 方法时将创建另一个密钥和 IV。
不对称密钥
.NET Framework 为不对称加密提供了 RSACryptoServiceProvider 和 DSACryptoServiceProvider 类。这些类在您使用默认构造函数创建新实例时创建一个公钥/私钥对。既可以存储不对称密钥以用在多个会话中,也可以只为一个会话生成不对称密钥。公钥可以被广泛地使用,私钥应被严密地保护起来。
每当创建不对称算法类的新实例时,都生成一个公钥/私钥对。创建该类的新实例后,就可以用以下两种方法之一提取密钥信息:
- ToXMLString 方法,它返回密钥信息的 XML 表示形式。
- ExportParameters 方法,它返回 RSAParameters 枚举以保存密钥信息。
两个方法都接受布尔值,该值指示是只返回公钥信息还是同时返回公钥和私钥信息。通过使用 ImportParameters 方法,可以将 RSACryptoServiceProvider 类初始化为 RSAParameters 结构的值。
下面的代码示例创建 RSACryptoServiceProvider 类的一个新实例,创建一个公钥/私钥对,并将公钥信息保存在 RSAParameters 结构中。
[Visual Basic] 'Generate a public/private key pair. Dim RSA as RSACryptoServiceProvider = new RSACryptoServiceProvider() 'Save the public key information to an RSAParameters structure. Dim RSAKeyInfo As RSAParameters = RSA.ExportParameters(false) [C#] //Generate a public/private key pair. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); //Save the public key information to an RSAParameters structure. RSAParameters RSAKeyInfo = RSA.ExportParameters(false);
将不对称密钥存储在密钥容器中
千万不要将不对称私钥逐字存储(或者说以明文形式存储)在本地计算机上。如果需要存储私钥,则应使用密钥容器。有关密钥容器的更多信息,请参见位于 http://msdn.microsoft.com 上的 Platform SDK 文档中的“CryptoAPI”一节。
创建不对称密钥并将其保存在密钥容器中
- 创建 CspParameters 类的一个新实例,并将您要密钥容器使用的名称传递给 CspParameters.KeyContainerName 字段。
- 为从 AsymmetricAlgorithm 类派生的一个类(通常是 RSACryptoServiceProvider 或 DSACryptoServiceProvider)创建一个新实例,并将先前创建的 CspParameters 对象传递给其构造函数。
从密钥容器中删除密钥
- 创建 CspParameters 类的一个新实例,并将您要密钥容器使用的名称传递给 CspParameters.KeyContainerName 字段。
- 为从 AsymmetricAlgorithm 类派生的一个类(通常是 RSACryptoServiceProvider 或 DSACryptoServiceProvider)创建一个新实例,并将先前创建的 CspParameters 对象传递给其构造函数。
- 将从 AsymmetricAlgorithm 中派生的类的 PersistKeyInCSP 属性设置为 false(在 Visual Basic 中为 False)。
- 调用从 AsymmetricAlgorihtm 派生的类的 Clear 方法。该方法释放该类所有的资源并清除密钥容器。
以下示例说明下面这一过程:创建一个不对称密钥,将其保存在密钥容器中,以后检索此密钥,最后从该容器中删除此密钥。
[Visual Basic] Imports System Imports System.IO Imports System.Security.Cryptography _ Public Class StoreKey Public Shared Sub Main() Try ' Create a key and save it in a container. GenKey_SaveInContainer("MyKeyContainer") ' Retrieve the key from the container. GetKeyFromContainer("MyKeyContainer") ' Delete the key from the container. DeleteKeyFromContainer("MyKeyContainer") ' Create a key and save it in a container. GenKey_SaveInContainer("MyKeyContainer") ' Delete the key from the container. DeleteKeyFromContainer("MyKeyContainer") Catch e As CryptographicException Console.WriteLine(e.Message) End Try End Sub Public Shared Sub GenKey_SaveInContainer(ByVal ContainerName As String) ' Create the CspParameters object and set the key container ' name used to store the RSA key pair. Dim cp As New CspParameters() cp.KeyContainerName = ContainerName ' Create a new instance of RSACryptoServiceProvider that accesses ' the key container MyKeyContainerName. Dim rsa As New RSACryptoServiceProvider(cp) ' Display the key information to the console. Console.WriteLine("Key added to container: {0}", rsa.ToXmlString(True)) End Sub Public Shared Sub GetKeyFromContainer(ByVal ContainerName As String) ' Create the CspParameters object and set the key container ' name used to store the RSA key pair. Dim cp As New CspParameters() cp.KeyContainerName = ContainerName ' Create a new instance of RSACryptoServiceProvider that accesses ' the key container MyKeyContainerName. Dim rsa As New RSACryptoServiceProvider(cp) ' Display the key information to the console. Console.WriteLine("Key retrieved from container : {0}", rsa.ToXmlString(True)) End Sub Public Shared Sub DeleteKeyFromContainer(ByVal ContainerName As String) ' Create the CspParameters object and set the key container ' name used to store the RSA key pair. Dim cp As New CspParameters() cp.KeyContainerName = ContainerName ' Create a new instance of RSACryptoServiceProvider that accesses ' the key container. Dim rsa As New RSACryptoServiceProvider(cp) ' Delete the key entry in the container. rsa.PersistKeyInCsp = False ' Call Clear to release resources and delete the key from the container. rsa.Clear() Console.WriteLine("Key deleted.") End Sub End Class [C#] using System; using System.IO; using System.Security.Cryptography; public class StoreKey { public static void Main() { try { // Create a key and save it in a container. GenKey_SaveInContainer("MyKeyContainer"); // Retrieve the key from the container. GetKeyFromContainer("MyKeyContainer"); // Delete the key from the container. DeleteKeyFromContainer("MyKeyContainer"); // Create a key and save it in a container. GenKey_SaveInContainer("MyKeyContainer"); // Delete the key from the container. DeleteKeyFromContainer("MyKeyContainer"); } catch(CryptographicException e) { Console.WriteLine(e.Message); } } public static void GenKey_SaveInContainer(string ContainerName) { // Create the CspParameters object and set the key container // name used to store the RSA key pair. CspParameters cp = new CspParameters(); cp.KeyContainerName = ContainerName; // Create a new instance of RSACryptoServiceProvider that accesses // the key container MyKeyContainerName. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp); // Display the key information to the console. Console.WriteLine("Key added to container: \n {0}", rsa.ToXmlString(true)); } public static void GetKeyFromContainer(string ContainerName) { // Create the CspParameters object and set the key container // name used to store the RSA key pair. CspParameters cp = new CspParameters(); cp.KeyContainerName = ContainerName; // Create a new instance of RSACryptoServiceProvider that accesses // the key container MyKeyContainerName. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp); // Display the key information to the console. Console.WriteLine("Key retrieved from container : \n {0}", rsa.ToXmlString(true)); } public static void DeleteKeyFromContainer(string ContainerName) { // Create the CspParameters object and set the key container // name used to store the RSA key pair. CspParameters cp = new CspParameters(); cp.KeyContainerName = ContainerName; // Create a new instance of RSACryptoServiceProvider that accesses // the key container. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp); // Delete the key entry in the container. rsa.PersistKeyInCsp = false; // Call Clear to release resources and delete the key from the container. rsa.Clear(); Console.WriteLine("Key deleted."); } }
运行上述示例时,控制台上将显示以下内容。
Key added to container:
<RSAKeyValue> ...Key Information A...</RSAKeyValue>
Key retrieved from container :
<RSAKeyValue> ...Key Information A...</RSAKeyValue>
Key deleted.
Key added to container:
<RSAKeyValue> ...Key Information B...</RSAKeyValue>
Key deleted.
使用Convert.ToBase64String(TDES.Key)可以把密钥变成字符串来储存。