source: trunk/CrypPlugins/MD5Collider/Algorithm/MultiThreadedMD5Collider.cs @ 1430

Last change on this file since 1430 was 1430, checked in by pretzsch, 11 years ago

MD5Collider: Added comments

File size: 7.9 KB
RevLine 
[1355]1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.ComponentModel;
6using System.Timers;
7
8namespace Cryptool.Plugins.MD5Collider.Algorithm
9{
[1430]10    /// <summary>
11    /// Wraps an existing <c>IMD5ColliderAlgorithm</c> implementation to execute it in parallel using multiple threads
12    /// </summary>
13    /// <typeparam name="T">Type of collider to run in parallel</typeparam>
[1355]14    class MultiThreadedMD5Collider<T> : IMD5ColliderAlgorithm where T : IMD5ColliderAlgorithm, new()
15    {
[1430]16        /// <summary>
17        /// A list of <c>ColliderWorkerAdapter</c> which manage the threads for the collider instances
18        /// </summary>
19        /// <seealso cref="ColliderWorkerAdapter"/>
[1355]20        private List<ColliderWorkerAdapter<T>> workers = new List<ColliderWorkerAdapter<T>>();
[1430]21
22        /// <summary>
23        /// The managed container instances
24        /// </summary>
[1355]25        private List<IMD5ColliderAlgorithm> colliders = new List<IMD5ColliderAlgorithm>();
[1430]26
27        /// <summary>
28        /// The collider which finished first
29        /// </summary>
[1355]30        private IMD5ColliderAlgorithm successfulCollider;
[1430]31
32        /// <summary>
33        /// Timer periodically emitting <c>PropertyChanged</c> events for progress notification properties
34        /// </summary>
[1355]35        private Timer progressUpdateTimer;
[1430]36
37        /// <summary>
38        /// Amount of worker threads managed
39        /// </summary>
[1355]40        private int workerCount;
41
[1430]42        /// <summary>
43        /// Event triggered when the first collision has finished
44        /// </summary>
[1355]45        private System.Threading.AutoResetEvent finishedEvent = new System.Threading.AutoResetEvent(false);
46
[1430]47        /// <summary>
48        /// Constructs as many managed colliders and worker threads as CPU cores are available and sets up the timer
49        /// </summary>
[1355]50        public MultiThreadedMD5Collider()
51        {
52            workerCount = Math.Max(Environment.ProcessorCount, 1);
53
54            for (int i = 0; i < workerCount; i++)
55            {
56                IMD5ColliderAlgorithm collider = new T();
57                colliders.Add(collider);
58
59                ColliderWorkerAdapter<T> colliderWorkerAdapter = new ColliderWorkerAdapter<T>(this, collider);
60                workers.Add(colliderWorkerAdapter);
61            }
62
63            progressUpdateTimer = new Timer();
[1356]64            progressUpdateTimer.Interval = 250;
[1355]65            progressUpdateTimer.Elapsed += progressUpdateTimer_Tick;
66        }
67
[1430]68        /// <summary>
69        /// First resulting block as retrieved from finished collider
70        /// </summary>
[1355]71        public byte[] FirstCollidingData { get { return successfulCollider != null ? successfulCollider.FirstCollidingData : null; } }
[1430]72
73        /// <summary>
74        /// Second resulting block as retrieved from finished collider
75        /// </summary>
[1355]76        public byte[] SecondCollidingData { get { return successfulCollider != null ? successfulCollider.SecondCollidingData : null; } }
77
[1430]78        /// <summary>
79        /// Second resulting block as retrieved from finished collider
80        /// </summary>
[1355]81        public byte[] RandomSeed
82        {
83            set
84            {
85                if (value == null)
86                {
87                    foreach (IMD5ColliderAlgorithm collider in colliders)
88                        collider.RandomSeed = null;
89                    return;
90                }
91
92
93                byte[] randomSeedCopy = (byte[])value.Clone();
94
95                foreach (IMD5ColliderAlgorithm collider in colliders)
96                {
97                    collider.RandomSeed = randomSeedCopy;
98
99                    randomSeedCopy = (byte[])randomSeedCopy.Clone();
100
101                    if (randomSeedCopy.Length == 0)
102                        randomSeedCopy = new byte[1];
103
104                    randomSeedCopy[0]++;
105                }
106            }
107        }
108
[1430]109        /// <summary>
110        /// Mutex locked when a computation has finished
111        /// </summary>
[1356]112        private Object finishedLock = new Object();
113
[1430]114        /// <summary>
115        /// Called by a <c>ColliderWorkerAdapter</c> when wrapped collider has finished
116        /// </summary>
117        /// <param name="successfulCollider"></param>
[1355]118        internal void SignalWorkIsFinished(IMD5ColliderAlgorithm successfulCollider)
119        {
[1356]120            lock (finishedLock)
121            {
122                if (this.successfulCollider == null)
123                {
124                    this.successfulCollider = successfulCollider;
125                    updateProgress();
126                    Stop();
[1355]127
[1356]128                    finishedEvent.Set();
129                }
130            }
[1355]131        }
[1430]132       
133        /// <summary>
134        /// IHV (intermediate hash value) for the start of the collision, must be initialized if prefix is desired
135        /// </summary>
[1355]136        public byte[] IHV
137        {
138            set
139            {
140                foreach (IMD5ColliderAlgorithm collider in colliders)
141                    collider.IHV = value;
142            }
143        }
144
[1430]145        /// <summary>
146        /// Maximum possible value for match progress
147        /// </summary>
[1355]148        public int MatchProgressMax
149        {
150            get { return colliders.Max(c => c.MatchProgressMax); }
151        }
152
[1430]153        /// <summary>
154        /// Indicates how far conditions for a valid collision block were satisfied in last attempt
155        /// </summary>
[1355]156        public int MatchProgress
157        {
158            get { return colliders.Max(c => c.MatchProgress); }
159            set { }
160        }
161
[1430]162        /// <summary>
163        /// Number of conditions which have failed
164        /// </summary>
[1355]165        public long CombinationsTried
166        {
167            get { return colliders.Sum(c => c.CombinationsTried); }
168        }
169
[1430]170        /// <summary>
171        /// Time elapsed since start of collision search
172        /// </summary>
[1355]173        public TimeSpan ElapsedTime
174        {
175            get { return colliders.Max(c => c.ElapsedTime); }
176        }
177
[1430]178        /// <summary>
179        /// Starts the collision search
180        /// </summary>
[1355]181        public void FindCollision()
182        {
183            progressUpdateTimer.Start();
184
185            finishedEvent.Reset();
[1356]186            successfulCollider = null;
[1355]187
188            foreach (ColliderWorkerAdapter<T> worker in workers)
189                worker.StartWork();
190
191            finishedEvent.WaitOne();
192
193            OnPropertyChanged("FirstCollidingData");
194            OnPropertyChanged("SecondCollidingData");
195        }
196
[1430]197        /// <summary>
198        /// Stops the collision search
199        /// </summary>
[1355]200        public void Stop()
201        {
202            foreach (IMD5ColliderAlgorithm collider in colliders)
203                collider.Stop();
204
205            progressUpdateTimer.Stop();
206        }
207
[1430]208        /// <summary>
209        /// The <c>PropertyChanged</c> event as prescribed by the <c>INotifyPropertyChanged</c> interface
210        /// </summary>
[1355]211        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
[1430]212
213        /// <summary>
214        /// Helper function triggering <c>PropertyChanged</c> event for given property name
215        /// </summary>
216        /// <param name="propertyName">Property for which change event should be triggerd</param>
[1355]217        private void OnPropertyChanged(string propertyName)
218        {
219            if (PropertyChanged != null)
220                PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
221        }
222
223
224        void progressUpdateTimer_Tick(object sender, EventArgs e)
225        {
226            updateProgress();
227        }
228
229        private void updateProgress()
230        {
231            OnPropertyChanged("MatchProgressMax");
232            OnPropertyChanged("MatchProgress");
233            OnPropertyChanged("CombinationsTried");
234            OnPropertyChanged("ElapsedTime");
235        }
236    }
237}
Note: See TracBrowser for help on using the repository browser.