我需要实现一个新的或已经存在的加密算法,该算法使用另一个字符串作为密钥来加密和解密字符串。问题是此算法必须独立于使用它的计算机。
所以方法签名是:
public static string Encrypt(this string source, string key);
public static string Decrypt(this string source, string key);
我尝试了这些算法,但它们不能按我想要的方式工作:
public static string Encrypt(this string source, string key)
{
if (String.IsNullOrEmpty(source) || String.IsNullOrEmpty(key))
throw new ArgumentException();
CspParameters cspp = new CspParameters { KeyContainerName = key };
using (var rsa = new RSACryptoServiceProvider(cspp) { PersistKeyInCsp = true })
return BitConverter.ToString(rsa.Encrypt(UTF8Encoding.UTF8.GetBytes(source), true));
}
public static string Decrypt(this string source, string key)
{
if (String.IsNullOrEmpty(source) || String.IsNullOrEmpty(key))
throw new ArgumentException();
try
{
CspParameters cspp = new CspParameters { KeyContainerName = key };
using (var rsa = new RSACryptoServiceProvider(cspp) { PersistKeyInCsp = true })
{
string[] decryptArray = source.Split(new char[] { '-' }, StringSplitOptions.None);
byte[] bytes = Array.ConvertAll<string, byte>(decryptArray, (s => Convert.ToByte(Byte.Parse(s, NumberStyles.HexNumber))));
return UTF8Encoding.UTF8.GetString(rsa.Decrypt(bytes, true));
}
}
catch
{ return null; }
}
我该怎么办?
答案 0 :(得分:2)
KeyContainerName不是键。在上面的示例中,通过将密钥作为商店名称传递,您将在每台计算机上创建一个新的RSA密钥对,其中包含您传入密钥的商店名称(而不是像“MyRSAKeyPair”或其他任何东西的商店名称)。这意味着公钥和私钥都将完全不同,您的例程似乎无法正常工作。
另请注意:您使用的是非对称加密,这具有密钥长度的最大块大小限制。这意味着您需要创建一个分块机制(因为非对称加密很昂贵)或者使用像AES那样对称的东西,并且在每次会话的基础上使用非对称加密(例如RSA)发送AES密钥。
您需要导出RSA公钥,然后将其导入远程计算机的密钥库。更容易生成X509证书(如果您只是在两台计算机之间进行自我签名,将其公共部分导出到.CER文件中,那么您可以使用X509证书库API来获取RSA提供程序,这意味着你有一个很好的便携钥匙。
public static RSACryptoServiceProvider GetRsaProviderFromCertificate()
{
X509Store store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection certCollection = (X509Certificate2Collection)store.Certificates;
foreach(X509Certificate2 cert in certCollection)
{
if (cert.SubjectName.Name.IndexOf("TheCertIWantToUse") > 0)
{
return cert.PrivateKey as RSACryptoServiceProvider;
}
}
我希望这很明确......
如果你想在没有证书的情况下这样做
// Export public key (on the encrypting end)
publicKey = rsaProvider.ToXmlString(false);
// Write public key to file
publicKeyFile = File.CreateText(publicKeyFileName);
publicKeyFile.Write(publicKey);
然后在另一台机器上
// Select target CSP
cspParams = new CspParameters();
cspParams.ProviderType = 1; // PROV_RSA_FULL
rsaProvider = new RSACryptoServiceProvider(cspParams);
// Read public key from file
publicKeyFile = File.OpenText(publicKeyFileName);
publicKeyText = publicKeyFile.ReadToEnd();
// Import public key
rsaProvider.FromXmlString(publicKeyText);