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

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