Шифрование файла с 3 паролями - PullRequest
2 голосов
/ 12 сентября 2010

Это какая-то необычная проблема. У меня проблемы с шифрованием файла с использованием 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;
    }
}

Код для удаления файла закомментирован и не используется в программе.

Ответы [ 6 ]

1 голос
/ 13 сентября 2010

Вы не избавляетесь от своего потока.Вставьте это в свой код теста шифрования:

thestream.Dispose();

или (предпочтительно) используйте оператор using, чтобы открыть файл:

using (Stream stream = File.Open(...))
{
}

в конце, и это работает.

Вы должны (почти) всегда использовать операторы using при использовании потоков, чтобы убедиться, что они закрыты должным образом.В случае криптопотоков при закрытии потока также записывается последний блок.

Я несколько удивлен, что вам не нужно менять порядок ключей в обратном порядке ... но код создания ключа достаточно неясенчто я действительно не хочу исследовать это намного дальше: (

1 голос
/ 13 сентября 2010

Если я правильно понимаю, ваши пароли должны быть использованы в обратном порядке при расшифровке.

Попробуйте сделать это в расшифровке вашей Program.cs:

  keyPair[] list = new keyPair[] { thirdpair, secondpair, mypair };
  thestream = gridCrypto.Decrypt(thestream, list);
0 голосов
/ 13 сентября 2010

Это была проблема файловой системы на сервере.Это было исправлено после того, как администратор сервера запустил FSRepair на сервере (это был поврежденный виртуальный жесткий диск, а не ошибка в программе).

0 голосов
/ 13 сентября 2010

Я полагаю, что проблема в том, что вы не используете метод записи CryptoStream, где происходит шифрование. Вы просто инициализируете их, которые задают поток, в который вы будете писать, а не читать. Посмотрите на этот пример:

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, потому что я знаю, каковы мои входные и выходные байты.

0 голосов
/ 13 сентября 2010

Почему бы просто не зашифровать их в массив байтов, а затем запустить эти байты с помощью другого алгоритма.

Если вы спроектируете его хорошо, у вас может быть n-количество алгоритмов шифрования, и вы можете встроить их внутрьдругой, если вы хотите.

Но, если вы хотите пойти по своему маршруту, вы можете разбить его на отдельные этапы для тестирования, чтобы увидеть, где может быть проблема.

Итак, вы сначала зашифруете одним алгоритмом, затем сразу расшифруете, затем используете два, а затем три.

Для этого вам нужно выполнить модульный тест, чтобы вы могли тестировать короткое, а затем длинное сообщение, чтобыубедитесь, что у вас нет проблем с размером сообщения.

0 голосов
/ 12 сентября 2010

Вы уверены, что конструктор new CryptoStream не создает ни одного потока?

Вы уверены, что когда вы делаете prevStream = mystream вновь созданный mystream фактически закончил писать?

Возможно, вам нужно сначала «очистить» поток и убедиться, что вызов завершен, прежде чем назначить его более старому объекту.Я не знаю библиотеку, но для меня это похоже на состояние гонки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...