C# 如何修复调用CryptDeriveKey的Mono异常不支持的CSP参数
我尝试将ASP.NETMVC2密码恢复代码从answer移植到Mono。 它包含以下步骤。CryptDeriveKey调用在Mono中导致异常C# 如何修复调用CryptDeriveKey的Mono异常不支持的CSP参数,c#,.net,mono,cryptography,security,C#,.net,Mono,Cryptography,Security,我尝试将ASP.NETMVC2密码恢复代码从answer移植到Mono。 它包含以下步骤。CryptDeriveKey调用在Mono中导致异常 CspParameters not supported by Mono 如何在ASP.NETMVC2应用程序中实现Mono中的密码恢复 /// <summary> /// Takes a text message and encrypts it using a password as a key. /// <
CspParameters not supported by Mono
如何在ASP.NETMVC2应用程序中实现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);
}
//
///接收文本消息并使用密码作为密钥对其进行加密。
///
///要加密的文本。
///用于加密消息的密码。
///加密字符串。
///此方法使用三重对称加密。
公共静态字符串EncodeMessageWithPassword(字符串明文消息,字符串密码)
{
if(明文==null)
抛出新ArgumentNullException(“encryptedMessage”,“消息不能为null”);
TripleDESCryptoServiceProvider des=新的TripleDESCryptoServiceProvider();
des.IV=新字节[8];
//基于密码创建密钥并将其存储在字节数组中。
PasswordDeriveBytes pdb=新PasswordDeriveBytes(密码,新字节[0]);
//在mono CryptDeriveKey中,会导致异常:
//Mono不支持CSP参数
des.Key=pdb.CryptDeriveKey(“RC2”,“MD5”,128,新字节[8]);
MemoryStream ms=新的MemoryStream(plainMessage.Length*2);
CryptoStream encStream=新加密流(ms,des.CreateEncryptor(),CryptoStreamMode.Write);
byte[]plainBytes=Encoding.UTF8.GetBytes(plainMessage);
encStream.Write(纯字节,0,纯字节.Length);
encStream.FlushFinalBlock();
字节[]encryptedBytes=新字节[ms.Length];
ms.Position=0;
ms.Read(encryptedBytes,0,(int)ms.Length);
encStream.Close();
返回Convert.tobase64字符串(encryptedBytes);
}
您无法修复此问题,因为Mono并不真正支持类型CspParameters
原因是该类型用于在(托管)BCL代码和CryptoAPI的CSP(加密服务提供商)之间传输额外信息。由于Mono只使用托管代码,并且CryptoAPI在Windows之外不可用,因此CspParameters
类主要是一个存根,一个没有代码的定义
特别是类型有点特殊。它实现了Mono支持的标准PKCS#5 v1.5,但它还添加了一些Microsoft(违反规范),其中一个是(安全方面的)。使用PasswordDeriveBytes
时应格外小心
CryptDeriveKey
的情况设计得更糟糕。它与PKCS#5的(任何版本)无关,就像其他的PasswordDeriveBytes
(即,它不是基于标准的)。它所做的只是使用默认CSP将参数重定向到CryptoAPI。由此产生了一些主要问题:
PasswordDeriveBytes.CryptDeriveKey
,除非您可以确保运行应用程序的所有计算机上的默认CSP都是(并且将保持)相同的
总之,为了避免互操作性/安全问题,我强烈建议您使用更新的PKCS#5 v2,Mono/MonoTouch/Microsoft将其实现为。非常感谢。我将此方法中的两行更改为
var pdb=new Rfc2898DeriveBytes(密码,new byte[8]);des.Key=pdb.GetBytes(16)代码>。这是最好的解决方案吗?是的,这很好-但您可能需要硬编码一些其他值(而不是空的字节
数组)。