Exemplo n.º 1
0
        public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
        {
            Validate.AnArray(inputBuffer, inputOffset, inputCount);

            // Extract the MAC and ciphered from the input
            byte[] macMessageAONT = new byte[moMAC.HashSize / 8];
            byte[] messageAONT    = new byte[inputCount - macMessageAONT.Length];
            Buffer.BlockCopy(inputBuffer, inputOffset, macMessageAONT, 0, macMessageAONT.Length);
            Buffer.BlockCopy(inputBuffer, inputOffset + macMessageAONT.Length, messageAONT, 0, messageAONT.Length);

            // Decrypt the head of the AONT message
            byte[] plaintextHeadOfMessageAONT = moCipher.CreateDecryptor().TransformFinalBlock(messageAONT, 0, mKey.Length);

            // Replace the encrypted head with the plaintext head
            Buffer.BlockCopy(plaintextHeadOfMessageAONT, 0, messageAONT, 0, plaintextHeadOfMessageAONT.Length);

            // Verify the MAC of the AONT message
            byte[] calcMacMessageAONT = moMAC.ComputeHash(messageAONT);
            if (!calcMacMessageAONT.SequenceEqual(macMessageAONT))
            {
                // Throw not authenticated exception
                throw new Exception("Authentication check failed");
            }

            // Inverse the AONT of the AONT message
            byte[] plaintext = moAONT.Decode(messageAONT, 0, messageAONT.Length);

            return(plaintext);
        }
