private void Reset() { try { stop = false; inputKey = null; outputStream = null; if (outputStream != null) { outputStream.Flush(); outputStream.Close(); outputStream.Dispose(); outputStream = null; } } catch (Exception ex) { GuiLogMessage(ex.Message, NotificationLevel.Error); } }
/// <summary> /// Called every time this plugin is run in the workflow execution. /// </summary> public void Execute() { ProgressChanged(0, 1); try { inputStreamReader = InputStream.CreateReader(); //inputStreamReader.WaitEof(); if (!ValidateInputs()) { return; // beende die Ausführung bei Problemen mit den Eingabedaten } debugDataWriter = new CStreamWriter(); if (settings.Debug) { WriteDebug("Starting computation ...\r\n\r\n"); WriteDebug(String.Format("mode: {0}\r\n", settings.HashMode)); if (settings.HashMode != CypherMatrixHashSettings.CypherMatrixHashMode.Mini) { WriteDebug(String.Format("permutation: {0}\r\n", settings.Perm)); } else { WriteDebug("permutation: none\r\n"); } WriteDebug("\r\n\r\n"); } Stopwatch sw = new Stopwatch(); sw.Start(); Hash(); sw.Stop(); if (!stop) { GuiLogMessage(string.Format("Processed {0:N} KiB data in {1} ms.", (double)InputStream.Length / 1024, sw.ElapsedMilliseconds), NotificationLevel.Info); GuiLogMessage(string.Format("Achieved data throughput: {0:N} kB/s", (double)InputStream.Length / sw.ElapsedMilliseconds), NotificationLevel.Info); } } catch (Exception exception) { GuiLogMessage(exception.Message + "\r\n" + exception.StackTrace, NotificationLevel.Error); if (settings.Debug) { WriteDebug("\r\nThe following error occurred during execution:\r\n"); WriteDebug(exception.Message + "\r\n" + exception.StackTrace + "\r\n"); } } finally { if (stop) { GuiLogMessage("Computation aborted!", NotificationLevel.Warning); stop = false; } if (settings.Debug) { WriteDebug("\r\n>>>>>>>>>> END OF OPERATION <<<<<<<<<<"); } else { WriteDebug("You have to enable the debug logging to see the internal variables here."); } debugDataWriter.Flush(); debugDataWriter.Close(); OnPropertyChanged("OutputDebug"); } ProgressChanged(1, 1); }
/// <summary> /// Encrypts/Decrypts using OFB /// </summary> /// <param name="blockCipher"></param> /// <param name="cipherAction"></param> /// <param name="inputStream"></param> /// <param name="outputStream"></param> /// <param name="key"></param> /// <param name="iv"></param> /// <param name="padding"></param> /// <param name="stop"></param> /// <param name="progressChanged"></param> /// <param name="lastInputBlock"></param> /// <param name="blocksize"></param> public static void ExecuteOFB(BlockCipher blockCipher, CipherAction cipherAction, ref ICrypToolStream inputStream, ref ICrypToolStream outputStream, byte[] key, byte[] iv, PaddingType padding, ref bool stop, ProgressChanged progressChanged, ref byte[] lastInputBlock, int blocksize = 8) { using (CStreamReader reader = inputStream.CreateReader()) { using (CStreamWriter writer = new CStreamWriter()) { byte[] lastBlock = iv; int readcount = 0; while (reader.Position < reader.Length && !stop) { //we always try to read a complete block byte[] inputBlock = new byte[blocksize]; readcount = 0; while ((readcount += reader.Read(inputBlock, readcount, blocksize - readcount)) < blocksize && reader.Position < reader.Length && !stop) { ; } if (stop) { return; } //Show progress in UI progressChanged(reader.Position, reader.Length); byte[] outputblock = null; //we read a complete block if (readcount == blocksize) { //Compute XOR with lastblock for OFB mode if (cipherAction == CipherAction.Encrypt) { outputblock = blockCipher(lastBlock, key); lastBlock = outputblock; outputblock = XOR(outputblock, inputBlock); } else { outputblock = blockCipher(lastBlock, key); lastBlock = outputblock; outputblock = XOR(outputblock, inputBlock); } } //we read an incomplete block, thus, we are at the end of the stream else if (readcount > 0) { //Compute XOR with lastblock for CFB mode if (cipherAction == CipherAction.Encrypt) { byte[] block = new byte[blocksize]; Array.Copy(inputBlock, 0, block, 0, readcount); outputblock = blockCipher(lastBlock, key); outputblock = XOR(outputblock, block); } else { byte[] block = new byte[blocksize]; Array.Copy(inputBlock, 0, block, 0, readcount); outputblock = blockCipher(inputBlock, key); outputblock = XOR(outputblock, lastBlock); } } //check if it is the last block and we decrypt, thus, we have to remove the padding if (reader.Position == reader.Length && cipherAction == CipherAction.Decrypt && padding != PaddingType.None) { int valid = StripPadding(outputblock, blocksize, padding, blocksize); if (valid != blocksize) { byte[] newoutputblock = new byte[valid]; Array.Copy(outputblock, 0, newoutputblock, 0, valid); outputblock = newoutputblock; } else if (valid == 0) { outputblock = null; } } //if we crypted something, we output it if (outputblock != null) { writer.Write(outputblock, 0, outputblock.Length); //if we wrote to the stream, we memorize the last input block for the visualization lastInputBlock = inputBlock; } } writer.Flush(); outputStream = writer; } } }
/// <summary> /// En- or decrypt input stream with ChaCha. /// </summary> /// <param name="key">The secret 128-bit or 256-bit key. A 128-bit key will be expanded into a 256-bit key by concatenation with itself.</param> /// <param name="iv">Initialization vector (DJB version: 64-bit, IETF version: 96-bit)</param> /// <param name="initialCounter">Initial counter (DJB version: 64-bit, IETF version: 32-bit)</param> /// <param name="settings">Chosen Settings in the Plugin workspace. Includes Rounds and Version property.</param> /// <param name="input">Input stream</param> /// <param name="output">Output stream</param> /// <param name="keystreamWriter">Keystream Output stream</param> private void Xcrypt(byte[] key, byte[] iv, ulong initialCounter, ChaChaSettings settings, ICryptoolStream input, CStreamWriter output, CStreamWriter keystreamOutput) { if (!(key.Length == 32 || key.Length == 16)) { throw new ArgumentOutOfRangeException("key", key.Length, "Key must be exactly 128-bit or 256-bit."); } if (iv.Length != settings.Version.IVBits / 8) { throw new ArgumentOutOfRangeException("iv", iv.Length, $"IV must be exactly {settings.Version.IVBits}-bit."); } void AssertCounter(ulong counter, ulong max) { if (!(0 <= counter && counter <= max)) { throw new ArgumentOutOfRangeException("initialCounter", counter, $"Initial counter must be between 0 and {max}."); } } if (settings.Version == Version.DJB) { AssertCounter(initialCounter, ulong.MaxValue); } else if (settings.Version == Version.IETF) { AssertCounter(initialCounter, uint.MaxValue); } // The first 512-bit state. Reused for counter insertion. uint[] firstState = State(key, iv, initialCounter, settings.Version); // Buffer to read 512-bit input block byte[] inputBytes = new byte[64]; CStreamReader inputReader = input.CreateReader(); // byte size of input long inputSize = inputReader.Length; // one keystream block is 64 bytes (512 bit) TotalKeystreamBlocks = (int)Math.Ceiling((double)(inputSize) / 64); ulong blockCounter = initialCounter; int read = inputReader.Read(inputBytes); while (read != 0) { // Will hold the state during each keystream uint[] state = (uint[])firstState.Clone(); InsertCounter(ref state, blockCounter, settings.Version); ChaChaHash(ref state, settings.Rounds); byte[] keystream = ByteUtil.ToByteArray(state); keystreamOutput.Write(keystream); byte[] c = ByteUtil.XOR(keystream, inputBytes, read); output.Write(c); // Don't add to InputMessage during diffusion run because it won't // return a different list during the diffusion run. if (!DiffusionExecution) { InputMessage.AddRange(inputBytes.Take(read)); } Keystream.AddRange(keystream.Take(read)); Output.AddRange(c); blockCounter++; // Read next input block read = inputReader.Read(inputBytes); } inputReader.Dispose(); output.Flush(); output.Close(); output.Dispose(); keystreamOutput.Flush(); keystreamOutput.Close(); keystreamOutput.Dispose(); }