using System;
namespace Renci.SshNet.Security.Cryptography
{
    /// 
    /// Base class for cipher implementation.
    /// 
    public abstract class Cipher
    {
        /// 
        /// Gets the minimum data size.
        /// 
        /// 
        /// The minimum data size.
        /// 
        public abstract byte MinimumSize { get; }
        /// 
        /// Encrypts the specified input.
        /// 
        /// The input.
        /// Encrypted data.
        public abstract byte[] Encrypt(byte[] input);
        /// 
        /// Decrypts the specified input.
        /// 
        /// The input.
        /// Decrypted data.
        public abstract byte[] Decrypt(byte[] input);
        #region Packing functions
        /// 
        /// Populates buffer with big endian number representation.
        /// 
        /// The number to convert.
        /// The buffer.
        protected static void UInt32ToBigEndian(uint number, byte[] buffer)
        {
            buffer[0] = (byte)(number >> 24);
            buffer[1] = (byte)(number >> 16);
            buffer[2] = (byte)(number >> 8);
            buffer[3] = (byte)(number);
        }
        /// 
        /// Populates buffer with big endian number representation.
        /// 
        /// The number to convert.
        /// The buffer.
        /// The buffer offset.
        protected static void UInt32ToBigEndian(uint number, byte[] buffer, int offset)
        {
            buffer[offset] = (byte)(number >> 24);
            buffer[offset + 1] = (byte)(number >> 16);
            buffer[offset + 2] = (byte)(number >> 8);
            buffer[offset + 3] = (byte)(number);
        }
        /// 
        /// Converts big endian bytes into number.
        /// 
        /// The buffer.
        /// Converted .
        protected static uint BigEndianToUInt32(byte[] buffer)
        {
            uint n = (uint)buffer[0] << 24;
            n |= (uint)buffer[1] << 16;
            n |= (uint)buffer[2] << 8;
            n |= (uint)buffer[3];
            return n;
        }
        /// 
        /// Converts big endian bytes into number.
        /// 
        /// The buffer.
        /// The buffer offset.
        /// Converted .
        protected static uint BigEndianToUInt32(byte[] buffer, int offset)
        {
            uint n = (uint)buffer[offset] << 24;
            n |= (uint)buffer[offset + 1] << 16;
            n |= (uint)buffer[offset + 2] << 8;
            n |= (uint)buffer[offset + 3];
            return n;
        }
        /// 
        /// Converts big endian bytes into number.
        /// 
        /// The buffer.
        /// Converted .
        protected static ulong BigEndianToUInt64(byte[] buffer)
        {
            uint hi = BigEndianToUInt32(buffer);
            uint lo = BigEndianToUInt32(buffer, 4);
            return ((ulong)hi << 32) | (ulong)lo;
        }
        /// 
        /// Converts big endian bytes into number.
        /// 
        /// The buffer.
        /// The buffer offset.
        /// Converted .
        protected static ulong BigEndianToUInt64(byte[] buffer, int offset)
        {
            uint hi = BigEndianToUInt32(buffer, offset);
            uint lo = BigEndianToUInt32(buffer, offset + 4);
            return ((ulong)hi << 32) | (ulong)lo;
        }
        /// 
        /// Populates buffer with big endian number representation.
        /// 
        /// The number to convert.
        /// The buffer.
        protected static void UInt64ToBigEndian(ulong number, byte[] buffer)
        {
            UInt32ToBigEndian((uint)(number >> 32), buffer);
            UInt32ToBigEndian((uint)(number), buffer, 4);
        }
        /// 
        /// Populates buffer with big endian number representation.
        /// 
        /// The number to convert.
        /// The buffer.
        /// The buffer offset.
        protected static void UInt64ToBigEndian(ulong number, byte[] buffer, int offset)
        {
            UInt32ToBigEndian((uint)(number >> 32), buffer, offset);
            UInt32ToBigEndian((uint)(number), buffer, offset + 4);
        }
        /// 
        /// Populates buffer with little endian number representation.
        /// 
        /// The number to convert.
        /// The buffer.
        protected static void UInt32ToLittleEndian(uint number, byte[] buffer)
        {
            buffer[0] = (byte)(number);
            buffer[1] = (byte)(number >> 8);
            buffer[2] = (byte)(number >> 16);
            buffer[3] = (byte)(number >> 24);
        }
        /// 
        /// Populates buffer with little endian number representation.
        /// 
        /// The number to convert.
        /// The buffer.
        /// The buffer offset.
        protected static void UInt32ToLittleEndian(uint number, byte[] buffer, int offset)
        {
            buffer[offset] = (byte)(number);
            buffer[offset + 1] = (byte)(number >> 8);
            buffer[offset + 2] = (byte)(number >> 16);
            buffer[offset + 3] = (byte)(number >> 24);
        }
        /// 
        /// Converts little endian bytes into number.
        /// 
        /// The buffer.
        /// Converted .
        protected static uint LittleEndianToUInt32(byte[] buffer)
        {
            uint n = (uint)buffer[0];
            n |= (uint)buffer[1] << 8;
            n |= (uint)buffer[2] << 16;
            n |= (uint)buffer[3] << 24;
            return n;
        }
        /// 
        /// Converts little endian bytes into number.
        /// 
        /// The buffer.
        /// The buffer offset.
        /// Converted .
        protected static uint LittleEndianToUInt32(byte[] buffer, int offset)
        {
            uint n = (uint)buffer[offset];
            n |= (uint)buffer[offset + 1] << 8;
            n |= (uint)buffer[offset + 2] << 16;
            n |= (uint)buffer[offset + 3] << 24;
            return n;
        }
        /// 
        /// Converts little endian bytes into number.
        /// 
        /// The buffer.
        /// Converted .
        protected static ulong LittleEndianToUInt64(byte[] buffer)
        {
            uint lo = LittleEndianToUInt32(buffer);
            uint hi = LittleEndianToUInt32(buffer, 4);
            return ((ulong)hi << 32) | (ulong)lo;
        }
        /// 
        /// Converts little endian bytes into number.
        /// 
        /// The buffer.
        /// The buffer offset.
        /// Converted .
        protected static ulong LittleEndianToUInt64(byte[] buffer, int offset)
        {
            uint lo = LittleEndianToUInt32(buffer, offset);
            uint hi = LittleEndianToUInt32(buffer, offset + 4);
            return ((ulong)hi << 32) | (ulong)lo;
        }
        /// 
        /// Populates buffer with little endian number representation.
        /// 
        /// The number to convert.
        /// The buffer.
        protected static void UInt64ToLittleEndian(ulong number, byte[] buffer)
        {
            UInt32ToLittleEndian((uint)(number), buffer);
            UInt32ToLittleEndian((uint)(number >> 32), buffer, 4);
        }
        /// 
        /// Populates buffer with little endian number representation.
        /// 
        /// The number to convert.
        /// The buffer.
        /// The buffer offset.
        protected static void UInt64ToLittleEndian(ulong number, byte[] buffer, int offset)
        {
            UInt32ToLittleEndian((uint)(number), buffer, offset);
            UInt32ToLittleEndian((uint)(number >> 32), buffer, offset + 4);
        }
        #endregion
    }
}