这是一个不寻常的问题。我无法使用3个密码加密文件。我试图围绕另外两个CryptoStream包装一个CryptoStream,但是当我将文件写入磁盘时,它似乎已损坏,并且无法完全删除填充。为什么会发生这种情况?
编辑:这是一些示例代码
public static Stream Encrypt(Stream source, int delcount, params keyPair[] cryptInfo)
{
Stream prevStream = source;
foreach (keyPair et in cryptInfo)
{
Rijndael mydale = Rijndael.Create();
mydale.BlockSize = 256;
mydale.KeySize = 256;
mydale.IV = et.IV;
mydale.Key = et.key;
CryptoStream mystream = new CryptoStream(prevStream, mydale.CreateEncryptor(), CryptoStreamMode.Write);
prevStream = mystream;
}
return prevStream;
}
这是完整的计划 Program.cs的
class Program
{
static string opcode = "test";
static string IDCID = "an ID";
static string password = "A strong password";
static void Main(string[] args)
{
if (Console.ReadLine() == "encrypt")
{
Stream thestream = File.Open(Environment.CurrentDirectory + "\\sample.txt", FileMode.Create, FileAccess.ReadWrite);
PasswordDeriveBytes mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes(opcode), Encoding.ASCII.GetBytes(opcode));
byte[] key = mybytes.GetBytes(32);
mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes((IDCID.Length + password.Length + opcode.Length * 15).ToString()), Encoding.ASCII.GetBytes((IDCID.Length + password.Length + 5 + opcode.Length * 24).ToString()));
byte[] IV = mybytes.GetBytes(32);
keyPair mypair = new GlobalGridCore.keyPair(IV, key);
mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes(password), Encoding.ASCII.GetBytes(password));
key = mybytes.GetBytes(32);
mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes((IDCID.Length + password.Length + opcode.Length * 9).ToString()), Encoding.ASCII.GetBytes((IDCID.Length + password.Length + 7 + opcode.Length * 24).ToString()));
IV = mybytes.GetBytes(32);
keyPair secondpair = new keyPair(IV, key);
mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes(IDCID), Encoding.ASCII.GetBytes(IDCID));
key = mybytes.GetBytes(32);
mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes((IDCID.Length + password.Length + opcode.Length * 2).ToString()), Encoding.ASCII.GetBytes((IDCID.Length + password.Length + 14 + opcode.Length * 7).ToString()));
IV = mybytes.GetBytes(32);
keyPair thirdpair = new keyPair(IV, key);
keyPair[] list = new keyPair[] { mypair, secondpair, thirdpair };
thestream = gridCrypto.Encrypt(thestream, 0, list);
BinaryWriter mywriter = new BinaryWriter(thestream);
mywriter.Write("ehlo");
mywriter.Write(new byte[512]);
mywriter.Flush();
}
else
{
Stream thestream = File.Open(Environment.CurrentDirectory + "\\sample.txt", FileMode.Open, FileAccess.ReadWrite);
PasswordDeriveBytes mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes(opcode), Encoding.ASCII.GetBytes(opcode));
byte[] key = mybytes.GetBytes(32);
mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes((IDCID.Length + password.Length + opcode.Length * 15).ToString()), Encoding.ASCII.GetBytes((IDCID.Length + password.Length + 5 + opcode.Length * 24).ToString()));
byte[] IV = mybytes.GetBytes(32);
keyPair mypair = new GlobalGridCore.keyPair(IV, key);
mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes(password), Encoding.ASCII.GetBytes(password));
key = mybytes.GetBytes(32);
mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes((IDCID.Length + password.Length + opcode.Length * 9).ToString()), Encoding.ASCII.GetBytes((IDCID.Length + password.Length + 7 + opcode.Length * 24).ToString()));
IV = mybytes.GetBytes(32);
keyPair secondpair = new keyPair(IV, key);
mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes(IDCID), Encoding.ASCII.GetBytes(IDCID));
key = mybytes.GetBytes(32);
mybytes = new PasswordDeriveBytes(Encoding.Unicode.GetBytes((IDCID.Length + password.Length + opcode.Length * 2).ToString()), Encoding.ASCII.GetBytes((IDCID.Length + password.Length + 14 + opcode.Length * 7).ToString()));
IV = mybytes.GetBytes(32);
keyPair thirdpair = new keyPair(IV, key);
keyPair[] list = new keyPair[] { mypair, secondpair, thirdpair };
thestream = gridCrypto.Decrypt(thestream, list);
BinaryReader myreader = new BinaryReader(thestream);
Console.WriteLine(myreader.ReadString());
Console.ReadLine();
}
}
}
cryptDriver.cs
abstract class gridCrypto
{
/// <summary>
/// Decrypts the input stream to the output stream
/// </summary>
/// <param name="source">I</param>
/// <param name="dest">O</param>
/// <param name="cryptInfo">U</param>
public static Stream Decrypt(Stream source, params keyPair[] cryptInfo)
{
Stream prevStream = source;
foreach (keyPair et in cryptInfo)
{
Rijndael mydale = Rijndael.Create();
mydale.BlockSize = 256;
mydale.KeySize = 256;
mydale.IV = et.IV;
mydale.Key = et.key;
CryptoStream mystream = new CryptoStream(prevStream, mydale.CreateDecryptor(), CryptoStreamMode.Read);
prevStream = mystream;
}
return prevStream;
}
/// <summary>
/// Encrypts the input stream and securely deletes the input file with the specified number of passes. The source stream MUST have length
/// </summary>
/// <param name="source">The source stream (to be deleted)</param>
/// <param name="dest">The destination stream</param>
/// <param name="delcount">The number of passes to erase the file</param>
/// <param name="cryptInfo">Crypto stuff</param>
public static Stream Encrypt(Stream source, int delcount, params keyPair[] cryptInfo)
{
Stream prevStream = source;
foreach (keyPair et in cryptInfo)
{
Rijndael mydale = Rijndael.Create();
mydale.BlockSize = 256;
mydale.KeySize = 256;
mydale.IV = et.IV;
mydale.Key = et.key;
CryptoStream mystream = new CryptoStream(prevStream, mydale.CreateEncryptor(), CryptoStreamMode.Write);
prevStream = mystream;
}
return prevStream;
//int cpos = 0;
//while (cpos < delcount)
//{
// source.Position = 0;
// while (source.Position < source.Length)
// {
// if (source.Length - source.Position > 512)
// {
// Random mrand = new Random();
// byte[] thearray = new byte[512];
// mrand.NextBytes(thearray);
// source.Write(thearray, 0, thearray.Length);
// }
// else
// {
// Random mrand = new Random();
// byte[] thearray = new byte[source.Length-source.Position];
// mrand.NextBytes(thearray);
// source.Write(thearray, 0, thearray.Length);
// source.Flush();
// }
// }
// cpos += 1;
//}
}
}
class keyPair
{
public byte[] IV;
public byte[] key;
public keyPair(byte[] InitializationVector, byte[] Key)
{
IV = InitializationVector;
key = Key;
}
}
删除文件的代码已注释掉,并且未在程序中使用。
答案 0 :(得分:1)
如果我理解正确,您的密码必须在解密时以相反的顺序使用。
在Program.cs的解密部分尝试:
keyPair[] list = new keyPair[] { thirdpair, secondpair, mypair };
thestream = gridCrypto.Decrypt(thestream, list);
答案 1 :(得分:1)
你没有处理你的流。将其插入加密测试代码:
thestream.Dispose();
或(最好)使用using
语句打开文件:
using (Stream stream = File.Open(...))
{
}
最后,它有效。
在使用流时,您应该(几乎)总是使用using
语句,以确保它们正确关闭。在加密流的情况下,关闭流也会写入最后一个块。
我有点惊讶你不需要反转键的顺序......但是密钥创建代码非常模糊,我真的不想进一步探索它:(
答案 2 :(得分:0)
你确定new CryptoStream
构造函数不会产生任何线程吗?
您确定当prevStream = mystream
新创建的mystream
实际写完了吗?
也许您需要首先“刷新”流,并确保在将其分配给旧对象之前已完成调用。我不知道图书馆,但这对我来说似乎是一种竞争条件。
答案 3 :(得分:0)
为什么不将它们加密为字节数组,然后通过另一种算法运行这些字节。
如果您设计得很好,那么您可以使用n个加密算法,如果需要,可以将其中一个嵌入到另一个中。
但是,如果你想要走你的路线那么你可能想把它分解成单独的测试步骤,看看问题可能在哪里。
所以,你先用一种算法加密,然后立即解密,再用两次,然后三次。
您应该对此进行单元测试,以便您可以使用短消息然后长消息进行测试,以确保您没有消息大小的问题。
答案 4 :(得分:0)
我认为问题在于您不使用加密发生的CryptoStream的Write方法。 您只是初始化它们,它们设置您要写入的流而不是从中读取。看看此示例:
http://msdn.microsoft.com/en-us/library/k1f992c1.aspx
说:
// Create or open the specified file.
FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);
// Create a new Rijndael object.
Rijndael RijndaelAlg = Rijndael.Create();
// Create a CryptoStream using the FileStream
// and the passed key and initialization vector (IV).
CryptoStream cStream = new CryptoStream(fStream,
RijndaelAlg.CreateEncryptor(Key, IV),
CryptoStreamMode.Write);
// Create a StreamWriter using the CryptoStream.
StreamWriter sWriter = new StreamWriter(cStream);
try
{
// Write the data to the stream
// to encrypt it.
sWriter.WriteLine(Data);
}
.....
我个人总是使用TransfromBlock,因为我知道我的输入和输出字节是什么。
答案 5 :(得分:0)
这是服务器上的文件系统问题。它在服务器管理员在服务器上运行FSRepair后修复(它恰好是一个损坏的虚拟硬盘,而不是程序中的错误)。