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

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

o Work on the distributed KeySearcher

File size: 40.3 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.Miscellaneous;
15using System.IO;
16using Cryptool.PluginBase.IO;
17using System.Numerics;
18using KeySearcher.Helper;
19using KeySearcher.P2P;
20
21namespace KeySearcher
22{   
23    [Author("Sven Rech, Nils Kopal, Raoul Falk, Dennis Nolte", "rech@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-due.de")]
24    [PluginInfo(false, "KeySearcher", "Bruteforces a decryption algorithm.", "KeySearcher/DetailedDescription/Description.xaml", "KeySearcher/Images/icon.png")]
25    public class KeySearcher : IAnalysisMisc
26    {
27        /// <summary>
28        /// used for creating the TopList
29        /// </summary>
30        private Queue valuequeue;
31        private double value_threshold;
32        /// <summary>
33        /// the thread with the most keys left
34        /// </summary>
35        private int maxThread;
36        private Mutex maxThreadMutex = new Mutex();
37
38        private KeyQualityHelper _keyQualityHelper;
39
40        private KeyPattern pattern = null;
41        public KeyPattern Pattern
42        {
43            get
44            {
45                return pattern;
46            }
47            set
48            {
49                pattern = value;
50                if ((settings.Key == null) || ((settings.Key != null) && !pattern.testWildcardKey(settings.Key)))
51                    settings.Key = pattern.giveInputPattern();
52            }
53        }
54
55        internal bool stop;
56
57        #region IControlEncryption + IControlCost + InputFields
58
59        #region IControlEncryption Members
60
61        private IControlEncryption controlMaster;
62        [PropertyInfo(Direction.ControlMaster, "Control Master", "Used for bruteforcing", "", DisplayLevel.Beginner)]
63        public IControlEncryption ControlMaster
64        {
65            get { return controlMaster; }
66            set
67            {
68                if (controlMaster != null)
69                {
70                    controlMaster.keyPatternChanged -= keyPatternChanged;
71                }
72                if (value != null)
73                {
74                    Pattern = new KeyPattern(value.getKeyPattern());
75                    value.keyPatternChanged += keyPatternChanged;
76                    controlMaster = value;
77                    OnPropertyChanged("ControlMaster");
78
79                }
80                else
81                    controlMaster = null;
82            }
83        }
84
85        #endregion
86
87        #region IControlCost Members
88
89        private IControlCost costMaster;
90        [PropertyInfo(Direction.ControlMaster, "Cost Master", "Used for cost calculation", "", DisplayLevel.Beginner)]
91        public IControlCost CostMaster
92        {
93            get { return costMaster; }
94            set
95            {
96                costMaster = value;
97                _keyQualityHelper = new KeyQualityHelper(costMaster);
98            }
99        }
100
101        #endregion
102
103        /* BEGIN: following lines are from Arnie - 2010.01.12 */
104        CryptoolStream csEncryptedData;
105        [PropertyInfo(Direction.InputData, "CS Encrypted Data", "Encrypted data out of an Encryption PlugIn", "", false, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, "")]
106        public virtual CryptoolStream CSEncryptedData
107        {
108            get { return this.csEncryptedData; }
109            set
110            {
111                if (value != this.csEncryptedData)
112                {
113                    this.csEncryptedData = value;
114                    this.encryptedData = GetByteFromCryptoolStream(value);
115                    OnPropertyChanged("CSEncryptedData");
116                }
117            }
118        }
119
120        byte[] encryptedData;
121        [PropertyInfo(Direction.InputData,"Encrypted Data","Encrypted data out of an Encryption PlugIn","",false,false,DisplayLevel.Beginner,QuickWatchFormat.Hex,"")]
122        public virtual byte[] EncryptedData
123        {
124            get { return this.encryptedData; }
125            set
126            {
127                if (value != this.encryptedData)
128                {
129                    this.encryptedData = value;
130                    OnPropertyChanged("EncryptedData");
131                }
132            }
133        }
134
135        /// <summary>
136        /// When the Input-Slot changed, set this variable to true, so the new Stream will be transformed to byte[]
137        /// </summary>
138        private byte[] GetByteFromCryptoolStream(CryptoolStream cryptoolStream)
139        {
140            byte[] encryptedByteData = null;
141
142            if (cryptoolStream != null)
143            {
144                CryptoolStream cs = new CryptoolStream();
145                cs.OpenRead(cryptoolStream.FileName);
146                encryptedByteData = new byte[cs.Length];
147                if(cs.Length > Int32.MaxValue)
148                    throw(new Exception("CryptoolStream length is longer than the Int32.MaxValue"));
149                cs.Read(encryptedByteData, 0, (int)cs.Length);
150            }
151            return encryptedByteData;
152        }
153
154        byte[] initVector;
155        [PropertyInfo(Direction.InputData, "Initialization Vector", "Initialization vector with which the data were encrypted", "", DisplayLevel.Beginner)]
156        public virtual byte[] InitVector
157        {
158            get { return this.initVector; }
159            set
160            {
161                if (value != this.initVector)
162                {
163                    this.initVector = value;
164                    OnPropertyChanged("InitVector");
165                }
166            }
167        }
168        /* END: Lines above are from Arnie - 2010.01.12 */
169
170        private ValueKey top1ValueKey;
171        public virtual ValueKey Top1
172        {
173            set { top1ValueKey = value; OnPropertyChanged("Top1Message"); OnPropertyChanged("Top1Key"); }
174        }
175
176        [PropertyInfo(Direction.OutputData, "Top1 Message", "The best message found", "", DisplayLevel.Beginner)]
177        public virtual byte[] Top1Message
178        {
179            get { return top1ValueKey.decryption; }
180        }
181        [PropertyInfo(Direction.OutputData, "Top1 Key", "The best key found", "", DisplayLevel.Beginner)]
182        public virtual byte[] Top1Key
183        {
184            get
185            {
186                if (top1ValueKey.key != null) //added by Arnold - 2010.02.22
187                {
188                    int[] a = null, b = null, c = null;
189                    return ControlMaster.getKeyFromString(top1ValueKey.key, ref a, ref b, ref c);
190                }
191                else
192                    return null;
193            }
194        }
195
196        #endregion
197
198        #region IPlugin Members
199
200        public event StatusChangedEventHandler OnPluginStatusChanged;
201
202        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
203
204        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
205
206        private KeySearcherSettings settings;
207        private AutoResetEvent _connectResetEvent;
208
209        public KeySearcher()
210        {
211            settings = new KeySearcherSettings(this);
212            QuickWatchPresentation = new KeySearcherQuickWatchPresentation();
213        }
214
215        public ISettings Settings
216        {
217            get { return settings; }
218        }
219
220        public UserControl Presentation
221        {
222            get { return QuickWatchPresentation; }
223        }
224
225        public UserControl QuickWatchPresentation
226        {
227            get;
228            private set;
229        }
230
231        public void PreExecution()
232        {
233        }
234
235        // because Encryption PlugIns were changed radical, the new StartPoint is here - Arnie 2010.01.12
236        public virtual void Execute()
237        {
238            //either byte[] CStream input or CryptoolStream Object input
239            if (encryptedData != null || csEncryptedData != null) //to prevent execution on initialization
240            {
241                if (ControlMaster != null)
242                    process(ControlMaster);
243                else
244                {
245                    GuiLogMessage("You have to connect the KeySearcher with the Decryption Control!", NotificationLevel.Warning);
246                }
247            }
248        }
249
250        public void PostExecution()
251        {
252        }
253
254        public void Pause()
255        {
256        }
257
258        public void Stop()
259        {
260            stop = true;
261        }
262
263        public void Initialize()
264        {
265        }
266
267        public void Dispose()
268        {
269        }
270
271        #endregion
272
273        #region INotifyPropertyChanged Members
274
275        public event PropertyChangedEventHandler PropertyChanged;
276
277        public void OnPropertyChanged(string name)
278        {
279            if (PropertyChanged != null)
280            {
281                PropertyChanged(this, new PropertyChangedEventArgs(name));
282            }
283        }
284
285        #endregion
286
287        /* BEGIN functionality */
288
289        #region whole KeySearcher functionality
290
291        private class ThreadStackElement
292        {
293            public AutoResetEvent ev;
294            public int threadid;
295        }
296
297        #region code for the worker threads
298
299        private void KeySearcherJob(object param)
300        {
301            object[] parameters = (object[])param;
302            KeyPattern[] patterns = (KeyPattern[])parameters[0];
303            int threadid = (int)parameters[1];
304            BigInteger[] doneKeysArray = (BigInteger[])parameters[2];
305            BigInteger[] keycounterArray = (BigInteger[])parameters[3];
306            BigInteger[] keysLeft = (BigInteger[])parameters[4];
307            IControlEncryption sender = (IControlEncryption)parameters[5];
308            int bytesToUse = (int)parameters[6];
309            Stack threadStack = (Stack)parameters[7];
310
311            KeyPattern pattern = patterns[threadid];
312
313            bool useKeyblocks = false;
314
315            try
316            {
317                while (pattern != null)
318                {
319                    BigInteger size = pattern.size();
320                    keysLeft[threadid] = size;
321                    int nextWildcard;
322
323                    do
324                    {
325                        //if we are the thread with most keys left, we have to share them:
326                        if (maxThread == threadid && threadStack.Count != 0)
327                        {
328                            try
329                            {
330                                maxThreadMutex.WaitOne();
331                                if (maxThread == threadid && threadStack.Count != 0)
332                                {
333                                    KeyPattern[] split = pattern.split();
334                                    if (split != null)
335                                    {
336                                        patterns[threadid] = split[0];
337                                        pattern = split[0];
338                                        ThreadStackElement elem = (ThreadStackElement)threadStack.Pop();
339                                        patterns[elem.threadid] = split[1];
340                                        elem.ev.Set();    //wake the other thread up                                   
341                                        size = pattern.size();
342                                        keysLeft[threadid] = size;
343                                    }
344                                    maxThread = -1;
345                                }
346                            }
347                            finally
348                            {
349                                maxThreadMutex.ReleaseMutex();
350                            }
351                        }
352
353
354                        ValueKey valueKey = new ValueKey();
355                        int blocksize = 0;
356                        nextWildcard = -3;
357                        try
358                        {
359                            string key = "";
360                            if (useKeyblocks)
361                                key = pattern.getKeyBlock(ref blocksize, ref nextWildcard);
362                            if (key == null)
363                                useKeyblocks = false;
364                            if (!useKeyblocks)
365                                key = pattern.getKey();
366                            valueKey.key = key;
367                        }
368                        catch (Exception ex)
369                        {
370                            GuiLogMessage("Could not get next key: " + ex.Message, NotificationLevel.Error);
371                            return;
372                        }
373
374                        int[] arrayPointers = null;
375                        int[] arraySuccessors = null;
376                        int[] arrayUppers = null;
377                        byte[] keya = ControlMaster.getKeyFromString(valueKey.key, ref arrayPointers, ref arraySuccessors, ref arrayUppers);
378                        if (keya == null)
379                        {
380                            useKeyblocks = false;
381                            nextWildcard = -2;
382                            continue;   //try again
383                        }
384
385                        if (arrayPointers == null)  //decrypt only one key
386                        {
387                            if (!decryptAndCalculate(sender, bytesToUse, ref valueKey, keya, 0, null))
388                                return;
389                            doneKeysArray[threadid]++;
390                            keycounterArray[threadid]++;
391                            keysLeft[threadid]--;
392                        }
393                        else  //decrypt several keys
394                        {
395                            int counter = 0;
396                            if (!bruteforceBlock(sender, bytesToUse, ref valueKey, keya, arrayPointers, arraySuccessors, arrayUppers, 0, ref counter, pattern))
397                                return;
398                            doneKeysArray[threadid] += blocksize;
399                            keycounterArray[threadid] += blocksize;
400                            keysLeft[threadid] -= blocksize;
401                        }
402                    } while (pattern.nextKey(nextWildcard) && !stop);
403
404                    if (stop)
405                        return;
406
407                    //Let's wait until another thread is willing to share with us:
408                    pattern = null;
409                    ThreadStackElement el = new ThreadStackElement();
410                    el.ev = new AutoResetEvent(false);
411                    el.threadid = threadid;
412                    patterns[threadid] = null;
413                    threadStack.Push(el);
414                    GuiLogMessage("Thread waiting for new keys.", NotificationLevel.Debug);
415                    el.ev.WaitOne();
416                    GuiLogMessage("Thread waking up with new keys.", NotificationLevel.Debug);
417                    pattern = patterns[threadid];
418                }
419            }
420            finally
421            {
422                sender.Dispose();
423            }
424        }
425
426        #region bruteforce methods
427
428        private bool bruteforceBlock(IControlEncryption sender, int bytesToUse, ref ValueKey valueKey, byte[] keya, int[] arrayPointers,
429            int[] arraySuccessors, int[] arrayUppers, int arrayPointer, ref int counter, KeyPattern pattern)
430        {
431            byte store = keya[arrayPointers[arrayPointer]];
432            while (!stop)
433            {
434                if (arrayPointer + 1 < arrayPointers.Length && arrayPointers[arrayPointer + 1] != -1)
435                {
436                    if (!bruteforceBlock(sender, bytesToUse, ref valueKey, keya, arrayPointers, arraySuccessors, arrayUppers, arrayPointer + 1, ref counter, pattern))
437                        return false;
438                }
439                else
440                {
441                    if (!decryptAndCalculate(sender, bytesToUse, ref valueKey, keya, counter, pattern))
442                        return false;
443                }
444
445                if (keya[arrayPointers[arrayPointer]] + arraySuccessors[arrayPointer] <= arrayUppers[arrayPointer])
446                {
447                    keya[arrayPointers[arrayPointer]] += (byte)arraySuccessors[arrayPointer];
448                    counter++;
449                }
450                else
451                    break;
452            }
453            keya[arrayPointers[arrayPointer]] = store;
454            if (stop)
455                return false;
456            return true;
457        }
458
459        private bool decryptAndCalculate(IControlEncryption sender, int bytesToUse, ref ValueKey valueKey, byte[] keya, int counter, KeyPattern pattern)
460        {
461            try
462            {
463                if (this.encryptedData != null && this.encryptedData.Length > 0)
464                {
465                    valueKey.decryption = sender.Decrypt(this.encryptedData, keya, InitVector, bytesToUse);
466                }
467                else
468                {
469                    GuiLogMessage("Can't bruteforce empty input!", NotificationLevel.Error);
470                    return false;
471                }
472                //CryptoolStream cs = new CryptoolStream();
473                //if (this.CSEncryptedData == null)
474                //{
475                //    cs.OpenRead(this.EncryptedData);
476                //    valueKey.decryption = sender.Decrypt(this.EncryptedData, keya);
477                //}
478                //else
479                //{
480                //    cs.OpenRead(this.CSEncryptedData.FileName);
481                //    byte[] byteCS = new byte[cs.Length];
482                //    cs.Read(byteCS, 0, byteCS.Length);
483                //    //this.CSEncryptedData.Read(byteCS, 0, byteCS.Length);
484                //    valueKey.decryption = sender.Decrypt(byteCS, keya);
485                //}
486
487                //valueKey.decryption = sender.Decrypt(keya, bytesToUse);
488            }
489            catch (Exception ex)
490            {
491                GuiLogMessage("Decryption is not possible: " + ex.Message, NotificationLevel.Error);
492                GuiLogMessage("Stack Trace: " + ex.StackTrace, NotificationLevel.Error);
493                return false;
494            }
495
496            try
497            {
498                valueKey.value = CostMaster.calculateCost(valueKey.decryption);
499            }
500            catch (Exception ex)
501            {
502                GuiLogMessage("Cost calculation is not possible: " + ex.Message, NotificationLevel.Error);
503                return false;
504            }
505
506            if (this.costMaster.getRelationOperator() == RelationOperator.LargerThen)
507            {
508                if (valueKey.value > value_threshold)
509                {
510                    if (pattern != null)
511                        valueKey.key = pattern.getKey(counter);
512                    valuequeue.Enqueue(valueKey);
513                }
514            }
515            else
516            {
517                if (valueKey.value < value_threshold)
518                {
519                    if (pattern != null)
520                        valueKey.key = pattern.getKey(counter);
521                    valuequeue.Enqueue(valueKey);
522                }
523            }
524            return true;
525        }
526
527        #endregion
528
529        #endregion
530
531        public void process(IControlEncryption sender)
532        {
533            if (sender == null || costMaster == null)
534                return;
535            if (!Pattern.testWildcardKey(settings.Key))
536            {
537                GuiLogMessage("Wrong key pattern!", NotificationLevel.Error);
538                return;
539            }
540            Pattern.WildcardKey = settings.Key;
541            this.sender = sender;
542
543            bruteforcePattern(Pattern);
544        }
545
546        internal LinkedList<ValueKey> costList = new LinkedList<ValueKey>();
547        private int bytesToUse;
548        private IControlEncryption sender;
549        private DateTime beginBruteforcing;
550
551        // modified by Christian Arnold 2009.12.07 - return type LinkedList (top10List)
552        // main entry point to the KeySearcher
553        private LinkedList<ValueKey> bruteforcePattern(KeyPattern pattern)
554        {
555            //For evaluation issues - added by Arnold 2010.03.17
556            beginBruteforcing = DateTime.Now;
557            GuiLogMessage("Start bruteforcing pattern '" + pattern.getKey() + "'", NotificationLevel.Debug);
558
559
560                       
561            int maxInList = 10;
562            costList = new LinkedList<ValueKey>();
563            fillListWithDummies(maxInList, costList);
564            valuequeue = Queue.Synchronized(new Queue());
565
566            stop = false;
567            if (!pattern.testWildcardKey(settings.Key))
568            {
569                GuiLogMessage("Wrong key pattern!", NotificationLevel.Error);
570                return null;
571            }
572
573            bytesToUse = 0;
574
575            try
576            {
577                bytesToUse = CostMaster.getBytesToUse();
578            }
579            catch (Exception ex)
580            {
581                GuiLogMessage("Bytes used not valid: " + ex.Message, NotificationLevel.Error);
582                return null;
583            }
584
585            if (settings.UsePeerToPeer)
586            {
587                BruteForceWithPeerToPeerSystem();
588                return null;
589            }
590
591            return BruteForceWithLocalSystem(pattern);
592        }
593
594        private Dispatcher _dispatcher;
595
596        private void BruteForceWithPeerToPeerSystem()
597        {
598            _dispatcher = Dispatcher.CurrentDispatcher;
599            GuiLogMessage("Launching p2p based bruteforce logic...", NotificationLevel.Info);
600            ValidateConnectionToPeerToPeerSystem();
601            new P2PBruteForce(this, pattern, settings, _keyQualityHelper);
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 pattern)
653        {
654            BigInteger size = pattern.size();
655            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[] 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[] splitPatternForThreads(KeyPattern pattern)
965        {
966            KeyPattern[] patterns = new KeyPattern[settings.CoresUsed + 1];
967            if (settings.CoresUsed > 0)
968            {
969                KeyPattern[] patterns2 = pattern.split();
970                if (patterns2 == null)
971                {
972                    patterns2 = new 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[] patterns3 = patterns[maxPattern].split();
991                    if (patterns3 == null)
992                    {
993                        patterns3 = new 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(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 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.