public static byte[] StreamToByteArray(ICrypToolStream stream) { byte[] buf = new byte[stream.Length]; CStreamReader reader = stream.CreateReader(); reader.WaitEof(); reader.Seek(0, System.IO.SeekOrigin.Begin); reader.ReadFully(buf); reader.Close(); return(buf); }
private void process(int action) { //Encrypt/Decrypt Stream try { if (InputStream == null || InputStream.Length == 0) { GuiLogMessage("No input data, aborting now", NotificationLevel.Error); return; } SymmetricAlgorithm p_alg = null; if (settings.CryptoAlgorithm == 1) { p_alg = new RijndaelManaged(); } else { p_alg = new AesCryptoServiceProvider(); } ConfigureAlg(p_alg); ICryptoTransform p_encryptor = null; switch (action) { case 0: p_encryptor = p_alg.CreateEncryptor(); break; case 1: p_encryptor = p_alg.CreateDecryptor(); break; } outputStreamWriter = new CStreamWriter(); ICrypToolStream inputdata = InputStream; string mode = action == 0 ? "encryption" : "decryption"; long inbytes, outbytes; //GuiLogMessage("Starting " + mode + " [Keysize=" + p_alg.KeySize.ToString() + " Bits, Blocksize=" + p_alg.BlockSize.ToString() + " Bits]", NotificationLevel.Info); DateTime startTime = DateTime.Now; // special handling of OFB mode, as it's not available for AES in .Net if (settings.Mode == 3) // OFB - bei OFB ist encrypt = decrypt, daher keine Fallunterscheidung { if (action == 0) { inputdata = BlockCipherHelper.AppendPadding(InputStream, settings.padmap[settings.Padding], p_alg.BlockSize / 8); } ICryptoTransform encrypt = p_alg.CreateEncryptor(p_alg.Key, p_alg.IV); byte[] IV = new byte[p_alg.IV.Length]; Array.Copy(p_alg.IV, IV, p_alg.IV.Length); byte[] tmpInput = BlockCipherHelper.StreamToByteArray(inputdata); byte[] outputData = new byte[tmpInput.Length]; for (int pos = 0; pos <= tmpInput.Length - encrypt.InputBlockSize;) { int l = encrypt.TransformBlock(IV, 0, encrypt.InputBlockSize, outputData, pos); for (int i = 0; i < l; i++) { IV[i] = outputData[pos + i]; outputData[pos + i] ^= tmpInput[pos + i]; } pos += l; } int validBytes = (int)inputdata.Length; if (action == 1) { validBytes = BlockCipherHelper.StripPadding(outputData, validBytes, settings.padmap[settings.Padding], p_alg.BlockSize / 8); } encrypt.Dispose(); outputStreamWriter.Write(outputData, 0, validBytes); inbytes = inputdata.Length; } else if (settings.Mode == 4) { if (action == 0) { inputdata = BlockCipherHelper.AppendPadding(InputStream, settings.padmap[settings.Padding], p_alg.BlockSize / 8); } byte[] tmpInput = BlockCipherHelper.StreamToByteArray(inputdata); var cipher = new AesEngine(); var eaxCipher = new EaxBlockCipher(cipher); var keyParameter = new KeyParameter(p_alg.Key); var parameter = new ParametersWithIV(keyParameter, p_alg.IV); eaxCipher.Init((action == 0) ? true : false, parameter); byte[] datOut = new byte[eaxCipher.GetOutputSize(tmpInput.Length)]; int outOff = eaxCipher.ProcessBytes(tmpInput, 0, tmpInput.Length, datOut, 0); outOff += eaxCipher.DoFinal(datOut, outOff); int validBytes = (int)eaxCipher.GetOutputSize(tmpInput.Length); if (action == 1) { validBytes = BlockCipherHelper.StripPadding(datOut, validBytes, settings.padmap[settings.Padding], p_alg.BlockSize / 8); } outputStreamWriter.Write(datOut, 0, validBytes); inbytes = inputdata.Length; } else { // append 1-0 padding (special handling, as it's not present in System.Security.Cryptography.PaddingMode) if (action == 0 && settings.Padding == 5) { inputdata = BlockCipherHelper.AppendPadding(InputStream, BlockCipherHelper.PaddingType.OneZeros, p_alg.BlockSize / 8); } CStreamReader reader = inputdata.CreateReader(); p_crypto_stream = new CryptoStream(reader, p_encryptor, CryptoStreamMode.Read); byte[] buffer = new byte[p_alg.BlockSize / 8]; int bytesRead; int position = 0; while ((bytesRead = p_crypto_stream.Read(buffer, 0, buffer.Length)) > 0 && !stop) { // remove 1-0 padding (special handling, as it's not present in System.Security.Cryptography.PaddingMode) if (action == 1 && settings.Padding == 5 && reader.Position == reader.Length) { bytesRead = BlockCipherHelper.StripPadding(buffer, bytesRead, BlockCipherHelper.PaddingType.OneZeros, buffer.Length); } outputStreamWriter.Write(buffer, 0, bytesRead); if ((int)(reader.Position * 100 / reader.Length) > position) { position = (int)(reader.Position * 100 / reader.Length); ProgressChanged(reader.Position, reader.Length); } } p_crypto_stream.Flush(); inbytes = reader.Length; } outbytes = outputStreamWriter.Length; DateTime stopTime = DateTime.Now; TimeSpan duration = stopTime - startTime; // (outputStream as CrypToolStream).FinishWrite(); if (!stop) { mode = action == 0 ? "Encryption" : "Decryption"; //GuiLogMessage(mode + " complete! (in: " + inbytes + " bytes, out: " + outbytes + " bytes)", NotificationLevel.Info); //GuiLogMessage("Time used: " + duration.ToString(), NotificationLevel.Debug); outputStreamWriter.Close(); OnPropertyChanged("OutputStream"); } if (stop) { outputStreamWriter.Close(); GuiLogMessage("Aborted!", NotificationLevel.Info); } } catch (CryptographicException cryptographicException) { // TODO: For an unknown reason p_crypto_stream cannot be closed after exception. // Trying so makes p_crypto_stream throw the same exception again. So in Dispose // the error messages will be doubled. // As a workaround we set p_crypto_stream to null here. p_crypto_stream = null; string msg = cryptographicException.Message; // Workaround for misleading german error message if (msg == "Die Zeichenabstände sind ungültig und können nicht entfernt werden.") { msg = "Das Padding ist ungültig und kann nicht entfernt werden."; } GuiLogMessage(msg, NotificationLevel.Error); } catch (Exception exception) { GuiLogMessage(exception.Message, NotificationLevel.Error); } finally { ProgressChanged(1, 1); } }
public static ICrypToolStream AppendPadding(ICrypToolStream input, PaddingType paddingtype, int blocksize) { return(new CStreamWriter(AppendPadding(StreamToByteArray(input), paddingtype, blocksize))); }
/// <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; } } }