示例#1
0
        /// <summary>
        /// Goes one step forward by either restoring a previously calculated state from the history or calculating the next state
        /// </summary>
        public void NextStep()
        {
            if (!IsInitialized)
            {
                return;
            }

            if (IsInFinishedState)
            {
                return;
            }

            if (HistoryHasMoreStates)
            {
                CurrentStateNumber++;
                CurrentState = StateHistory[CurrentStateNumber];
                OnStatusChanged();
            }
            else
            {
                PresentableMD5State previousState = CurrentState;
                AddNewState();
                PerformStep(previousState, CurrentState);
                OnStatusChanged();
            }

            if (!IsInFinishedState && skippedStates.Contains(CurrentState.State))
            {
                NextStep();
            }
        }
示例#2
0
 /// <summary>
 /// Reads from the data source
 /// </summary>
 /// <param name="newState">Algorithm state to modify</param>
 private void ReadData(PresentableMD5State newState)
 {
     // Fetch up to 64 bytes of data
     newState.Data       = new byte[128];
     newState.DataLength = (uint)DataStream.Read(newState.Data, 0, 64); //fully
     newState.DataOffset = 0;
 }
示例#3
0
        /// <summary>
        /// Performs the steps necessary after the individual compression function steps have run
        /// </summary>
        /// <param name="newState">Algorithm state to modify</param>
        private void FinishCompression(PresentableMD5State newState)
        {
            // Add compression function results to accumulators
            newState.H1 += newState.A;
            newState.H2 += newState.B;
            newState.H3 += newState.C;
            newState.H4 += newState.D;

            // Increment the number of bytes hashed so far
            newState.BytesHashed += DATA_BLOCK_SIZE;
        }
示例#4
0
        /// <summary>
        /// Clears the state history and adds the "uninitialized" state
        /// </summary>
        private void SetUninitializedState()
        {
            StateHistory.Clear();

            PresentableMD5State uninitializedState = new PresentableMD5State();

            uninitializedState.State = MD5StateDescription.UNINITIALIZED;
            StateHistory.Add(uninitializedState);
            CurrentState = uninitializedState;

            CurrentStateNumber = 0;
        }
示例#5
0
        /// <summary>
        /// Executes the round function and modifies algorithm state to reflect results
        /// </summary>
        /// <param name="state">Algorithm state to modify</param>
        /// <param name="function">The inner round function to execute</param>
        /// <param name="W">The part of the data to use in the round function</param>
        /// <param name="i">Index of this step (range 0 - 63)</param>
        protected static void ExecRoundFunction(PresentableMD5State state, RoundFunction function, uint W, uint i)
        {
            // Apply central compression function
            state.A = state.B + RotateLeft((state.A + function(state.A, state.B, state.C, state.D) + W + AdditionConstantTable[i]), ShiftConstantTable[i]);

            // Right-rotate the 4 compression result accumulators
            uint oldD = state.D;

            state.D = state.C;
            state.C = state.B;
            state.B = state.A;
            state.A = oldD;
        }
示例#6
0
        /// <summary>
        /// Performs one step of the compression function
        /// </summary>
        /// <param name="newState">Algorithm state to modify</param>
        private void PerformRoundStep(PresentableMD5State newState)
        {
            // Determine which round function to use
            RoundFunction roundFunction = ROUND_FUNCTION[newState.RoundIndex];

            // Determine which step in the compression function this is
            uint stepIndex = newState.RoundIndex * 16 + newState.RoundStepIndex;

            // Determine which part of the data to use in this step
            int wordIndex = GetWordIndex(newState.RoundIndex, stepIndex);

            // Execute the chosen round function
            ExecRoundFunction(newState, roundFunction, newState.DataAsIntegers[wordIndex], stepIndex);
        }
示例#7
0
        /// <summary>
        /// Adds a new state to the history and sets it as the current state
        /// </summary>
        protected void AddNewState()
        {
            if (CurrentStateNumber == -1)
            {
                CurrentState = new PresentableMD5State();
            }
            else
            {
                CurrentState = new PresentableMD5State(StateHistory[CurrentStateNumber]);
            }

            StateHistory.Add(CurrentState);
            CurrentStateNumber = StateHistory.Count - 1;
        }
