Beispiel #1
0
        public int InverseTransform(Buffer buffer, int length)
        {
            Log.Trace("BlockCipher.InverseTransform: input length {0}", length);

            using (var decryptor = decryptionAlgorithm.CreateDecryptor(decryptionKey, decryptionIV))
            using (var ms = new MemoryStream(length))
            using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
            {
            #if UNITY_WORKAROUND
                // Workaround for ancient mono 2.0 of Unity3D
                // Multiple Write() calls are not properly handled there.

                byte[] ciphertext = buffer.ToArray();
                if (Log.Level <= LogLevel.Trace)
                {
                    Log.Trace("BlockCipher.InverseTransform: input {0}",
                        BitConverter.ToString(ciphertext, 0, length));
                }
                System.Buffer.BlockCopy(ciphertext, length - BlockSizeInBytes,
                    decryptionIV, 0, BlockSizeInBytes);
                cs.Write(ciphertext, 0, length);

            #else
                var buffers = new List<ArraySegment<byte>>();
                buffer.ListStartingSegments(buffers, length);

                // Store the last ciphertext block as a next decryption IV.
                byte[] nextIV = new byte[BlockSizeInBytes];
                int bytesCopied = 0;
                for (var i = buffers.Count - 1; bytesCopied < BlockSizeInBytes && i >= 0; --i)
                {
                    var segment = buffers[i];
                    int bytesToCopy = Math.Min(segment.Count, BlockSizeInBytes);
                    System.Buffer.BlockCopy(segment.Array, segment.Offset + segment.Count - bytesToCopy,
                        decryptionIV, BlockSizeInBytes - bytesCopied - bytesToCopy, bytesToCopy);
                    bytesCopied += bytesToCopy;
                }

                for (var i = 0; i < buffers.Count; ++i)
                {
                    var segment = buffers[i];

                    if (Log.Level <= LogLevel.Trace)
                    {
                        Log.Trace("BlockCipher.InverseTransform: input block {0}",
                            BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
                    }

                    cs.Write(segment.Array, segment.Offset, segment.Count);
                }
            #endif

                cs.FlushFinalBlock();

                int result = (int)ms.Length;
                var streamBuffer = ms.GetBuffer();

                if (Log.Level <= LogLevel.Trace)
                {
                    Log.Trace("BlockCipher.InverseTransform: output {0} {1}",
                        result, BitConverter.ToString(streamBuffer, 0, result));
                }

                buffer.Rewind();
                buffer.CopyFrom(streamBuffer, 0, result);

                return result;
            }
        }