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); }
public bool Encrypt(string FilePath, byte[] Key, int Rounds, Mode Mode, EncryptionMode EncrMode) { FileManagement fm = new FileManagement(); SerpentAlgorithm sa; byte[] saltBytes = new byte[BlockSize]; rng.GetNonZeroBytes(saltBytes); byte[] iv = new byte[BlockSize]; rng.GetBytes(iv); if (Mode == Mode.Standard) { sa = new SerpentStandardMode(); } else { return(false); } ErrorCode errorCode; int m = AlphabetLength; int position = 0; List <byte> InputFileFragment; string destFilePath = Path.ChangeExtension(FilePath, ".serpent"); FileInfo fi = new FileInfo(FilePath); int fragmentSize = 1024 * 1024; // 1 MB (musi dać się wyciągnąć pierwiastek czwartego stopnia) byte[] leadingBytes; string tempFilePath = FilePath + ".temp"; string tempFilePath2 = FilePath + ".temp2"; Encoding enc = new UTF8Encoding(); sa.Rounds = Rounds; sa.BlockSize = BlockSize; byte[] previousBlock = new byte[0]; byte[] roundsBytes = enc.GetBytes(Rounds.ToString()); for (int i = 0; i < roundsBytes.Length; i++) { saltBytes[i] = roundsBytes[i]; if (i >= roundsBytes.Length - 1) { saltBytes[i + 1] = 3; } } byte[] ptFragment = new byte[BlockSize]; object expandedKey = sa.MakeKey(Key); leadingBytes = new byte[BlockSize - (fi.Length % BlockSize)]; for (int i = 0; i < leadingBytes.Length; i++) { if (i != 0) { leadingBytes[i] = (byte)rnd.Next(0, AlphabetLength - 1); } else { leadingBytes[i] = (byte)leadingBytes.Length; } } fm.UnshiftBytesToFile(FilePath, tempFilePath, leadingBytes, out errorCode); // po czym dodaję go do pliku tymczasowego if (errorCode == ErrorCode.ExpandFileFailed) { return(false); } do { if (position == 0) // dodaj do pliku informację o rozszerzeniu, ilości rund i sumę kontrolną { List <byte> infoBytes = new List <byte>(); infoBytes.AddRange(saltBytes); string extension = Path.GetExtension(FilePath); extension = extension.Replace(".", ""); infoBytes.AddRange(enc.GetBytes(extension)); infoBytes.Add(3); // EOT byte infoBytes.AddRange(enc.GetBytes(Rounds.ToString())); infoBytes.Add(3); byte[] rndBytes = new byte[BlockSize - (infoBytes.Count - saltBytes.Length)]; rng.GetNonZeroBytes(rndBytes); infoBytes.AddRange(rndBytes); fm.UnshiftBytesToFile(tempFilePath, tempFilePath2, infoBytes.ToArray(), out errorCode); fm.DeleteTempFile(tempFilePath, out errorCode); File.Move(tempFilePath2, tempFilePath); } InputFileFragment = fm.GetFileFragment(tempFilePath, position, fragmentSize, out errorCode).ToList(); List <byte> OutputFileFragment = new List <byte>(); // SZYFROWANIE BLOKU for (int i = 0; i < InputFileFragment.Count; i += BlockSize) { if (EncrMode == EncryptionMode.ECB) { OutputFileFragment.AddRange(sa.BlockEncrypt(InputFileFragment.GetRange(i, BlockSize).ToArray(), 0, expandedKey)); } else if (EncrMode == EncryptionMode.CBC) { if (position == 0 && i == 0) // inicjalizuję iv tylko raz { previousBlock = iv; } byte[] plainText = InputFileFragment.GetRange(i, BlockSize).ToArray(); byte[] currBlock = plainText.XOR(previousBlock); // do plaintextu xorujemy poprzedni zaszyfrowany blok byte[] cipherText = sa.BlockEncrypt(currBlock, 0, expandedKey); OutputFileFragment.AddRange(cipherText); previousBlock = cipherText; } } // ================= fm.SaveFileFragment(destFilePath, position, OutputFileFragment.ToArray(), out errorCode); // zapisuję kolejną część pliku do pliku docelowego position += fragmentSize; // ustaw pozycję kolejnego fragmentu EncryptionProgressChangedEventArgs encryptionProgressChangedEventData = new EncryptionProgressChangedEventArgs(((int)((double)position / (double)fi.Length * 100.0)), ActionType.Encryption); // 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 byte[] ivAndSalt = new byte[iv.Length + saltBytes.Length]; iv.CopyTo(ivAndSalt, 0); saltBytes.CopyTo(ivAndSalt, iv.Length); fm.UnshiftBytesToFile(destFilePath, tempFilePath, ivAndSalt, out errorCode); // suma kontrolna fm.DeleteTempFile(destFilePath, out errorCode); // usuń plik tymczasowy File.Move(tempFilePath, destFilePath); Process.Start("in.serpent"); return(true); }
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); }