使用 RSA 的 C# 扩展方法






4.76/5 (8投票s)
创建加密字符串值的扩展方法的示例。
引言
本文希望能给您创建一个自己的 .NET 扩展方法的简单示例。我非常喜欢示例代码,但通常情况下,你会看到一些试图向你展示如何完成某事的各种可能场景的巨大示例。我真的更喜欢简单的代码,所以我特意让这个项目保持小巧,并且范围非常狭窄。虽然我展示了两种加密和解密字符串的方法,但您可以使用“注册表键”方式,而无需了解任何关于 RSA 或创建私钥/公钥的知识。
背景
在之前的工作中,我们使用加密来处理用户名和密码,但必须调用一个单独的 DLL 方法来完成所有工作。使用 .NET 3.0,扩展现有类型(甚至是 .NET 内置类型)的功能要容易得多,而不是创建额外的 DLL。本文不会深入探讨使用 RSACryptoServiceProvider
对象的细节,但如果需要一些示例代码,这里有一些注释良好的代码。
使用代码
您可以使用此代码,而无需了解任何关于 RSACryptoServiceProvider
的知识,只需选择使用“Reg Key”(注册表键)而不是“Use Xml”(使用 Xml)的单选按钮即可。如果您确实有 XML 文件中的 RSA 私钥/公钥,那么您可以使用“Use Xml”单选按钮。只需确保在加密/解密时指定正确的文件即可。示例代码使用 Visual Studio 2008 构建,并使用 C# 编写。此代码不是面向对象的,并且确实包含重复的代码,以便于理解。
为什么要创建扩展方法
那么,您为什么要使用扩展方法? 假设您有一个已经被某些客户端实现的接口,现在您需要添加一些功能,甚至更糟的是,您必须添加默认逻辑。 大家都知道,接口不包含逻辑,只包含签名,所以现在,您必须跳过一些环节,要么将接口更改为抽象类并让客户端修复他们的代码,要么添加一些与原始接口无关的新逻辑,并在那里拥有一些丑陋的代码。
您想创建扩展方法的另一种情况在这里显示。您希望扩展您无法控制的现有功能。本文展示了如何向任何字符串对象添加 RSA 加密/解密,而无需了解任何关于 RSA 的知识!
开始创建自己的扩展方法的步骤
开始真的很简单。首先,创建一个标准库类文件。将类的签名修改为 static
,添加静态方法,并为新 DLL 添加对项目的引用。大多数情况下,就是这样。方法签名有一些小的更改,我们将在下面的示例代码中介绍,但这很容易。对于此处发布的代码,为了简洁起见,我将省略验证检查,但可下载的代码确实包含它。我还会只展示使用注册表键进行加密/解密的代码。
我创建的库类名为 ExtensionMethods
,其中包含一个名为 StringExtensionMethods
的类
//Nothing special about this - just a standard static class
public static class StringExtensionMethods
{
//Almost a standard static method just the first parameter is different
//the keyword "this" tells what type of type you are extending
//so the "this string" means we want
//this method to be used by System.String types
public static string EncryptStringUsingRegistryKey(this string encryptValue,
string publicKey)
{
// This is the variable that will be returned to the user
string encryptedValue = string.Empty;
// Create the CspParameters object which is used to create the RSA provider
// without it generating a new private/public key.
// Parameter value of 1 indicates RSA provider
// type - 13 would indicate DSA provider
CspParameters csp = new CspParameters(1);
// Registry key name containing the RSA private/public key
csp.KeyContainerName = publicKey;
// Supply the provider name
csp.ProviderName = "Microsoft Strong Cryptographic Provider";
try
{
//Create new RSA object passing our key info
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp);
// Before encrypting the value we must convert it over to byte array
byte[] bytesToEncrypt = System.Text.Encoding.UTF8.GetBytes(encryptValue);
// Encrypt our byte array. The false parameter has to do with
// padding (not to clear on this point but you can
// look it up and decide which is better for your use)
byte[] bytesEncrypted = rsa.Encrypt(bytesToEncrypt, false);
// Extract our encrypted byte array into a string value to return to our user
encryptedValue = Convert.ToBase64String(bytesEncrypted);
}
catch (CryptographicException cex)
{
Console.WriteLine(cex.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return encryptedValue;
}
public static string DecryptStringUsingRegistryKey(this string
decryptValue, string privateKey)
{
// This is the variable that will be returned to the user
string decryptedValue = string.Empty;
// Create the CspParameters object which is used to create the RSA provider
// without it generating a new private/public key.
// Parameter value of 1 indicates RSA provider
// type - 13 would indicate DSA provider
CspParameters csp = new CspParameters(1);
// Registry key name containing the RSA private/public key
csp.KeyContainerName = privateKey;
// Supply the provider name
csp.ProviderName = "Microsoft Strong Cryptographic Provider";
try
{
//Create new RSA object passing our key info
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp);
// Before decryption we must convert this ugly string into a byte array
byte[] valueToDecrypt = Convert.FromBase64String(decryptValue);
// Decrypt the passed in string value -
// Again the false value has to do with padding
byte[] plainTextValue = rsa.Decrypt(valueToDecrypt, false);
// Extract our decrypted byte array into
// a string value to return to our user
decryptedValue = System.Text.Encoding.UTF8.GetString(plainTextValue);
}
catch (CryptographicException cex)
{
Console.WriteLine(cex.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return decryptedValue;
}
}
上面的代码有很好的注释,所以我不会再详细介绍它,但请记住,如果您使用“使用 XML”单选按钮,请根据您要执行的操作更改到私钥/公钥文件的路径。因此,要使用此代码,您只需编译它,添加对 DLL 的引用,并在您的代码中设置一个 "usings"。调用该方法的实际代码行如下所示
string valueToEncrypt = "Hello World";
string encryptedValue = valueToEncrypt.EncryptStringUsingRegistryKey("SomeKey");
请记住,“SomeKey”值是您想使用的任何字符串。RSACryptoSerivceProvider
将为您创建一个密钥。
好吧,我希望这可以帮助您理解扩展方法。