0

我需要实现一个新的或已经存在的加密算法,该算法使用另一个字符串作为密钥来加密和解密一个字符串。问题是这个算法必须独立于使用它的计算机工作

所以方法签名是:

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

我能怎么做?

4

1 回答 1

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);
于 2013-05-10T10:39:03.497 回答