source: trunk/CrypPlugins/KeySearcher/KeySearcher.cs @ 1674

Last change on this file since 1674 was 1674, checked in by Paul Lelgemann, 11 years ago

o Refactored distributed KeySearcher: updated directory structure and variable names

File size: 40.6 KB
Line 
1using System;
2using System.Linq;
3using System.Text;
4using Cryptool.P2P;
5using Cryptool.PluginBase.Analysis;
6using Cryptool.PluginBase;
7using System.Windows.Controls;
8using System.ComponentModel;
9using Cryptool.PluginBase.Control;
10using System.Collections;
11using System.Collections.Generic;
12using System.Threading;
13using System.Windows.Threading;
14using Cryptool.PluginBase.IO;
15using System.Numerics;
16using KeySearcher.Helper;
17using KeySearcher.P2P;
18using KeySearcher.Presentation;
19
20namespace KeySearcher
21{   
22    [Author("Sven Rech, Nils Kopal, Raoul Falk, Dennis Nolte", "rech@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-due.de")]
23    [PluginInfo(false, "KeySearcher", "Bruteforces a decryption algorithm.", "KeySearcher/DetailedDescription/Description.xaml", "KeySearcher/Images/icon.png")]
24    public class KeySearcher : IAnalysisMisc
25    {
26        /// <summary>
27        /// used for creating the TopList
28        /// </summary>
29        private Queue valuequeue;
30        private double value_threshold;
31        /// <summary>
32        /// the thread with the most keys left
33        /// </summary>
34        private int maxThread;
35        private Mutex maxThreadMutex = new Mutex();
36
37        private KeyQualityHelper _keyQualityHelper;
38
39        private KeyPattern.KeyPattern pattern = null;
40        public KeyPattern.KeyPattern Pattern
41        {
42            get
43            {
44                return pattern;
45            }
46            set
47            {
48                pattern = value;
49                if ((settings.Key == null) || ((settings.Key != null) && !pattern.testWildcardKey(settings.Key)))
50                    settings.Key = pattern.giveInputPattern();
51            }
52        }
53
54        internal bool stop;
55
56        #region IControlEncryption + IControlCost + InputFields
57
58        #region IControlEncryption Members
59
60        private IControlEncryption controlMaster;
61        [PropertyInfo(Direction.ControlMaster, "Control Master", "Used for bruteforcing", "", DisplayLevel.Beginner)]
62        public IControlEncryption ControlMaster
63        {
64            get { return controlMaster; }
65            set
66            {
67                if (controlMaster != null)
68                {
69                    controlMaster.keyPatternChanged -= keyPatternChanged;
70                }
71                if (value != null)
72                {
73                    Pattern = new KeyPattern.KeyPattern(value.getKeyPattern());
74                    value.keyPatternChanged += keyPatternChanged;
75                    controlMaster = value;
76                    OnPropertyChanged("ControlMaster");
77
78                }
79                else
80                    controlMaster = null;
81            }
82        }
83
84        #endregion
85
86        #region IControlCost Members
87
88        private IControlCost costMaster;
89        [PropertyInfo(Direction.ControlMaster, "Cost Master", "Used for cost calculation", "", DisplayLevel.Beginner)]
90        public IControlCost CostMaster
91        {
92            get { return costMaster; }
93            set
94            {
95                costMaster = value;
96                _keyQualityHelper = new KeyQualityHelper(costMaster);
97            }
98        }
99
100        #endregion
101
102        /* BEGIN: following lines are from Arnie - 2010.01.12 */
103        CryptoolStream csEncryptedData;
104        [PropertyInfo(Direction.InputData, "CS Encrypted Data", "Encrypted data out of an Encryption PlugIn", "", false, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, "")]
105        public virtual CryptoolStream CSEncryptedData
106        {
107            get { return this.csEncryptedData; }
108            set
109            {
110                if (value != this.csEncryptedData)
111                {
112                    this.csEncryptedData = value;
113                    this.encryptedData = GetByteFromCryptoolStream(value);
114                    OnPropertyChanged("CSEncryptedData");
115                }
116            }
117        }
118
119        byte[] encryptedData;
120        [PropertyInfo(Direction.InputData,"Encrypted Data","Encrypted data out of an Encryption PlugIn","",false,false,DisplayLevel.Beginner,QuickWatchFormat.Hex,"")]
121        public virtual byte[] EncryptedData
122        {
123            get { return this.encryptedData; }
124            set
125            {
126                if (value != this.encryptedData)
127                {
128                    this.encryptedData = value;
129                    OnPropertyChanged("EncryptedData");
130                }
131            }
132        }
133
134        /// <summary>
135        /// When the Input-Slot changed, set this variable to true, so the new Stream will be transformed to byte[]
136        /// </summary>
137        private byte[] GetByteFromCryptoolStream(CryptoolStream cryptoolStream)
138        {
139            byte[] encryptedByteData = null;
140
141            if (cryptoolStream != null)
142            {
143                CryptoolStream cs = new CryptoolStream();
144                cs.OpenRead(cryptoolStream.FileName);
145                encryptedByteData = new byte[cs.Length];
146                if(cs.Length > Int32.MaxValue)
147                    throw(new Exception("CryptoolStream length is longer than the Int32.MaxValue"));
148                cs.Read(encryptedByteData, 0, (int)cs.Length);
149            }
150            return encryptedByteData;
151        }
152
153        byte[] initVector;
154        [PropertyInfo(Direction.InputData, "Initialization Vector", "Initialization vector with which the data were encrypted", "", DisplayLevel.Beginner)]
155        public virtual byte[] InitVector
156        {
157            get { return this.initVector; }
158            set
159            {
160                if (value != this.initVector)
161                {
162                    this.initVector = value;
163                    OnPropertyChanged("InitVector");
164                }
165            }
166        }
167        /* END: Lines above are from Arnie - 2010.01.12 */
168
169        private ValueKey top1ValueKey;
170        public virtual ValueKey Top1
171        {
172            set { top1ValueKey = value; OnPropertyChanged("Top1Message"); OnPropertyChanged("Top1Key"); }
173        }
174
175        [PropertyInfo(Direction.OutputData, "Top1 Message", "The best message found", "", DisplayLevel.Beginner)]
176        public virtual byte[] Top1Message
177        {
178            get { return top1ValueKey.decryption; }
179        }
180        [PropertyInfo(Direction.OutputData, "Top1 Key", "The best key found", "", DisplayLevel.Beginner)]
181        public virtual byte[] Top1Key
182        {
183            get
184            {
185                if (top1ValueKey.key != null) //added by Arnold - 2010.02.22
186                {
187                    int[] a = null, b = null, c = null;
188                    return ControlMaster.getKeyFromString(top1ValueKey.key, ref a, ref b, ref c);
189                }
190                else
191                    return null;
192            }
193        }
194
195        #endregion
196
197        #region IPlugin Members
198
199        public event StatusChangedEventHandler OnPluginStatusChanged;
200
201        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
202
203        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
204
205        private KeySearcherSettings settings;
206        private AutoResetEvent _connectResetEvent;
207
208        public KeySearcher()
209        {
210            settings = new KeySearcherSettings(this);
211            QuickWatchPresentation = new KeySearcherQuickWatchPresentation();
212        }
213
214        public ISettings Settings
215        {
216            get { return settings; }
217        }
218
219        public UserControl Presentation
220        {
221            get { return QuickWatchPresentation; }
222        }
223
224        public UserControl QuickWatchPresentation
225        {
226            get;
227            private set;
228        }
229
230        public void PreExecution()
231        {
232        }
233
234        // because Encryption PlugIns were changed radical, the new StartPoint is here - Arnie 2010.01.12
235        public virtual void Execute()
236        {
237            //either byte[] CStream input or CryptoolStream Object input
238            if (encryptedData != null || csEncryptedData != null) //to prevent execution on initialization
239            {
240                if (ControlMaster != null)
241                    process(ControlMaster);
242                else
243                {
244                    GuiLogMessage("You have to connect the KeySearcher with the Decryption Control!", NotificationLevel.Warning);
245                }
246            }
247        }
248
249        public void PostExecution()
250        {
251        }
252
253        public void Pause()
254        {
255        }
256
257        public void Stop()
258        {
259            stop = true;
260        }
261
262        public void Initialize()
263        {
264        }
265
266        public void Dispose()
267        {
268        }
269
270        #endregion
271
272        #region INotifyPropertyChanged Members
273
274        public event PropertyChangedEventHandler PropertyChanged;
275
276        public void OnPropertyChanged(string name)
277        {
278            if (PropertyChanged != null)
279            {
280                PropertyChanged(this, new PropertyChangedEventArgs(name));
281            }
282        }
283
284        #endregion
285
286        /* BEGIN functionality */
287
288        #region whole KeySearcher functionality
289
290        private class ThreadStackElement
291        {
292            public AutoResetEvent ev;
293            public int threadid;
294        }
295
296        #region code for the worker threads
297
298        private void KeySearcherJob(object param)
299        {
300            object[] parameters = (object[])param;
301            KeyPattern.KeyPattern[] patterns = (KeyPattern.KeyPattern[])parameters[0];
302            int threadid = (int)parameters[1];
303            BigInteger[] doneKeysArray = (BigInteger[])parameters[2];
304            BigInteger[] keycounterArray = (BigInteger[])parameters[3];
305            BigInteger[] keysLeft = (BigInteger[])parameters[4];
306            IControlEncryption sender = (IControlEncryption)parameters[5];
307            int bytesToUse = (int)parameters[6];
308            Stack threadStack = (Stack)parameters[7];
309
310            KeyPattern.KeyPattern pattern = patterns[threadid];
311
312            bool useKeyblocks = false;
313
314            try
315            {
316                while (pattern != null)
317                {
318                    BigInteger size = pattern.size();
319                    keysLeft[threadid] = size;
320                    int nextWildcard;
321
322                    do
323                    {
324                        //if we are the thread with most keys left, we have to share them:
325                        if (maxThread == threadid && threadStack.Count != 0)
326                        {
327                            try
328                            {
329                                maxThreadMutex.WaitOne();
330                                if (maxThread == threadid && threadStack.Count != 0)
331                                {
332                                    KeyPattern.KeyPattern[] split = pattern.split();
333                                    if (split != null)
334                                    {
335                                        patterns[threadid] = split[0];
336                                        pattern = split[0];
337                                        ThreadStackElement elem = (ThreadStackElement)threadStack.Pop();
338                                        patterns[elem.threadid] = split[1];
339                                        elem.ev.Set();    //wake the other thread up                                   
340                                        size = pattern.size();
341                                        keysLeft[threadid] = size;
342                                    }
343                                    maxThread = -1;
344                                }
345                            }
346                            finally
347                            {
348                                maxThreadMutex.ReleaseMutex();
349                            }
350                        }
351
352
353                        ValueKey valueKey = new ValueKey();
354                        int blocksize = 0;
355                        nextWildcard = -3;
356                        try
357                        {
358                            string key = "";
359                            if (useKeyblocks)
360                                key = pattern.getKeyBlock(ref blocksize, ref nextWildcard);
361                            if (key == null)
362                                useKeyblocks = false;
363                            if (!useKeyblocks)
364                                key = pattern.getKey();
365                            valueKey.key = key;
366                        }
367                        catch (Exception ex)
368                        {
369                            GuiLogMessage("Could not get next key: " + ex.Message, NotificationLevel.Error);
370                            return;
371                        }
372
373                        int[] arrayPointers = null;
374                        int[] arraySuccessors = null;
375                        int[] arrayUppers = null;
376                        byte[] keya = ControlMaster.getKeyFromString(valueKey.key, ref arrayPointers, ref arraySuccessors, ref arrayUppers);
377                        if (keya == null)
378                        {
379                            useKeyblocks = false;
380                            nextWildcard = -2;
381                            continue;   //try again
382                        }
383
384                        if (arrayPointers == null)  //decrypt only one key
385                        {
386                            if (!decryptAndCalculate(sender, bytesToUse, ref valueKey, keya, 0, null))
387                                return;
388                            doneKeysArray[threadid]++;
389                            keycounterArray[threadid]++;
390                            keysLeft[threadid]--;
391                        }
392                        else  //decrypt several keys
393                        {
394                            int counter = 0;
395                            if (!bruteforceBlock(sender, bytesToUse, ref valueKey, keya, arrayPointers, arraySuccessors, arrayUppers, 0, ref counter, pattern))
396                                return;
397                            doneKeysArray[threadid] += blocksize;
398                            keycounterArray[threadid] += blocksize;
399                            keysLeft[threadid] -= blocksize;
400                        }
401                    } while (pattern.nextKey(nextWildcard) && !stop);
402
403                    if (stop)
404                        return;
405
406                    //Let's wait until another thread is willing to share with us:
407                    pattern = null;
408                    ThreadStackElement el = new ThreadStackElement();
409                    el.ev = new AutoResetEvent(false);
410                    el.threadid = threadid;
411                    patterns[threadid] = null;
412                    threadStack.Push(el);
413                    GuiLogMessage("Thread waiting for new keys.", NotificationLevel.Debug);
414                    el.ev.WaitOne();
415                    GuiLogMessage("Thread waking up with new keys.", NotificationLevel.Debug);
416                    pattern = patterns[threadid];
417                }
418            }
419            finally
420            {
421                sender.Dispose();
422            }
423        }
424
425        #region bruteforce methods
426
427        private bool bruteforceBlock(IControlEncryption sender, int bytesToUse, ref ValueKey valueKey, byte[] keya, int[] arrayPointers,
428            int[] arraySuccessors, int[] arrayUppers, int arrayPointer, ref int counter, KeyPattern.KeyPattern pattern)
429        {
430            byte store = keya[arrayPointers[arrayPointer]];
431            while (!stop)
432            {
433                if (arrayPointer + 1 < arrayPointers.Length && arrayPointers[arrayPointer + 1] != -1)
434                {
435                    if (!bruteforceBlock(sender, bytesToUse, ref valueKey, keya, arrayPointers, arraySuccessors, arrayUppers, arrayPointer + 1, ref counter, pattern))
436                        return false;
437                }
438                else
439                {
440                    if (!decryptAndCalculate(sender, bytesToUse, ref valueKey, keya, counter, pattern))
441                        return false;
442                }
443
444                if (keya[arrayPointers[arrayPointer]] + arraySuccessors[arrayPointer] <= arrayUppers[arrayPointer])
445                {
446                    keya[arrayPointers[arrayPointer]] += (byte)arraySuccessors[arrayPointer];
447                    counter++;
448                }
449                else
450                    break;
451            }
452            keya[arrayPointers[arrayPointer]] = store;
453            if (stop)
454                return false;
455            return true;
456        }
457
458        private bool decryptAndCalculate(IControlEncryption sender, int bytesToUse, ref ValueKey valueKey, byte[] keya, int counter, KeyPattern.KeyPattern pattern)
459        {
460            try
461            {
462                if (this.encryptedData != null && this.encryptedData.Length > 0)
463                {
464                    valueKey.decryption = sender.Decrypt(this.encryptedData, keya, InitVector, bytesToUse);
465                }
466                else
467                {
468                    GuiLogMessage("Can't bruteforce empty input!", NotificationLevel.Error);
469                    return false;
470                }
471                //CryptoolStream cs = new CryptoolStream();
472                //if (this.CSEncryptedData == null)
473                //{
474                //    cs.OpenRead(this.EncryptedData);
475                //    valueKey.decryption = sender.Decrypt(this.EncryptedData, keya);
476                //}
477                //else
478                //{
479                //    cs.OpenRead(this.CSEncryptedData.FileName);
480                //    byte[] byteCS = new byte[cs.Length];
481                //    cs.Read(byteCS, 0, byteCS.Length);
482                //    //this.CSEncryptedData.Read(byteCS, 0, byteCS.Length);
483                //    valueKey.decryption = sender.Decrypt(byteCS, keya);
484                //}
485
486                //valueKey.decryption = sender.Decrypt(keya, bytesToUse);
487            }
488            catch (Exception ex)
489            {
490                GuiLogMessage("Decryption is not possible: " + ex.Message, NotificationLevel.Error);
491                GuiLogMessage("Stack Trace: " + ex.StackTrace, NotificationLevel.Error);
492                return false;
493            }
494
495            try
496            {
497                valueKey.value = CostMaster.calculateCost(valueKey.decryption);
498            }
499            catch (Exception ex)
500            {
501                GuiLogMessage("Cost calculation is not possible: " + ex.Message, NotificationLevel.Error);
502                return false;
503            }
504
505            if (this.costMaster.getRelationOperator() == RelationOperator.LargerThen)
506            {
507                if (valueKey.value > value_threshold)
508                {
509                    if (pattern != null)
510                        valueKey.key = pattern.getKey(counter);
511                    valuequeue.Enqueue(valueKey);
512                }
513            }
514            else
515            {
516                if (valueKey.value < value_threshold)
517                {
518                    if (pattern != null)
519                        valueKey.key = pattern.getKey(counter);
520                    valuequeue.Enqueue(valueKey);
521                }
522            }
523            return true;
524        }
525
526        #endregion
527
528        #endregion
529
530        public void process(IControlEncryption sender)
531        {
532            if (sender == null || costMaster == null)
533                return;
534            if (!Pattern.testWildcardKey(settings.Key))
535            {
536                GuiLogMessage("Wrong key pattern!", NotificationLevel.Error);
537                return;
538            }
539            Pattern.WildcardKey = settings.Key;
540            this.sender = sender;
541
542            bruteforcePattern(Pattern);
543        }
544
545        internal LinkedList<ValueKey> costList = new LinkedList<ValueKey>();
546        private int bytesToUse;
547        private IControlEncryption sender;
548        private DateTime beginBruteforcing;
549
550        // modified by Christian Arnold 2009.12.07 - return type LinkedList (top10List)
551        // main entry point to the KeySearcher
552        private LinkedList<ValueKey> bruteforcePattern(KeyPattern.KeyPattern pattern)
553        {
554            //For evaluation issues - added by Arnold 2010.03.17
555            beginBruteforcing = DateTime.Now;
556            GuiLogMessage("Start bruteforcing pattern '" + pattern.getKey() + "'", NotificationLevel.Debug);
557
558
559                       
560            int maxInList = 10;
561            costList = new LinkedList<ValueKey>();
562            fillListWithDummies(maxInList, costList);
563            valuequeue = Queue.Synchronized(new Queue());
564
565            stop = false;
566            if (!pattern.testWildcardKey(settings.Key))
567            {
568                GuiLogMessage("Wrong key pattern!", NotificationLevel.Error);
569                return null;
570            }
571
572            bytesToUse = 0;
573
574            try
575            {
576                bytesToUse = CostMaster.getBytesToUse();
577            }
578            catch (Exception ex)
579            {
580                GuiLogMessage("Bytes used not valid: " + ex.Message, NotificationLevel.Error);
581                return null;
582            }
583
584            if (settings.UsePeerToPeer)
585            {
586                BruteForceWithPeerToPeerSystem();
587                return null;
588            }
589
590            return BruteForceWithLocalSystem(pattern);
591        }
592
593        private Dispatcher _dispatcher;
594
595        private void BruteForceWithPeerToPeerSystem()
596        {
597            _dispatcher = Dispatcher.CurrentDispatcher;
598            GuiLogMessage("Launching p2p based bruteforce logic...", NotificationLevel.Info);
599            ValidateConnectionToPeerToPeerSystem();
600            var bruteForceManager = new DistributedBruteForceManager(this, pattern, settings, _keyQualityHelper);
601            bruteForceManager.Execute();
602        }
603
604
605        #region P2P connection validation
606
607        private void ValidateConnectionToPeerToPeerSystem()
608        {
609            if (P2PManager.IsConnected)
610            {
611                return;
612            }
613
614            if(settings.AutoconnectPeerToPeer)
615            {
616                HandleAutoconnect();
617            } else
618            {
619                GuiLogMessage("P2P network not connected and autoconnect disabled. Cannot compute job.",
620                              NotificationLevel.Error);
621            }
622        }
623
624        private void HandleAutoconnect()
625        {
626            P2PManager.ConnectionManager.OnP2PConnectionStateChangeOccurred += HandleConnectionStateChange;
627            _connectResetEvent = new AutoResetEvent(false);
628
629            P2PManager.Connect();
630
631            _connectResetEvent.WaitOne();
632
633            if (P2PManager.IsConnected)
634            {
635                GuiLogMessage("P2P network was connected due to plugin setting.",
636                              NotificationLevel.Info);
637            }
638            else
639            {
640                GuiLogMessage("P2P network could not be connected.",
641                              NotificationLevel.Error);
642            }
643        }
644
645        void HandleConnectionStateChange(object sender, bool newState)
646        {
647            _connectResetEvent.Set();
648        }
649
650        #endregion
651
652        internal LinkedList<ValueKey> BruteForceWithLocalSystem(KeyPattern.KeyPattern pattern)
653        {
654            BigInteger size = pattern.size();
655            KeyPattern.KeyPattern[] patterns = splitPatternForThreads(pattern);
656
657            BigInteger[] doneKeysA = new BigInteger[patterns.Length];
658            BigInteger[] keycounters = new BigInteger[patterns.Length];
659            BigInteger[] keysleft = new BigInteger[patterns.Length];
660            Stack threadStack = Stack.Synchronized(new Stack());
661            startThreads(sender, bytesToUse, patterns, doneKeysA, keycounters, keysleft, threadStack);
662
663            //update message:
664            while (!stop)
665            {
666                Thread.Sleep(1000);
667
668                updateToplist();
669
670                #region calculate global counters from local counters
671                BigInteger keycounter = 0;
672                BigInteger doneKeys = 0;
673                foreach (BigInteger dk in doneKeysA)
674                    doneKeys += dk;
675                foreach (BigInteger kc in keycounters)
676                    keycounter += kc;
677                #endregion
678
679                if (keycounter > size)
680                    GuiLogMessage("There must be an error, because we bruteforced too much keys...", NotificationLevel.Error);
681
682                #region determination of the thread with most keys
683                if (size - keycounter > 1000)
684                {
685                    try
686                    {
687                        maxThreadMutex.WaitOne();
688                        BigInteger max = 0;
689                        int id = -1;
690                        for (int i = 0; i < patterns.Length; i++)
691                            if (keysleft[i] != null && keysleft[i] > max)
692                            {
693                                max = keysleft[i];
694                                id = i;
695                            }
696                        maxThread = id;
697                    }
698                    finally
699                    {
700                        maxThreadMutex.ReleaseMutex();
701                    }
702                }
703                #endregion
704
705                showProgress(costList, size, keycounter, doneKeys);
706
707                #region set doneKeys to 0
708                doneKeys = 0;
709                for (int i = 0; i < doneKeysA.Length; i++)
710                    doneKeysA[i] = 0;
711                #endregion
712
713                if (keycounter >= size)
714                    break;
715            }//end while
716
717            //wake up all sleeping threads, so they can stop:
718            while (threadStack.Count != 0)
719                ((ThreadStackElement)threadStack.Pop()).ev.Set();
720
721            if (!stop)
722                ProgressChanged(1, 1);
723
724            /* BEGIN: For evaluation issues - added by Arnold 2010.03.17 */
725            TimeSpan bruteforcingTime = DateTime.Now.Subtract(beginBruteforcing);
726            StringBuilder sbBFTime = new StringBuilder();
727            if (bruteforcingTime.Days > 0)
728                sbBFTime.Append(bruteforcingTime.Days.ToString() + " days ");
729            if (bruteforcingTime.Hours > 0)
730            {
731                if (bruteforcingTime.Hours <= 9)
732                    sbBFTime.Append("0");
733                sbBFTime.Append(bruteforcingTime.Hours.ToString() + ":");
734            }
735            if (bruteforcingTime.Minutes <= 9)
736                sbBFTime.Append("0");
737            sbBFTime.Append(bruteforcingTime.Minutes.ToString() + ":");
738            if (bruteforcingTime.Seconds <= 9)
739                sbBFTime.Append("0");
740            sbBFTime.Append(bruteforcingTime.Seconds.ToString() + "-");
741            if (bruteforcingTime.Milliseconds <= 9)
742                sbBFTime.Append("00");
743            if (bruteforcingTime.Milliseconds <= 99)
744                sbBFTime.Append("0");
745            sbBFTime.Append(bruteforcingTime.Milliseconds.ToString());
746
747            GuiLogMessage("Ended bruteforcing pattern '" + pattern.getKey() + "'. Bruteforcing TimeSpan: " + sbBFTime.ToString(), NotificationLevel.Debug);
748            /* END: For evaluation issues - added by Arnold 2010.03.17 */
749
750            return costList;
751        }
752
753        internal void showProgress(LinkedList<ValueKey> costList, BigInteger size, BigInteger keycounter, BigInteger doneKeys)
754        {
755            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
756
757            LinkedListNode<ValueKey> linkedListNode;
758            ProgressChanged((double)keycounter / (double) size, 1.0);
759
760            if (QuickWatchPresentation.IsVisible && doneKeys != 0 && !stop)
761            {
762                double time = (Math.Pow(10, BigInteger.Log((size - keycounter), 10) - BigInteger.Log(doneKeys, 10)));
763                TimeSpan timeleft = new TimeSpan(-1);
764
765                try
766                {
767                    if (time / (24 * 60 * 60) <= int.MaxValue)
768                    {
769                        int days = (int)(time / (24 * 60 * 60));
770                        time = time - (days * 24 * 60 * 60);
771                        int hours = (int)(time / (60 * 60));
772                        time = time - (hours * 60 * 60);
773                        int minutes = (int)(time / 60);
774                        time = time - (minutes * 60);
775                        int seconds = (int)time;
776
777                        timeleft = new TimeSpan(days, hours, minutes, (int)seconds, 0);
778                    }
779                }
780                catch
781                {
782                    //can not calculate time span
783                }
784
785                ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
786                {
787                    ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).keysPerSecond.Text = "" + doneKeys;
788                    if (timeleft != new TimeSpan(-1))
789                    {
790                        ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).timeLeft.Text = "" + timeleft;
791                        try
792                        {
793                            ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).endTime.Text = "" + DateTime.Now.Add(timeleft);
794                        }
795                        catch
796                        {
797                            ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).endTime.Text = "in a galaxy far, far away...";
798                        }
799                    }
800                    else
801                    {
802                        ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).timeLeft.Text = "incalculable :-)";
803                        ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).endTime.Text = "in a galaxy far, far away...";
804                    }
805
806                    ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).entries.Clear();
807                    linkedListNode = costList.First;
808                   
809                    int i = 0;
810                    while (linkedListNode != null)
811                    {
812                        i++;
813
814                        ResultEntry entry = new ResultEntry();
815                        entry.Ranking = "" + i;
816                        entry.Value = "" + Math.Round(linkedListNode.Value.value,3);
817                        entry.Key = linkedListNode.Value.key;
818                        entry.Text = enc.GetString(linkedListNode.Value.decryption);
819
820                        ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).entries.Add(entry);
821                        linkedListNode = linkedListNode.Next;
822                    }
823                }
824                , null);
825            }//end if
826
827
828            else if (!stop && QuickWatchPresentation.IsVisible)
829            {
830
831                ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
832                {
833                    ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).entries.Clear();
834                    linkedListNode = costList.First;                   
835                    int i = 0;
836
837                    while (linkedListNode != null)
838                    {
839                        i++;
840
841                        ResultEntry entry = new ResultEntry();
842                        entry.Ranking = "" + i;
843                        entry.Value = "" + Math.Round(linkedListNode.Value.value, 3);
844                        entry.Key = linkedListNode.Value.key;
845                        entry.Text = enc.GetString(linkedListNode.Value.decryption);
846
847                        ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).entries.Add(entry);
848                        linkedListNode = linkedListNode.Next;
849                    }
850                }
851                , null);
852            }
853        }
854
855        #region For TopList
856
857        private void fillListWithDummies(int maxInList, LinkedList<ValueKey> costList)
858        {
859            ValueKey valueKey = new ValueKey();
860            if (this.costMaster.getRelationOperator() == RelationOperator.LessThen)
861                valueKey.value = double.MaxValue;
862            else
863                valueKey.value = double.MinValue;
864            valueKey.key = "dummykey";
865            valueKey.decryption = new byte[0];
866            value_threshold = valueKey.value;
867            LinkedListNode<ValueKey> node = costList.AddFirst(valueKey);
868            for (int i = 1; i < maxInList; i++)
869            {
870                node = costList.AddAfter(node, valueKey);
871            }
872        }
873
874        internal void IntegrateNewResults(LinkedList<ValueKey> costList)
875        {
876            foreach (var valueKey in costList)
877            {
878                if (_keyQualityHelper.IsBetter(valueKey.value, value_threshold))
879                {
880                    valuequeue.Enqueue(valueKey);
881                }
882            }
883
884            updateToplist();
885            UpdateWithShowProgress();
886        }
887
888        internal void updateToplist()
889        {
890            LinkedListNode<ValueKey> node;
891            while (valuequeue.Count != 0)
892            {
893                ValueKey vk = (ValueKey)valuequeue.Dequeue();
894
895                //if (costList.Contains(vk)) continue;
896                var result = costList.Where(valueKey => valueKey.key == vk.key);
897                if (result.Count() > 0)
898                {
899                    continue;
900                }
901
902                if (this.costMaster.getRelationOperator() == RelationOperator.LargerThen)
903                {
904                    if (vk.value > costList.Last().value)
905                    {
906                        node = costList.First;
907                        while (node != null)
908                        {
909                            if (vk.value > node.Value.value)
910                            {
911                                if (node == costList.First)
912                                    Top1 = vk;
913                                costList.AddBefore(node, vk);
914                                costList.RemoveLast();
915                                value_threshold = costList.Last.Value.value;
916                                break;
917                            }
918                            node = node.Next;
919                        }//end while
920                    }//end if
921                }
922                else
923                {
924                    if (vk.value < costList.Last().value)
925                    {
926                        node = costList.First;
927                        while (node != null)
928                        {
929                            if (vk.value < node.Value.value)
930                            {
931                                if (node == costList.First)
932                                    Top1 = vk;
933                                costList.AddBefore(node, vk);
934                                costList.RemoveLast();
935                                value_threshold = costList.Last.Value.value;
936                                break;
937                            }
938                            node = node.Next;
939                        }//end while
940                    }//end if
941                }
942            }
943        }
944
945        private void UpdateWithShowProgress()
946        {
947            showProgress(costList, 1, 0, 0);
948        }
949
950        #endregion
951
952        private void startThreads(IControlEncryption sender, int bytesToUse, KeyPattern.KeyPattern[] patterns, BigInteger[] doneKeysA, BigInteger[] keycounters, BigInteger[] keysleft, Stack threadStack)
953        {
954            for (int i = 0; i < patterns.Length; i++)
955            {
956                WaitCallback worker = new WaitCallback(KeySearcherJob);
957                doneKeysA[i] = new BigInteger();
958                keycounters[i] = new BigInteger();
959                //ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, keycounters, keysleft, sender.clone(), bytesToUse, threadStack });
960                ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack });
961            }
962        }
963
964        private KeyPattern.KeyPattern[] splitPatternForThreads(KeyPattern.KeyPattern pattern)
965        {
966            KeyPattern.KeyPattern[] patterns = new KeyPattern.KeyPattern[settings.CoresUsed + 1];
967            if (settings.CoresUsed > 0)
968            {
969                KeyPattern.KeyPattern[] patterns2 = pattern.split();
970                if (patterns2 == null)
971                {
972                    patterns2 = new KeyPattern.KeyPattern[1];
973                    patterns2[0] = pattern;
974                    return patterns2;
975                }
976                patterns[0] = patterns2[0];
977                patterns[1] = patterns2[1];
978                int p = 1;
979                int threads = settings.CoresUsed - 1;
980                while (threads > 0)
981                {
982                    int maxPattern = -1;
983                    BigInteger max = 0;
984                    for (int i = 0; i <= p; i++)
985                        if (patterns[i].size() > max)
986                        {
987                            max = patterns[i].size();
988                            maxPattern = i;
989                        }
990                    KeyPattern.KeyPattern[] patterns3 = patterns[maxPattern].split();
991                    if (patterns3 == null)
992                    {
993                        patterns3 = new KeyPattern.KeyPattern[p+1];
994                        for (int i = 0; i <= p; i++)
995                            patterns3[i] = patterns[i];
996                        return patterns3;
997                    }
998                    patterns[maxPattern] = patterns3[0];
999                    patterns[++p] = patterns3[1];
1000                    threads--;
1001                }
1002            }
1003            else
1004                patterns[0] = Pattern;
1005            return patterns;
1006        }
1007
1008        private void keyPatternChanged()
1009        {
1010            Pattern = new KeyPattern.KeyPattern(controlMaster.getKeyPattern());
1011        }
1012
1013        // added by Arnie - 2009.12.07
1014        public delegate void BruteforcingEnded(LinkedList<ValueKey> top10List);
1015        /// <summary>
1016        /// This event gets thrown after Bruteforcing had ended. This is no evidence, that bruteforcing was successful.
1017        /// But when the returned List is filled, we have (at least a part) of the possible best keys
1018        /// </summary>
1019        public event BruteforcingEnded OnBruteforcingEnded;
1020
1021        // added by Arnie -2009.12.02
1022        // for inheritance reasons
1023        public void BruteforcePattern(KeyPattern.KeyPattern pattern, byte[] encryptedData, byte[] initVector, IControlEncryption encryptControl, IControlCost costControl)
1024        {
1025            /* Begin: New stuff because of changing the IControl data flow - Arnie 2010.01.18 */
1026            this.encryptedData = encryptedData;
1027            this.initVector = initVector;
1028            /* End: New stuff because of changing the IControl data flow - Arnie 2010.01.18 */
1029
1030            this.sender = encryptControl;
1031            LinkedList<ValueKey> lstRet = bruteforcePattern(pattern);
1032            if(OnBruteforcingEnded != null)
1033                OnBruteforcingEnded(lstRet);
1034        }
1035
1036        #endregion
1037
1038        public void GuiLogMessage(string message, NotificationLevel loglevel)
1039        {
1040            if (OnGuiLogNotificationOccured != null)
1041                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(message, this, loglevel));
1042        }
1043
1044        public void ProgressChanged(double value, double max)
1045        {
1046            if (OnPluginProgressChanged != null)
1047            {
1048                OnPluginProgressChanged(this, new PluginProgressEventArgs(value, max));
1049
1050            }
1051        }
1052
1053        /// <summary>
1054        /// used for delivering the results from the worker threads to the main thread:
1055        /// </summary>
1056        public struct ValueKey
1057        {
1058            public double value;
1059            public String key;
1060            public byte[] decryption;
1061        };
1062    }
1063
1064    /// <summary>
1065    /// Represents one entry in our result list
1066    /// </summary>
1067    public class ResultEntry
1068    {
1069        public string Ranking { get; set; }
1070        public string Value { get; set; }
1071        public string Key { get; set; }
1072        public string Text { get; set; }
1073
1074    }
1075}
Note: See TracBrowser for help on using the repository browser.