我有一个在Windows和.NET Framework 4下运行良好的程序,但是在Mono(MonoDevelop 2.6内置)下,Encrypt()
和Decrypt()
函数似乎只有一半工作。 ..
如果我在本地对某些内容进行加密,然后立即对其进行解密(在Mono下),那么该消息的前10个字符将是混乱的,但是后面的任何内容看起来都非常有效!
加密功能如下:
public byte[] Encrypt(string plainText)
{
DateTime now = DateTime.Now;
string timeStamp = now.Millisecond.ToString("000") + "." + now.Second.ToString("00") + "." +
now.Minute.ToString("00") + "." + now.Hour.ToString("00") + Constants.MessageSplitChar;
plainText = plainText.Insert(0, timeStamp);
MemoryStream memoryStream = new MemoryStream();
lock (this.encryptor)
{
CryptoStream cryptoStream = new CryptoStream(memoryStream, this.encryptor, CryptoStreamMode.Write);
StreamWriter writer = new StreamWriter(cryptoStream);
try
{
writer.Write(plainText);
}
finally
{
writer.Close();
cryptoStream.Close();
memoryStream.Close();
}
}
byte[] encryptedMessage = memoryStream.ToArray();
return this.AppendArrays(BitConverter.GetBytes(encryptedMessage.Length), encryptedMessage);
}
Decrypt功能如下:
public string Decrypt(byte[] cipherText)
{
try
{
string plainText = string.Empty;
MemoryStream memoryStream = new MemoryStream(cipherText);
lock (this.decryptor)
{
CryptoStream cryptoStream = new CryptoStream(memoryStream, this.decryptor, CryptoStreamMode.Read);
StreamReader reader = new StreamReader(cryptoStream);
try
{
plainText = reader.ReadToEnd();
plainText = plainText.Substring(plainText.IndexOf("|") + 1);
plainText = plainText.TrimEnd("\0".ToCharArray());
}
finally
{
reader.Close();
cryptoStream.Close();
memoryStream.Close();
}
}
return plainText;
}
catch (Exception ex)
{
CMicroBingoServer.LogManager.Write(ex.ToString(), MessagePriority.Error);
return "DECRYPTION_FAILED";
}
}
答案 0 :(得分:3)
一开始看起来有多少字符字节可能很重要...如果第一个块出现废话但剩下的就好了那么可能是你的初始化向量不是在解密时纠正。
在最常见的块模式下,CBC在解密IV时仅影响第一个数据块的解密,因为之后它的密码文本充当后续块的IV。
您是否明确设置IV用于加密和解密?如果不是那么我会想象两个在处理未设置的IV时有不同的行为(例如,窗口使用全零和单声道产生随机IV - 这将导致窗口解密很好,因为IV是相同的,而单声道可能产生两个不同用于加密和解密过程的IV。
我不太了解单声道的内容,无法查看确切的解决方案,但这些内容似乎很可能。
答案 1 :(得分:3)
您的代码未显示如何创建decryptor
和encryptor
个实例。
这可能是一个问题,因为如果您正在重复使用该实例,那么您必须检查ICryptoTransform.CanReuseTransform
。如果它返回 false ,则您无法重用相同的加密器/解密器,并且必须创建新实例。
这更为重要,因为Mono和.NET对某些算法有不同的默认值。但在任何情况下,跳过此检查意味着未来.NET框架中的任何更改(或通过配置文件,因为加密可以使用CryptoConfig
插入)可能会在某一天破坏您的代码。