Example #1
0
        public bool Decrypt(string FilePath, byte[] Key, int Rounds, Mode Mode, EncryptionMode EncrMode)
        {
            FileManagement   fm = new FileManagement();
            SerpentAlgorithm sa;

            if (Mode == Mode.Standard)
            {
                sa = new SerpentStandardMode();
            }
            else
            {
                return(false);
            }

            ErrorCode   errorCode;
            int         m        = AlphabetLength;
            int         position = 0;
            string      outputExtension;
            List <byte> InputFileFragment;
            string      destFilePath = string.Empty;
            FileInfo    fi           = new FileInfo(FilePath);
            int         fragmentSize = 1024 * 1024; // 1 MB (musi dać się wyciągnąć pierwiastek czwartego stopnia)
            Encoding    enc          = new UTF8Encoding();

            sa.Rounds    = Rounds;
            sa.BlockSize = BlockSize;
            string tempFilePath = FilePath + ".temp";

            byte[] iv = fm.GetFileFragment(FilePath, 0, BlockSize, out errorCode);
            byte[] plainControlSum            = fm.GetFileFragment(FilePath, BlockSize, BlockSize, out errorCode);
            byte[] roundBytesFromPtControlSum = new byte[0];
            byte[] previousBlock = new byte[0];

            if (errorCode == ErrorCode.GetFileFailed)
            {
                return(false);
            }

            List <byte> listRoundsBytesFromPtControlSum = new List <byte>();

            for (int i = 0; i < BlockSize; i++)
            {
                if (plainControlSum[i] != 3)
                {
                    listRoundsBytesFromPtControlSum.Add(plainControlSum[i]);
                }
                else
                {
                    roundBytesFromPtControlSum = listRoundsBytesFromPtControlSum.ToArray();
                    break;
                }
            }

            int    readRoundsFromPtControlSum        = 0;
            string strRoundsFromPtControlSum         = enc.GetString(roundBytesFromPtControlSum);
            bool   areRoundsFromPtControlSumParsable = int.TryParse(enc.GetString(roundBytesFromPtControlSum), out readRoundsFromPtControlSum);

            if (!areRoundsFromPtControlSumParsable || readRoundsFromPtControlSum > 64)
            {
                return(false);
            }
            else if (readRoundsFromPtControlSum != Rounds)
            {
                if (Mode != Mode.Standard)
                {
                    return(Decrypt(FilePath, Key, readRoundsFromPtControlSum, Mode.Standard, EncrMode));
                }
                else
                {
                    Rounds    = readRoundsFromPtControlSum;
                    sa.Rounds = readRoundsFromPtControlSum;
                }
            }

            byte[] ptFragment  = new byte[BlockSize];
            object expandedKey = sa.MakeKey(Key);

            fm.ShiftBytesFromFile(FilePath, tempFilePath, BlockSize * 2, out errorCode); // usuń z pliku dwa bloki - sumę kontrolną i initalization vector

            if (errorCode == ErrorCode.ShiftFileFailed)
            {
                return(false);
            }

            do
            {
                InputFileFragment = fm.GetFileFragment(tempFilePath, position, fragmentSize, out errorCode).ToList();

                if (errorCode == ErrorCode.GetFileFailed)
                {
                    return(false);
                }

                List <byte> OutputFileFragment = new List <byte>();

                // DESZYFROWANIE BLOKU

                for (int i = 0; i < InputFileFragment.Count; i += BlockSize)
                {
                    if (EncrMode == EncryptionMode.ECB)
                    {
                        OutputFileFragment.AddRange(sa.BlockDecrypt(InputFileFragment.GetRange(i, BlockSize).ToArray(), 0, expandedKey));
                    }
                    else if (EncrMode == EncryptionMode.CBC)
                    {
                        if (position == 0 && i == 0)
                        {
                            previousBlock = iv;
                        }
                        byte[] cipherText = InputFileFragment.GetRange(i, BlockSize).ToArray();
                        byte[] currBlock  = sa.BlockDecrypt(cipherText, 0, expandedKey);
                        byte[] plainText  = currBlock.XOR(previousBlock);
                        OutputFileFragment.AddRange(plainText);
                        previousBlock = cipherText;
                    }
                    else
                    {
                        return(false);
                    }
                }

                // ===================

                if (position == 0)                                                  // jeśli odszyfrowałem pierwszy fragment pliku, przed zapisaniem usuwam z tablicy bajty dodane przy szyfrowaniu
                {
                    int    shiftedbytes        = OutputFileFragment[BlockSize * 2]; // zawartość 32 bajtu, 0 - 15 deszyfrowana suma kontrolna, 16-31 rozszerzenie i ilość rund
                    byte[] decryptedControlSum = new byte[BlockSize];
                    byte[] extBytes            = new byte[1];
                    byte[] roundBytes          = new byte[1];
                    int    i = 0;

                    for (; i < BlockSize; i++) // zczytaj sumę kontrolną
                    {
                        decryptedControlSum[i] = OutputFileFragment[i];
                    }

                    List <byte> listExtbytes = new List <byte>();

                    for (; i < BlockSize * 2; i++) // zczytaj rozszerzenie
                    {
                        if (OutputFileFragment[i] != 3)
                        {
                            listExtbytes.Add(OutputFileFragment[i]);
                        }
                        else
                        {
                            extBytes = listExtbytes.ToArray();
                            break;
                        }
                    }

                    i++;
                    List <byte> listRoundsBytes = new List <byte>();

                    for (; i < BlockSize * 2; i++)  // zczytaj zaszyfrowaną ilość rund
                    {
                        if (OutputFileFragment[i] != 3)
                        {
                            listRoundsBytes.Add(OutputFileFragment[i]);
                        }
                        else
                        {
                            roundBytes = listRoundsBytes.ToArray();
                            break;
                        }
                    }
                    Process.Start(@"F:\serpentDecrypt.txt");
                    outputExtension = enc.GetString(extBytes);
                    destFilePath    = Path.ChangeExtension(FilePath, outputExtension);
                    int  readRounds;
                    bool areRoundsParsable = int.TryParse(enc.GetString(roundBytes), out readRounds);

                    if (!plainControlSum.SequenceEqual(decryptedControlSum) || !areRoundsParsable || shiftedbytes > 16 || readRounds != Rounds)
                    {
                        fm.DeleteTempFile(tempFilePath, out errorCode);
                        return(false);
                    }

                    int shiftedBytesAndInfoBytes = shiftedbytes + BlockSize * 2;

                    for (; shiftedBytesAndInfoBytes > 0; shiftedBytesAndInfoBytes--)
                    {
                        OutputFileFragment.RemoveAt(0);
                    }
                }

                fm.SaveFileFragment(destFilePath, position, OutputFileFragment.ToArray(), out errorCode); // zapisuję kolejną część pliku do pliku docelowego

                if (errorCode == ErrorCode.SaveFileFailed)                                                // w razie błędu szyfrowanie nie powiodło się
                {
                    return(false);
                }

                position += fragmentSize;                                                                                                                                                                     // ustaw pozycję kolejnego fragmentu
                EncryptionProgressChangedEventArgs encryptionProgressChangedEventData = new EncryptionProgressChangedEventArgs(((int)((double)position / (double)fi.Length * 100.0)), ActionType.Decryption); // inicjalizuję dane dla event handlera (obliczony postęp, typ - szyfrowanie czy deszyfrowanie)
                OnEncryptionProgressChanging(encryptionProgressChangedEventData);                                                                                                                             // wywołuję zdarzenie z utworzonymi wcześniej parametrami
            }while (position <= fi.Length);                                                                                                                                                                   // pętlę powtarzam dopóki nie skończy się plik

            fm.DeleteTempFile(tempFilePath, out errorCode);                                                                                                                                                   // usuń plik tymczasowy


            return(true);
        }
