如何修复调用CryptDeriveKey的Mono异常不支持的CspParameters

时间:2011-12-10 18:56:03

标签: c# .net mono cryptography security

我尝试将ASP .NET MVC2密码恢复代码从Where to find C# sample code to implement password recovery in ASP .NET MVC2回复到Mono。 我包含以下程序。 CryptDeriveKey调用在Mono中导致异常

CspParameters not supported by Mono

如何在ASP.net MVC2应用程序中实现Mono中的密码恢复?

    /// <summary> 
    /// Takes a text message and encrypts it using a password as a key. 
    /// </summary> 
    /// <param name="plainMessage">A text to encrypt.</param> 
    /// <param name="password">The password to encrypt the message with.</param> 
    /// <returns>Encrypted string.</returns> 
    /// <remarks>This method uses TripleDES symmmectric encryption.</remarks> 
    public static string EncodeMessageWithPassword(string plainMessage, string password)
    {
        if (plainMessage == null)
            throw new ArgumentNullException("encryptedMessage", "The message cannot be null");

        TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
        des.IV = new byte[8];

        //Creates the key based on the password and stores it in a byte array. 
        PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, new byte[0]);
        // in mono CryptDeriveKey causes exception:
        // CspParameters not supported by Mono
        des.Key = pdb.CryptDeriveKey("RC2", "MD5", 128, new byte[8]);

        MemoryStream ms = new MemoryStream(plainMessage.Length * 2);
        CryptoStream encStream = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
        byte[] plainBytes = Encoding.UTF8.GetBytes(plainMessage);
        encStream.Write(plainBytes, 0, plainBytes.Length);
        encStream.FlushFinalBlock();
        byte[] encryptedBytes = new byte[ms.Length];
        ms.Position = 0;
        ms.Read(encryptedBytes, 0, (int)ms.Length);
        encStream.Close();

        return Convert.ToBase64String(encryptedBytes);
    }

1 个答案:

答案 0 :(得分:3)

您无法修复,因为{0}支持的类型CspParameters不是

原因是此类型用于在(托管)BCL代码和CryptoAPI的CSP(加密服务提供程序)之间传递额外信息。由于Mono仅使用托管代码,并且CryptoAPI在Windows之外不可用,因此CspParameters类主要是存根,没有代码的定义。

特别是类型PasswordDeriveBytes有点特殊。它实现了Mono支持的标准PKCS#5 v1.5,但它也增加了一些Microsoft extensions(违反规范),包括一个totally broken(安全明智) )。使用PasswordDeriveBytes时,您应该非常小心。

CryptDeriveKey的情况设计得更糟糕。它与(任何版本的)PKCS#5无关,就像PasswordDeriveBytes的其余部分一样(即它不是基于标准的)。它的作用是使用默认的CSP将参数重定向到CryptoAPI。一些专业问题出现在这个:

  1. AFAIK Microsoft从未发布过他们用于在他们的 CSP中派生密钥的算法。我不能说它是否安全,他们的PKCS#5扩展名不是;

  2. 可以将“默认”CSP更改为(例如,通过应用程序)默认为非Microsoft CSP(例如,硬件/智能卡CSP)。这些CSP提供的密钥派生算法未知(希望他们回调MS CSP);

  3. CryptoAPI和CSP仅在Windows上可用,因Windows /可导出版本而不是.NET框架版本而异。

  4. 您应该避免使用PasswordDeriveBytes.CryptDeriveKey,即使在Windows上也是如此,除非您可以确保默认CSP在运行您的应用程序的所有计算机上都是(并且将保持不变)。

    总之,为了避免互操作性/安全性问题,我强烈建议您使用较新的PKCS#5 v2,Mono / MonoTouch / Microsoft实现为System.Security.Cryptography.Rfc2898DeriveBytes