Exemple #1
0
        /// <summary>
        /// This method decrypts the specified data using the algorithm. This method should be used in checking the
        /// inputted password from the client, encrypted and passed in the authentication request packet.
        /// </summary>
        /// <param name="input">The inputted buffer to be decrypted.</param>
        public unsafe void Decrypt(byte[] input)
        {
            for (int index = 0; index < input.Length; index++)
            {
                // Is the algorithm done decrypting data?
                if (input[index] == 0)
                {
                    fixed(byte *ptr = input)
                    NativeFunctionCalls.memset(ptr + index, 0, input.Length - index);

                    return;
                }

                // Decrypt the byte at the current offset:
                byte position = _keyBuffer[input[index] * 2];
                if (position > 0x80)
                {
                    // Entered using the "SHIFT" key:
                    position     = (byte)(_keyBuffer[input[index] * 2] - 0x80);
                    input[index] = _decryptionSubstitutionBox[position];
                }
                else
                {
                    input[index] = _decryptionSubstitutionBox[position];
                    if (input[index] >= 0x41 && input[index] <= 90)
                    {
                        input[index] = (byte)(input[index] + 0x20);
                    }
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// This method generates keys for the algorithm. It should be used before the encryption and decryption
        /// methods are used to initialize the key vector. This method is automatically called by the constructor.
        /// </summary>
        /// <param name="initializationVector">The initialization vector used to generate keys.</param>
        public void GenerateKeys(byte[] initializationVector)
        {
            // Initialize Cipher Buffers:
            _keyBuffer          = new uint[KEY_SIZE];
            _substitutionBuffer = new uint[SUBSTITUTION_SIZE];

            fixed(uint *keyBufferPtr = _keyBuffer)
            NativeFunctionCalls.memcpy((byte *)keyBufferPtr, initializationVector, KEY_SIZE * sizeof(uint));

            // Generate the substitution box:
            _substitutionBuffer[0] = 0xB7E15163;
            for (int index = 1; index < SUBSTITUTION_SIZE; index++)
            {
                _substitutionBuffer[index] = _substitutionBuffer[index - 1] + 0x9E3779B9;
            }

            // Generate Key & Final Substitution Box:
            uint substitutionIndex = 0, keyIndex = 0, x = 0, y = 0;

            for (int loopControlIndex = 0; loopControlIndex < 3 * SUBSTITUTION_SIZE; loopControlIndex++)
            {
                _substitutionBuffer[substitutionIndex] = RotateLeft(_substitutionBuffer[substitutionIndex] + x + y, 3);
                x = _substitutionBuffer[substitutionIndex];
                substitutionIndex    = (substitutionIndex + 1) % SUBSTITUTION_SIZE;
                _keyBuffer[keyIndex] = RotateLeft(_keyBuffer[keyIndex] + x + y, (int)(x + y));
                y        = _keyBuffer[keyIndex];
                keyIndex = (keyIndex + 1) % KEY_SIZE;
            }
        }
Exemple #3
0
        /// <summary>
        /// This function sends a packet to the client using the client's remote socket defined above. The
        /// packet is encrypted using the client's selected cipher algorithm and sent through the client's remote
        /// socket. If the server has a footer, it will write that footer to the end of the packet.
        /// </summary>
        /// <param name="packet">The packet being encrypted and sent to the client.</param>
        public void Send(byte[] packet)
        {
            try
            {
                lock (SendLock) // Locked to prevent two packets from being encrypted and sent at the same time.
                {
                    // Add the footer to the end of the packet:
                    if (Server.FooterLength > 0)
                        fixed(byte *packetPtr = packet)
                        NativeFunctionCalls.memcpy(packetPtr + packet.Length - 8,
                                                   Server.Footer, Server.FooterLength);

                    // Encrypt the packet and attempt to send it to the client:
                    byte[] encryptedPacket = Cipher != null?Cipher.Encrypt(packet, packet.Length) : packet;

                    Socket.Send(encryptedPacket);
                }
            }
            catch (SocketException e)
            {
                // Was the connection issue a problem on our side or the client's side?
                if (e.SocketErrorCode != SocketError.Disconnecting &&
                    e.SocketErrorCode != SocketError.NotConnected &&
                    e.SocketErrorCode != SocketError.ConnectionReset &&
                    e.SocketErrorCode != SocketError.ConnectionAborted &&
                    e.SocketErrorCode != SocketError.Shutdown)
                {
                    Console.WriteLine(e);
                }
            }
        }
        /// <summary>
        /// This method accepts the initialization key vector from the server's key exchange with the client and generates
        /// an encryption initialization vector, used in generating the key vector and in encrypting data from the server.
        /// </summary>
        /// <param name="iv">The encryption initialization vector from key exchange.</param>
        public void SetEncryptionIV(byte[] iv)
        {
            // Error check before creating the initialization vector:
            if (iv == null || iv.Length != BF_BLOCK_SIZE)
            {
                return;
            }

            // Copy the key exchange's generated iv to the encryption iv and byte swap:
            NativeFunctionCalls.memcpy(_encryptionIV, iv, BF_BLOCK_SIZE);
            _encryptionIncrementor = 0;
        }
 /// <summary>
 /// Blowfish is a keyed, symmetric block cipher, designed in 1993 by Bruce Schneier and included in a large
 /// number of cipher suites and encryption products. Blowfish provides a good encryption rate in software and no
 /// effective cryptanalysis of it has been found to date. However, the Advanced Encryption Standard now receives
 /// more attention. Schneier designed Blowfish as a general-purpose algorithm, intended as an alternative to the
 /// aging DES and free of the problems and constraints associated with other algorithms. Schneier has stated that,
 /// "Blowfish is unpatented, and will remain so in all countries. The algorithm is hereby placed in the public
 /// domain, and can be freely used by anyone." The implementation type in use is CFB64.
 /// </summary>
 public BlowfishCipher()
 {
     _encryptionLock        = new object();
     _decryptionLock        = new object();
     _encryptionIncrementor = 0;
     _decryptionIncrementor = 0;
     _encryptionIV          = (byte *)NativeFunctionCalls.malloc(BF_BLOCK_SIZE);
     _decryptionIV          = (byte *)NativeFunctionCalls.malloc(BF_BLOCK_SIZE);
     NativeFunctionCalls.memset(_encryptionIV, 0, BF_BLOCK_SIZE);
     NativeFunctionCalls.memset(_decryptionIV, 0, BF_BLOCK_SIZE);
     KeySchedule(InitialKey);
 }