TripleDesCipher
Implements 3DES cipher algorithm.
            
                using Org.BouncyCastle.Crypto.Paddings;
using Renci.SshNet.Common;
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
using System;
using System.Security.Cryptography;
namespace Renci.SshNet.Security.Cryptography.Ciphers
{
    public sealed class TripleDesCipher : BlockCipher, IDisposable
    {
        private sealed class BclImpl : BlockCipher, IDisposable
        {
            private readonly TripleDES _des;
            private readonly ICryptoTransform _encryptor;
            private readonly ICryptoTransform _decryptor;
            public BclImpl(byte[] key, byte[] iv, System.Security.Cryptography.CipherMode mode, PaddingMode padding)
                : base(key, 8, null, null)
            {
                TripleDES tripleDES = TripleDES.Create();
                tripleDES.FeedbackSize = 64;
                tripleDES.Key = base.Key;
                tripleDES.IV = iv.Take(8);
                tripleDES.Mode = mode;
                tripleDES.Padding = padding;
                _des = tripleDES;
                _encryptor = _des.CreateEncryptor();
                _decryptor = _des.CreateDecryptor();
            }
            public override byte[] Encrypt(byte[] input, int offset, int length)
            {
                if (_des.Padding != PaddingMode.None)
                    return _encryptor.TransformFinalBlock(input, offset, length);
                int num = 0;
                if (length % (int)base.BlockSize > 0) {
                    System.Security.Cryptography.CipherMode mode = _des.Mode;
                    if (((uint)(mode - 3) <= 1) ? true : false) {
                        num = base.BlockSize - length % (int)base.BlockSize;
                        input = input.Take(offset, length);
                        length += num;
                        Array.Resize(ref input, length);
                        offset = 0;
                    }
                }
                byte[] array = new byte[length];
                _encryptor.TransformBlock(input, offset, length, array, 0);
                if (num > 0)
                    Array.Resize(ref array, array.Length - num);
                return array;
            }
            public override byte[] Decrypt(byte[] input, int offset, int length)
            {
                if (_des.Padding != PaddingMode.None)
                    return _decryptor.TransformFinalBlock(input, offset, length);
                int num = 0;
                if (length % (int)base.BlockSize > 0) {
                    System.Security.Cryptography.CipherMode mode = _des.Mode;
                    if (((uint)(mode - 3) <= 1) ? true : false) {
                        num = base.BlockSize - length % (int)base.BlockSize;
                        input = input.Take(offset, length);
                        length += num;
                        Array.Resize(ref input, length);
                        offset = 0;
                    }
                }
                byte[] array = new byte[length];
                _decryptor.TransformBlock(input, offset, length, array, 0);
                if (num > 0)
                    Array.Resize(ref array, array.Length - num);
                return array;
            }
            public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
            {
                throw new NotImplementedException("Invalid usage of EncryptBlock.");
            }
            public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
            {
                throw new NotImplementedException("Invalid usage of DecryptBlock.");
            }
            public void Dispose()
            {
                _des.Dispose();
                _encryptor.Dispose();
                _decryptor.Dispose();
            }
        }
        private sealed class BlockImpl : BlockCipher, IDisposable
        {
            private readonly TripleDES _tripleDES;
            private readonly ICryptoTransform _encryptor;
            private readonly ICryptoTransform _decryptor;
            public BlockImpl(byte[] key, CipherMode mode, IBlockCipherPadding padding)
                : base(key, 8, mode, padding)
            {
                TripleDES tripleDES = TripleDES.Create();
                tripleDES.Key = key;
                tripleDES.Mode = System.Security.Cryptography.CipherMode.ECB;
                tripleDES.Padding = PaddingMode.None;
                _tripleDES = tripleDES;
                _encryptor = tripleDES.CreateEncryptor();
                _decryptor = tripleDES.CreateDecryptor();
            }
            public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
            {
                return _encryptor.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
            }
            public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
            {
                return _decryptor.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
            }
            public void Dispose()
            {
                _tripleDES.Dispose();
                _encryptor.Dispose();
                _decryptor.Dispose();
            }
        }
        private readonly BlockCipher _impl;
        public TripleDesCipher(byte[] key, byte[] iv, System.Security.Cryptography.CipherMode mode, bool pkcs7Padding)
            : base(key, 8, null, null)
        {
            if (mode == System.Security.Cryptography.CipherMode.CFB)
                _impl = new BlockImpl(key, new CfbCipherMode(iv), pkcs7Padding ? new Pkcs7Padding() : null);
            else
                _impl = new BclImpl(key, iv, mode, (!pkcs7Padding) ? PaddingMode.None : PaddingMode.PKCS7);
        }
        public override byte[] Encrypt(byte[] input, int offset, int length)
        {
            return _impl.Encrypt(input, offset, length);
        }
        public override byte[] Decrypt(byte[] input, int offset, int length)
        {
            return _impl.Decrypt(input, offset, length);
        }
        public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
        {
            return _impl.EncryptBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
        }
        public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
        {
            return _impl.DecryptBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
        }
        public void Dispose()
        {
            (_impl as IDisposable)?.Dispose();
        }
    }
}