Exemplo n.º 2
0
        public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
        {
            #region Validation
            Validate.AnArray(inputBuffer, inputOffset, inputCount);
            #endregion

            // Check the ciphertext is large enough, Encrypt-then-MAC sig + MAC bits + at least 2 * miTotalPairsCount bytes
            if (moMAC.HashSize / 8 + 2 * (miTotalPairsCount / 8) + (2 * miTotalPairsCount) > inputCount)
            {
                // TODO
                throw new Exception("Ciphertext too short");
            }

            // Extract the Encrypt-then-MAC signature
            byte[] EtM = new byte[moMAC.HashSize / 8];
            Buffer.BlockCopy(inputBuffer, inputOffset, EtM, 0, EtM.Length);
            // Calculate the Encrypt-then-MAC signature
            byte[] calcEtM = moMAC.ComputeHash(inputBuffer, inputOffset + EtM.Length, inputCount - EtM.Length);
            // Compare
            if (!calcEtM.SequenceEqual(EtM))
            {
                // Throw not authenticated exception
                throw new Exception("Authentication check failed");
            }

            // Extract the HMAC seed
            byte[] seedMAC = new byte[miTotalPairsCount / 8];
            Buffer.BlockCopy(inputBuffer, inputOffset + EtM.Length, seedMAC, 0, seedMAC.Length);

            // Extract the MAC bits
            byte[] bitsMAC = new byte[miTotalPairsCount / 8];
            Buffer.BlockCopy(inputBuffer, inputOffset + EtM.Length + seedMAC.Length, bitsMAC, 0, bitsMAC.Length);

            // Allocate space for the encodedMessage
            byte[] encodedMessage = new byte[inputCount - EtM.Length - seedMAC.Length - bitsMAC.Length];

            // If the encodedMessage is odd in length copy the last byte from the ciphertext to the encodedMessage
            int encodedMessageLength = encodedMessage.Length;
            if (encodedMessage.Length % 2 != 0)
            {
                encodedMessage[encodedMessage.Length - 1] = inputBuffer[inputOffset + (inputCount - 1)];
                encodedMessageLength = encodedMessage.Length - 1;
            }

            // Determine the size of each message part (except for perhaps the last
            int partSize = getMaxPartSize(encodedMessageLength, 2 * miTotalPairsCount);

            // Allocate space for a buffer to calculate the HMAC on
            byte[] bufferHMAC = new byte[seedMAC.Length + 1 + 2 * partSize];    // We will HMAC the HMAC seed, the index and the 2 parts

            // Copy the HMAC seed to the HMAC buffer
            Buffer.BlockCopy(seedMAC, 0, bufferHMAC, 0, seedMAC.Length);

            int offset           = 0;                                                          //  Offset into the where we are writing the unswapped encoded message
            int encodedMsgOffset = inputOffset + EtM.Length + seedMAC.Length + bitsMAC.Length; // Offset into inputBuffer to read the swapped encoded message

            for (int i = 0; i < miTotalPairsCount; i++)
            {
                bufferHMAC[seedMAC.Length] = (byte)i;
                // Calculate the MAC of the 2 parts, unswapped and swapped
                // 1st unswapped
                Buffer.BlockCopy(inputBuffer, encodedMsgOffset, bufferHMAC, seedMAC.Length + 1, 2 * partSize);
                byte[] oMACUnswapped = moMAC.ComputeHash(bufferHMAC);
                // then swapped
                Buffer.BlockCopy(inputBuffer, encodedMsgOffset, bufferHMAC, seedMAC.Length + 1 + partSize, partSize);
                Buffer.BlockCopy(inputBuffer, encodedMsgOffset + partSize, bufferHMAC, seedMAC.Length + 1, partSize);
                byte[] oMACSwapped = moMAC.ComputeHash(bufferHMAC);

                // Find the location of the first bit difference
                bool   bFound      = false;
                byte[] correctPair = new byte[2 * partSize];
                for (byte j = 0; j < oMACUnswapped.Length; j++)
                {
                    if (oMACSwapped[j] != oMACUnswapped[j])
                    {
                        for (byte k = 0; k < 8; k++)
                        {
                            Boolean bUnSwappedBitSet = ((oMACUnswapped[j] & ((byte)1 << k)) > 0);
                            Boolean bSwappedBitSet   = ((oMACSwapped[j] & ((byte)1 << k)) > 0);
                            if (bUnSwappedBitSet != bSwappedBitSet)
                            {
                                // Get the value of the bit
                                byte bitValue = (byte)((bitsMAC[i / 8] >> (7 - (i % 8))) & 1);
                                if ((bitValue == 1) == bUnSwappedBitSet)
                                {
                                    Buffer.BlockCopy(inputBuffer, encodedMsgOffset, correctPair, 0, 2 * partSize);
                                }
                                else if ((bitValue == 1) == bSwappedBitSet)
                                {
                                    Buffer.BlockCopy(inputBuffer, encodedMsgOffset + partSize, correctPair, 0, partSize);
                                    Buffer.BlockCopy(inputBuffer, encodedMsgOffset, correctPair, partSize, partSize);
                                }
                                bFound = true;
                                break;
                            }
                        }
                    }
                    if (bFound)
                    {
                        break;
                    }
                }
                if (!bFound)
                {
                    // Likely the parts are identical, so swapping then and calculating the hash yields the same hash.
                    // Just set the unswapped version
                    Buffer.BlockCopy(inputBuffer, encodedMsgOffset, correctPair, 0, 2 * partSize);
                }

                // Copy to correctly ordered pair to the encoded message
                Buffer.BlockCopy(correctPair, 0, encodedMessage, offset, 2 * partSize);
                offset += (2 * partSize);

                encodedMsgOffset += (2 * partSize);

                partSize = getNextPartSize(encodedMessageLength, offset, (i + 1) * 2, 256);

                // If the partSize changes we need to alter the size of bufferHMAC
                if (bufferHMAC.Length != (seedMAC.Length + 1 + 2 * partSize))
                {
                    bufferHMAC = new byte[seedMAC.Length + 1 + 2 * partSize];
                }
            }

            // Reverse All Or Nothing Transform the message
            byte[] paddedMessage = moAONT.Decode(encodedMessage);
            //string hex = BitConverter.ToString(encodedMessage);
            //Console.WriteLine("Deco Message: " + hex.Replace("-", "") + " (length = " + encodedMessage.Length + ")");

            // Remove padding
            int paddingBytes = paddedMessage[paddedMessage.Length - 1];
            // Check all the padding bytes are correct
            for (int i = 0; i < paddingBytes; i++)
            {
                if (paddedMessage[paddedMessage.Length - 1 - i] != paddingBytes)
                {
                    throw new Exception("Padding error found");
                }
            }
            byte[] message = new byte[paddedMessage.Length - paddingBytes];
            Buffer.BlockCopy(paddedMessage, 0, message, 0, message.Length);

            return(message);
        }