public static void Encrypt(StreamCtx ctx, Stream instr, Stream outstr, StreamCipherMonitor monitor) { if (instr.Length <= 0) { return; } byte[] buffer = new byte[ctx.BlockSize()]; byte[] output = new byte[ctx.BlockSize()]; bool ivInited = false; int i = 0; if (monitor != null) { monitor.Progress(0, instr.Length); } do { if (monitor != null) { if (monitor.ShouldStop()) { return; } monitor.Progress(instr.Position, instr.Length); } i = instr.Read(buffer, 0, ctx.BlockSize()); if (i < 0) { i = 0; } if ((i > 0) && (!ivInited)) // first block { ivInited = true; if (ctx.Mode == Mode.CBC) { Array.Copy(ctx.IV, 0, output, 0, output.Length); } } if ((i <= 0) || (i < buffer.Length)) // lastBlock { PrepareLastBuffer(buffer, i); PrepareBuffer(ctx.Mode, buffer, output); ctx.Ibc.Cipher(buffer, output); outstr.Write(output, 0, output.Length); break; } PrepareBuffer(ctx.Mode, buffer, output); ctx.Ibc.Cipher(buffer, output); outstr.Write(output, 0, output.Length); } while(true); outstr.Flush(); if (monitor != null) { if (!monitor.ShouldStop()) { monitor.Progress(instr.Length, instr.Length); } } }
public static void Decrypt(StreamCtx ctx, Stream instr, Stream outstr, StreamCipherMonitor monitor) { // in this method we fail silently if (instr.Length <= 0) { return; } byte[] buffer = new byte[ctx.BlockSize()]; byte[] output = new byte[ctx.BlockSize()]; int i = 0; bool ivInited = false; byte[] iv = new byte[ctx.BlockSize()]; // to delay the output, required because we do not rely in // instr.Length to find the end of stream bool lastInited = false; byte[] last = new byte[ctx.BlockSize()]; if (monitor != null) { monitor.Progress(0, instr.Length); } do { if (monitor != null) { if (monitor.ShouldStop()) { return; } monitor.Progress(instr.Position, instr.Length); } i = instr.Read(buffer, 0, buffer.Length); if (i < 0) { i = 0; } // must be a multiple of ctx.blockSize if ((i > 0) && (i != buffer.Length)) { return; //throw new Exception(); } if ((i > 0) && (!ivInited)) { ivInited = true; if (ctx.Mode == Mode.CBC) { Array.Copy(ctx.IV, 0, iv, 0, ctx.IV.Length); } } if (i <= 0) //lastblock { // buffer has no data if (!lastInited) { return; // throw new Exception(); } Array.Copy(last, output, output.Length); // remove padd data int k = (int)output[output.Length - 1]; if (k > output.Length) { return; } outstr.Write(output, 0, output.Length - k); break; } ctx.Ibc.InvCipher(buffer, output); if (ctx.Mode == Mode.CBC) { PrepareBuffer(ctx.Mode, output, iv); Array.Copy(buffer, iv, buffer.Length); } //delay output if (!lastInited) { Array.Copy(output, last, output.Length); lastInited = true; } else { outstr.Write(last, 0, last.Length); Array.Copy(output, last, output.Length); } } while(true); outstr.Flush(); if (monitor != null) { if (!monitor.ShouldStop()) { monitor.Progress(instr.Length, instr.Length); } } }