C#RSA解密问题

时间:2009-10-01 16:56:02

标签: c# rsa

我有这个功能,我用来解密我的开发机器上工作正常的值。但是当在另一台服务器上的生产中运行时 - 给出这个确切的错误消息:

系统找不到指定的文件。

这是功能:

 public static string Decrypt(string stringToDecrypt, string key)
    {
        string result = null;

        if (string.IsNullOrEmpty(stringToDecrypt))
        {
            throw new ArgumentException("An empty string value cannot be encrypted.");
        }

        if (string.IsNullOrEmpty(key))
        {
            throw new ArgumentException("Cannot decrypt using an empty key. Please supply a decryption key.");
        }

        try
        {
            System.Security.Cryptography.CspParameters cspp = new System.Security.Cryptography.CspParameters();
            cspp.KeyContainerName = key;

            System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider(cspp);
            rsa.PersistKeyInCsp = true;

            string[] decryptArray = stringToDecrypt.Split(new string[] { "-" }, StringSplitOptions.None);
            byte[] decryptByteArray = Array.ConvertAll<string, byte>(decryptArray, (s => Convert.ToByte(byte.Parse(s, System.Globalization.NumberStyles.HexNumber))));


            byte[] bytes = rsa.Decrypt(decryptByteArray, true);

            result = System.Text.UTF8Encoding.UTF8.GetString(bytes);

        }
        finally
        {
            // no need for further processing
        }

        return result;
    }

更新

伙计们,我最初选择了这条路线,因为经过数小时和数小时的搜索后,我得到了stackoverflow的答案,这种加密/解密方法完全适用于字符串,无需导入/导出密钥。

所以....现在我错过了一个密钥文件?这怎么可能我甚至都没有创建密钥文件。

5 个答案:

答案 0 :(得分:2)

请注意,您没有将key参数用作密码,而是用作容器的名称。这依赖于先前存储密钥的加密功能。不适合跨计算机传输加密数据。除非你转移钥匙。

答案 1 :(得分:2)

如果您需要将密钥从一台计算机复制到另一台计算机,则必须从密钥容器中导出密钥。我们发现rsaCryptoServiceProvider.ImportCspBlobExportCspBlob方法适用于此;你得到一个单字节数组,然后你可以Convert.ToBase64StringConvert.FromBase64String

当然,它必须是一个可导出的密钥(或者更好的是,只导出公钥,这是PKC的意图,所以一端有私钥,另一端只有公钥)。不可导出的密钥只能导出其公钥。一旦您使系统工作,您可以创建一个新的不可导出密钥,您需要私钥驻留,并导出公钥以将其传输到其他需要加密到该单个收件人的地方。

此外,您需要确保Dispose加密提供程序完成后(显然Clear()不够好)。如果您在一个本地范围内使用它,则可以使用using语句来执行此操作,或者您可以在finally块中执行此操作。请注意,它明确地实现了IDisposable,因此您必须将它强制转换为IDisposable,以便在单独的语句中执行它。 using语句处理转换本身,因此更容易。

答案 2 :(得分:1)

使用Sysinternals.com的FileMon查看它正在寻找的文件?

我的猜测是cspp.KeyContainerName = key;是相关的。

答案 3 :(得分:0)

那么,您是否在服务器上的加密提供程序中将密钥安装在名为key的容器中?请参阅How to: Use the X.509 Certificate Management Tools

顺便说一句,如果你能够在你的机器上解密一些应该是服务器上的私钥 ,那么这个密钥已经被破坏了。您应该尽快更改密钥。

更新

之后

RSA密码术基于不对称密钥。您使用公钥加密,目标使用私钥解密。密钥是预先设置的,您生成或获取密钥对的目的地,并将私有部分保留给自己并为其他人公开公共部分。通常,密钥被打包为X509证书,因为它利用了围绕证书的整个信任基础设施(签名,可信管理机构,证书目的等)。在这种情况下,消息的目的地必须从受信任的机构(即Verisign)等请求用于加密目的的证书。或者使用自签名证书(makecert.exe)并通过一些带外方法建立信任(即。一个电话调用验证证书哈希或IssuerName / SerialNumber)。

RSa密码学非常远离“只是字符串”。更接近“只是字符串”的是对称密钥加密(AES,DES,XDES,RC4),其中您的应用程序具有用于加密和解密的密钥。

现在,除非您确实知道正在做什么,否则请避开加密,使用现成的协议,如SSL/TLS(在线)或S-MIME(离线) )。更好的是,使用一些框架工具,如CryptoStreamProtectedData。不要根据你从未见过的人的新闻组建议创建另一个伪加密......

答案 4 :(得分:0)

问题可能是RSA对象尝试在用户配置文件中创建CryptoContainer 您可以尝试添加此内容:

rsa.UseMachineKeyStore = true;