示例#8
0
        /// <summary>
        /// Adds padding bytes to the data
        /// </summary>
        /// <param name="newState">Algorithm state to modify</param>
        private void AddPaddingBytes(PresentableMD5State newState)
        {
            // Save length of data in bit
            newState.LengthInBit = (newState.BytesHashed + newState.DataLength) * 8;

            // Add '1' bit to end of data
            newState.Data[newState.DataLength] = 0x80;
            newState.DataLength++;

            // Add zero bytes until 8 bytes short of next 64-byte block
            while (newState.DataLength % 64 != 56)
            {
                newState.Data[newState.DataLength++] = 0;
            }
        }
示例#9
0
        /// <summary>
        /// Copy constructor
        /// </summary>
        /// <param name="other">State to copy</param>
        public PresentableMD5State(PresentableMD5State other)
        {
            foreach (FieldInfo fi in GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
            {
                fi.SetValue(this, fi.GetValue(other));
            }


            foreach (PropertyInfo pi in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                if (pi.CanWrite && pi.CanRead)
                {
                    pi.SetValue(this, pi.GetValue(other, null), null);
                }
            }
        }
示例#10
0
        /// <summary>
        /// Adds the data length part of the padding
        /// </summary>
        /// <param name="newState">Algorithm state to modify</param>
        private void AddLength(PresentableMD5State newState)
        {
            // Determine offset behind last written byte
            uint lengthOffset = newState.DataLength + 8;

            // Write the length in bit as 8 byte little-endian integer
            for (int i = 8; i > 0; i--)
            {
                newState.Data[lengthOffset - i] = (byte)(newState.LengthInBit >> ((8 - i) * 8) & 0xff);
            }

            // Remember that padding is done now
            newState.IsPaddingDone = true;

            // Update data length
            newState.DataLength += 8;
        }
示例#11
0
        /// <summary>
        /// Performs initialization required before running compression function steps
        /// </summary>
        /// <param name="newState">Algorithm state to modify</param>
        private void StartCompression(PresentableMD5State newState)
        {
            // Read data into unsigned 32 bit integers
            newState.DataAsIntegers = new uint[16];
            for (uint j = 0; j < 64; j += 4)
            {
                newState.DataAsIntegers[j / 4] = (((uint)newState.Data[newState.DataOffset + (j + 3)]) << 24) |
                                                 (((uint)newState.Data[newState.DataOffset + (j + 2)]) << 16) |
                                                 (((uint)newState.Data[newState.DataOffset + (j + 1)]) << 8) |
                                                 (((uint)newState.Data[newState.DataOffset + (j)]));
            }

            // Reset round counter
            newState.RoundIndex = 0;

            // Initialize A, B, C, D with accumulated values
            newState.A = newState.H1;
            newState.B = newState.H2;
            newState.C = newState.H3;
            newState.D = newState.H4;
        }
示例#12
0
 /// <summary>
 /// Performs initialization before a round
 /// </summary>
 /// <param name="newState">Algorithm state to modify</param>
 private void StartRound(PresentableMD5State newState)
 {
     // Reset round step counter
     newState.RoundStepIndex = 0;
 }
示例#13
0
        /// <summary>
        /// Performs the next step in the algorithm
        /// </summary>
        /// <param name="previousState">Previous state</param>
        /// <param name="newState">The new state which is to be determined</param>
        public void PerformStep(PresentableMD5State previousState, PresentableMD5State newState)
        {
            switch (previousState.State)
            {
            case MD5StateDescription.INITIALIZED:
                // Start by reading data
                newState.State = MD5StateDescription.READING_DATA;
                break;

            case MD5StateDescription.READING_DATA:
                // Fetch next data block and enter "data read" state
                ReadData(newState);
                newState.State = MD5StateDescription.READ_DATA;
                break;

            case MD5StateDescription.READ_DATA:
                // If an underfull buffer was read, enter "starting padding" state
                // If a full buffer was read, enter "starting compression" state
                if (previousState.DataLength < DATA_BLOCK_SIZE)
                {
                    newState.State = MD5StateDescription.STARTING_PADDING;
                }
                else
                {
                    newState.State = MD5StateDescription.STARTING_COMPRESSION;
                }
                break;

            case MD5StateDescription.STARTING_PADDING:
                // First step of padding is adding the padding bytes
                newState.State = MD5StateDescription.ADDING_PADDING_BYTES;
                break;

            case MD5StateDescription.ADDING_PADDING_BYTES:
                // Add necessary number of bytes and enter "added padding bytes" state
                AddPaddingBytes(newState);
                newState.State = MD5StateDescription.ADDED_PADDING_BYTES;
                break;

            case MD5StateDescription.ADDED_PADDING_BYTES:
                // Next step for padding is adding the data length
                newState.State = MD5StateDescription.ADDING_LENGTH;
                break;

            case MD5StateDescription.ADDING_LENGTH:
                // Add the length of the data and enter "added length" state
                AddLength(newState);
                newState.State = MD5StateDescription.ADDED_LENGTH;
                break;

            case MD5StateDescription.ADDED_LENGTH:
                // Padding is done after adding data length, so enter "finished padding" state
                newState.State = MD5StateDescription.FINISHED_PADDING;
                break;

            case MD5StateDescription.FINISHED_PADDING:
                // If padding is finished, call compression function for the last (two) time(s)
                newState.State = MD5StateDescription.STARTING_COMPRESSION;
                break;

            case MD5StateDescription.STARTING_COMPRESSION:
                // Perform pre-compression initialization and continue by starting the first round
                StartCompression(newState);
                newState.State = MD5StateDescription.STARTING_ROUND;
                break;

            case MD5StateDescription.STARTING_ROUND:
                // Start the round and continue with the first round step
                StartRound(newState);
                newState.State = MD5StateDescription.STARTING_ROUND_STEP;
                break;

            case MD5StateDescription.STARTING_ROUND_STEP:
                // Perform the step and go into finished state
                PerformRoundStep(newState);
                newState.State = MD5StateDescription.FINISHED_ROUND_STEP;
                break;

            case MD5StateDescription.FINISHED_ROUND_STEP:
                // If last step, go into 'finished round' state, else continue with next step
                if (previousState.IsLastStepInRound)
                {
                    newState.State = MD5StateDescription.FINISHED_ROUND;
                }
                else
                {
                    newState.RoundStepIndex++;
                    newState.State = MD5StateDescription.STARTING_ROUND_STEP;
                }
                break;

            case MD5StateDescription.FINISHED_ROUND:
                // If last step, go into "finishing compression" state, else continue with next round
                if (previousState.IsLastRound)
                {
                    newState.State = MD5StateDescription.FINISHING_COMPRESSION;
                }
                else
                {
                    newState.RoundIndex++;
                    newState.State = MD5StateDescription.STARTING_ROUND;
                }
                break;

            case MD5StateDescription.FINISHING_COMPRESSION:
                // Perform finishing actions and go into "finished compression" state
                FinishCompression(newState);
                newState.State = MD5StateDescription.FINISHED_COMPRESSION;
                break;

            case MD5StateDescription.FINISHED_COMPRESSION:
                // If there's more data left in buffer, reenter compression function with offset
                if (previousState.DataLength - previousState.DataOffset > DATA_BLOCK_SIZE)
                {
                    // Still some data left in buffer, rerun compression with offset
                    newState.DataOffset += DATA_BLOCK_SIZE;
                    newState.State       = MD5StateDescription.STARTING_COMPRESSION;
                }
                else
                {
                    // No data left in buffer

                    if (previousState.IsPaddingDone)
                    {
                        // If padding was already added, we're done
                        DataStream.Close();
                        newState.State = MD5StateDescription.FINISHED;
                    }
                    else
                    {
                        // Read more data
                        newState.State = MD5StateDescription.READING_DATA;
                    }
                }
                break;
            }
        }