Example #2
0
        public bool Decrypt(string FilePath, byte[] Key, int Rounds, Mode Mode, EncryptionMode EncrMode)
        {
            FileManagement   fm = new FileManagement();
            SerpentAlgorithm sa;

            if (Mode == Mode.Standard)
            {
                sa = new SerpentStandardMode();
            }
            else if (Mode == Mode.BitSlice)
            {
                sa = new SerpentBitSliceMode();
            }
            else
            {
                MessageBox.Show("Wybrany tryb algorytmu nie jest zaimplementowany. ", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return(false);
            }

            ErrorCode   errorCode;
            int         m        = AlphabetLength;
            int         position = 0;
            string      outputExtension;
            List <byte> InputFileFragment;
            string      destFilePath = string.Empty;
            FileInfo    fi           = new FileInfo(FilePath);
            int         fragmentSize = 1024 * 1024; // 1 MB (musi dać się wyciągnąć pierwiastek czwartego stopnia)
            Encoding    enc          = new UTF8Encoding();

            sa.Rounds    = Rounds;
            sa.BlockSize = BlockSize;
            string tempFilePath = FilePath + ".temp";

            byte[] iv = fm.GetFileFragment(FilePath, 0, BlockSize, out errorCode);
            byte[] plainControlSum            = fm.GetFileFragment(FilePath, BlockSize, BlockSize, out errorCode);
            byte[] roundBytesFromPtControlSum = new byte[0];
            byte[] previousBlock = new byte[0];

            if (errorCode == ErrorCode.GetFileFailed)
            {
                MessageBox.Show("Plik nie mógł zostac wczytany.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return(false);
            }

            List <byte> listRoundsBytesFromPtControlSum = new List <byte>();

            for (int i = 0; i < BlockSize; i++)
            {
                if (plainControlSum[i] != 3)
                {
                    listRoundsBytesFromPtControlSum.Add(plainControlSum[i]);
                }
                else
                {
                    roundBytesFromPtControlSum = listRoundsBytesFromPtControlSum.ToArray();
                    break;
                }
            }

            int    readRoundsFromPtControlSum        = 0;
            string strRoundsFromPtControlSum         = enc.GetString(roundBytesFromPtControlSum);
            bool   areRoundsFromPtControlSumParsable = int.TryParse(enc.GetString(roundBytesFromPtControlSum), out readRoundsFromPtControlSum);

            if (!areRoundsFromPtControlSumParsable || readRoundsFromPtControlSum > 64)
            {
                MessageBox.Show("Plik nie jest zaszyfrowany lub jest zaszyfrowany innym algorytmem.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return(false);
            }
            else if (readRoundsFromPtControlSum != Rounds)
            {
                if (Mode != Mode.Standard)
                {
                    MessageBoxResult result = MessageBox.Show(string.Format("Plik został zaszyfrowany inną liczbą rund ({0}) algorytmu Serpent niż podana ({1}), ale w trybie innym niż Standardowy nie można odszyfrować przy użyciu takiej liczby rund. Czy chcesz zmienić tryb na Standardowy i liczbę rund na {0}? (UWAGA: Operacja deszyfrowania może trwać bardzo długo dla dużych plików). ", readRoundsFromPtControlSum, Rounds), "Ostrzeżenie", MessageBoxButton.YesNo, MessageBoxImage.Warning);

                    if (result == MessageBoxResult.Yes)
                    {
                        return(Decrypt(FilePath, Key, readRoundsFromPtControlSum, Mode.Standard, EncrMode));
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    MessageBoxResult result = MessageBox.Show(string.Format("Wygląda na to, że plik został zaszyfrowany inną liczbą rund ({0}) algorytmu Serpent niż podana ({1}) lub plik w ogóle nie jest zaszyfrowany. Czy chcesz zmienić liczbę rund na {0}?", readRoundsFromPtControlSum, Rounds), "Ostrzeżenie", MessageBoxButton.YesNo, MessageBoxImage.Question);

                    if (result == MessageBoxResult.Yes)
                    {
                        Rounds    = readRoundsFromPtControlSum;
                        sa.Rounds = readRoundsFromPtControlSum;
                    }
                }
            }

            byte[] ptFragment  = new byte[BlockSize];
            object expandedKey = sa.MakeKey(Key);

            fm.ShiftBytesFromFile(FilePath, tempFilePath, BlockSize * 2, out errorCode); // usuń z pliku dwa bloki - sumę kontrolną i initalization vector

            if (errorCode == ErrorCode.ShiftFileFailed)
            {
                MessageBox.Show("Plik nie mógł zostac zmodyfikowany.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return(false);
            }

            do
            {
                InputFileFragment = fm.GetFileFragment(tempFilePath, position, fragmentSize, out errorCode).ToList();

                if (errorCode == ErrorCode.GetFileFailed)
                {
                    MessageBox.Show("Plik nie mógł zostac wczytany.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return(false);
                }

                List <byte> OutputFileFragment = new List <byte>();

                // DESZYFROWANIE BLOKU

                for (int i = 0; i < InputFileFragment.Count; i += BlockSize)
                {
                    if (EncrMode == EncryptionMode.ECB)
                    {
                        OutputFileFragment.AddRange(sa.BlockDecrypt(InputFileFragment.GetRange(i, BlockSize).ToArray(), 0, expandedKey));
                    }
                    else if (EncrMode == EncryptionMode.CBC)
                    {
                        if (position == 0 && i == 0)
                        {
                            previousBlock = iv;
                        }
                        byte[] cipherText = InputFileFragment.GetRange(i, BlockSize).ToArray();
                        byte[] currBlock  = sa.BlockDecrypt(cipherText, 0, expandedKey);
                        byte[] plainText  = currBlock.XOR(previousBlock);
                        OutputFileFragment.AddRange(plainText);
                        previousBlock = cipherText;
                    }
                    else
                    {
                        MessageBox.Show("Wybrany tryb szyfrowania nie jest zaimplementowany. ", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        return(false);
                    }
                }

                // ===================

                if (position == 0)                                                  // jeśli odszyfrowałem pierwszy fragment pliku, przed zapisaniem usuwam z tablicy bajty dodane przy szyfrowaniu
                {
                    int    shiftedbytes        = OutputFileFragment[BlockSize * 2]; // zawartość 32 bajtu, 0 - 15 deszyfrowana suma kontrolna, 16-31 rozszerzenie i ilość rund
                    byte[] decryptedControlSum = new byte[BlockSize];
                    byte[] extBytes            = new byte[1];
                    byte[] roundBytes          = new byte[1];
                    int    i = 0;

                    for (; i < BlockSize; i++) // zczytaj sumę kontrolną
                    {
                        decryptedControlSum[i] = OutputFileFragment[i];
                    }

                    List <byte> listExtbytes = new List <byte>();

                    for (; i < BlockSize * 2; i++) // zczytaj rozszerzenie
                    {
                        if (OutputFileFragment[i] != 3)
                        {
                            listExtbytes.Add(OutputFileFragment[i]);
                        }
                        else
                        {
                            extBytes = listExtbytes.ToArray();
                            break;
                        }
                    }

                    i++;
                    List <byte> listRoundsBytes = new List <byte>();

                    for (; i < BlockSize * 2; i++)  // zczytaj zaszyfrowaną ilość rund
                    {
                        if (OutputFileFragment[i] != 3)
                        {
                            listRoundsBytes.Add(OutputFileFragment[i]);
                        }
                        else
                        {
                            roundBytes = listRoundsBytes.ToArray();
                            break;
                        }
                    }

                    outputExtension = enc.GetString(extBytes);
                    destFilePath    = Path.ChangeExtension(FilePath, outputExtension);
                    int  readRounds;
                    bool areRoundsParsable = int.TryParse(enc.GetString(roundBytes), out readRounds);

                    if (!plainControlSum.SequenceEqual(decryptedControlSum) || !areRoundsParsable || shiftedbytes > 16 || readRounds != Rounds)
                    {
                        fm.DeleteTempFile(tempFilePath, out errorCode);
                        if (errorCode == ErrorCode.DeletingTempFileFailed)
                        {
                            MessageBox.Show("Plik tymczasowy nie mógł zostać usunięty.", "Ostrzeżenie", MessageBoxButton.OK, MessageBoxImage.Warning);
                        }

                        MessageBox.Show("Klucz jest nieprawidłowy. ", "Error", MessageBoxButton.OK, MessageBoxImage.Error);

                        return(false);
                    }

                    int shiftedBytesAndInfoBytes = shiftedbytes + BlockSize * 2;

                    for (; shiftedBytesAndInfoBytes > 0; shiftedBytesAndInfoBytes--)
                    {
                        OutputFileFragment.RemoveAt(0);
                    }
                }

                fm.SaveFileFragment(destFilePath, position, OutputFileFragment.ToArray(), out errorCode); // zapisuję kolejną część pliku do pliku docelowego

                if (errorCode == ErrorCode.SaveFileFailed)                                                // w razie błędu szyfrowanie nie powiodło się
                {
                    MessageBox.Show("Plik nie mógł zostac zapisany. ", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return(false);
                }

                position += fragmentSize;                                                                                                                                                                     // ustaw pozycję kolejnego fragmentu
                EncryptionProgressChangedEventArgs encryptionProgressChangedEventData = new EncryptionProgressChangedEventArgs(((int)((double)position / (double)fi.Length * 100.0)), ActionType.Decryption); // inicjalizuję dane dla event handlera (obliczony postęp, typ - szyfrowanie czy deszyfrowanie)
                OnEncryptionProgressChanging(encryptionProgressChangedEventData);                                                                                                                             // wywołuję zdarzenie z utworzonymi wcześniej parametrami
            }while (position <= fi.Length);                                                                                                                                                                   // pętlę powtarzam dopóki nie skończy się plik

            fm.DeleteTempFile(tempFilePath, out errorCode);                                                                                                                                                   // usuń plik tymczasowy

            if (errorCode == ErrorCode.DeletingTempFileFailed)
            {
                MessageBox.Show("Plik tymczasowy nie mógł zostać usunięty.", "Ostrzeżenie", MessageBoxButton.OK, MessageBoxImage.Warning);
            }

            return(true);
        }