I try to port ASP .NET MVC2 password recovery code from Where to find C# sample code to implement password recovery in ASP .NET MVC2 answer to Mono.
I it contains procedure below. CryptDeriveKey call causes exception in Mono
CspParameters not supported by Mono
How to implement password recovery in Mono in ASP .NET MVC2 application ?
/// <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);
}
You cannot fix this as the type
CspParametersis not really supported by Mono.The reason is that this type is used to communicate extra information between the (managed) BCL code and the CryptoAPI’s CSP (crypto service provider). Since Mono use only managed code and that CryptoAPI is not available outside Windows then the
CspParametersclass is mostly a stub, a definition without code.In particular the type
PasswordDeriveBytesis a bit special. It implements the standard PKCS#5 v1.5, which Mono supports, but it also adds a few Microsoft extensions (breaking the specification) including one one them being totally broken (security wise). You should take great care when usingPasswordDeriveBytes.The case for
CryptDeriveKeyis even more badly designed. It has nothing to do with (any version of) PKCS#5, like the rest ofPasswordDeriveBytes(i.e. it’s not standard-based). What it does is simply redirect your parameters to CryptoAPI using the default CSP. Some majors issues arise form this:AFAIK Microsoft never published the algorithm(s) they are using to derive keys in their CSP. I can’t say if it’s even secure, their PKCS#5 extensions were not;
The “default” CSP can be changed (e.g. by applications) to default to a non-Microsoft CSP (e.g. hardward/smartcard CSP). The key derivation algorithm provided by those CSP is unknown (hopefully they call back into MS CSP);
CryptoAPI and the CSP are only available on Windows and differs by the version of Windows/exportability, not the version of the .NET framework.
You should avoid using
PasswordDeriveBytes.CryptDeriveKey, even on Windows, unless you can assure the default CSP is (and will remain) identical across all computers running your application.In conclusion, to avoid interoperability / security issues, I strongly suggest your to use the newer PKCS#5 v2, which Mono/MonoTouch/Microsoft implements as
System.Security.Cryptography.Rfc2898DeriveBytes.