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

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

o Fixed KeySearcher progress display
+ Work on the distributed KeySearcher part

File size: 40.4 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                throw new ApplicationException("Workaround for wrong error handling... Workspace should be stopped now.");
643            }
644        }
645
646        void HandleConnectionStateChange(object sender, bool newState)
647        {
648            _connectResetEvent.Set();
649        }
650
651        #endregion
652
653        internal LinkedList<ValueKey> BruteForceWithLocalSystem(KeyPattern pattern)
654        {
655            BigInteger size = pattern.size();
656            KeyPattern[] patterns = splitPatternForThreads(pattern);
657
658            BigInteger[] doneKeysA = new BigInteger[patterns.Length];
659            BigInteger[] keycounters = new BigInteger[patterns.Length];
660            BigInteger[] keysleft = new BigInteger[patterns.Length];
661            Stack threadStack = Stack.Synchronized(new Stack());
662            startThreads(sender, bytesToUse, patterns, doneKeysA, keycounters, keysleft, threadStack);
663
664            //update message:
665            while (!stop)
666            {
667                Thread.Sleep(1000);
668
669                updateToplist();
670
671                #region calculate global counters from local counters
672                BigInteger keycounter = 0;
673                BigInteger doneKeys = 0;
674                foreach (BigInteger dk in doneKeysA)
675                    doneKeys += dk;
676                foreach (BigInteger kc in keycounters)
677                    keycounter += kc;
678                #endregion
679
680                if (keycounter > size)
681                    GuiLogMessage("There must be an error, because we bruteforced too much keys...", NotificationLevel.Error);
682
683                #region determination of the thread with most keys
684                if (size - keycounter > 1000)
685                {
686                    try
687                    {
688                        maxThreadMutex.WaitOne();
689                        BigInteger max = 0;
690                        int id = -1;
691                        for (int i = 0; i < patterns.Length; i++)
692                            if (keysleft[i] != null && keysleft[i] > max)
693                            {
694                                max = keysleft[i];
695                                id = i;
696                            }
697                        maxThread = id;
698                    }
699                    finally
700                    {
701                        maxThreadMutex.ReleaseMutex();
702                    }
703                }
704                #endregion
705
706                showProgress(costList, size, keycounter, doneKeys);
707
708                #region set doneKeys to 0
709                doneKeys = 0;
710                for (int i = 0; i < doneKeysA.Length; i++)
711                    doneKeysA[i] = 0;
712                #endregion
713
714                if (keycounter >= size)
715                    break;
716            }//end while
717
718            //wake up all sleeping threads, so they can stop:
719            while (threadStack.Count != 0)
720                ((ThreadStackElement)threadStack.Pop()).ev.Set();
721
722            if (!stop)
723                ProgressChanged(1, 1);
724
725            /* BEGIN: For evaluation issues - added by Arnold 2010.03.17 */
726            TimeSpan bruteforcingTime = DateTime.Now.Subtract(beginBruteforcing);
727            StringBuilder sbBFTime = new StringBuilder();
728            if (bruteforcingTime.Days > 0)
729                sbBFTime.Append(bruteforcingTime.Days.ToString() + " days ");
730            if (bruteforcingTime.Hours > 0)
731            {
732                if (bruteforcingTime.Hours <= 9)
733                    sbBFTime.Append("0");
734                sbBFTime.Append(bruteforcingTime.Hours.ToString() + ":");
735            }
736            if (bruteforcingTime.Minutes <= 9)
737                sbBFTime.Append("0");
738            sbBFTime.Append(bruteforcingTime.Minutes.ToString() + ":");
739            if (bruteforcingTime.Seconds <= 9)
740                sbBFTime.Append("0");
741            sbBFTime.Append(bruteforcingTime.Seconds.ToString() + "-");
742            if (bruteforcingTime.Milliseconds <= 9)
743                sbBFTime.Append("00");
744            if (bruteforcingTime.Milliseconds <= 99)
745                sbBFTime.Append("0");
746            sbBFTime.Append(bruteforcingTime.Milliseconds.ToString());
747
748            GuiLogMessage("Ended bruteforcing pattern '" + pattern.getKey() + "'. Bruteforcing TimeSpan: " + sbBFTime.ToString(), NotificationLevel.Debug);
749            /* END: For evaluation issues - added by Arnold 2010.03.17 */
750
751            return costList;
752        }
753
754        internal void showProgress(LinkedList<ValueKey> costList, BigInteger size, BigInteger keycounter, BigInteger doneKeys)
755        {
756            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
757
758            LinkedListNode<ValueKey> linkedListNode;
759            ProgressChanged((double)keycounter / (double) size, 1.0);
760
761            if (QuickWatchPresentation.IsVisible && doneKeys != 0 && !stop)
762            {
763                double time = (Math.Pow(10, BigInteger.Log((size - keycounter), 10) - BigInteger.Log(doneKeys, 10)));
764                TimeSpan timeleft = new TimeSpan(-1);
765
766                try
767                {
768                    if (time / (24 * 60 * 60) <= int.MaxValue)
769                    {
770                        int days = (int)(time / (24 * 60 * 60));
771                        time = time - (days * 24 * 60 * 60);
772                        int hours = (int)(time / (60 * 60));
773                        time = time - (hours * 60 * 60);
774                        int minutes = (int)(time / 60);
775                        time = time - (minutes * 60);
776                        int seconds = (int)time;
777
778                        timeleft = new TimeSpan(days, hours, minutes, (int)seconds, 0);
779                    }
780                }
781                catch
782                {
783                    //can not calculate time span
784                }
785
786                ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
787                {
788                    ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).keysPerSecond.Text = "" + doneKeys;
789                    if (timeleft != new TimeSpan(-1))
790                    {
791                        ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).timeLeft.Text = "" + timeleft;
792                        try
793                        {
794                            ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).endTime.Text = "" + DateTime.Now.Add(timeleft);
795                        }
796                        catch
797                        {
798                            ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).endTime.Text = "in a galaxy far, far away...";
799                        }
800                    }
801                    else
802                    {
803                        ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).timeLeft.Text = "incalculable :-)";
804                        ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).endTime.Text = "in a galaxy far, far away...";
805                    }
806
807                    ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).entries.Clear();
808                    linkedListNode = costList.First;
809                   
810                    int i = 0;
811                    while (linkedListNode != null)
812                    {
813                        i++;
814
815                        ResultEntry entry = new ResultEntry();
816                        entry.Ranking = "" + i;
817                        entry.Value = "" + Math.Round(linkedListNode.Value.value,3);
818                        entry.Key = linkedListNode.Value.key;
819                        entry.Text = enc.GetString(linkedListNode.Value.decryption);
820
821                        ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).entries.Add(entry);
822                        linkedListNode = linkedListNode.Next;
823                    }
824                }
825                , null);
826            }//end if
827
828
829            else if (!stop && QuickWatchPresentation.IsVisible)
830            {
831
832                ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
833                {
834                    ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).entries.Clear();
835                    linkedListNode = costList.First;                   
836                    int i = 0;
837
838                    while (linkedListNode != null)
839                    {
840                        i++;
841
842                        ResultEntry entry = new ResultEntry();
843                        entry.Ranking = "" + i;
844                        entry.Value = "" + Math.Round(linkedListNode.Value.value, 3);
845                        entry.Key = linkedListNode.Value.key;
846                        entry.Text = enc.GetString(linkedListNode.Value.decryption);
847
848                        ((KeySearcherQuickWatchPresentation)QuickWatchPresentation).entries.Add(entry);
849                        linkedListNode = linkedListNode.Next;
850                    }
851                }
852                , null);
853            }
854        }
855
856        #region For TopList
857
858        private void fillListWithDummies(int maxInList, LinkedList<ValueKey> costList)
859        {
860            ValueKey valueKey = new ValueKey();
861            if (this.costMaster.getRelationOperator() == RelationOperator.LessThen)
862                valueKey.value = double.MaxValue;
863            else
864                valueKey.value = double.MinValue;
865            valueKey.key = "dummykey";
866            valueKey.decryption = new byte[0];
867            value_threshold = valueKey.value;
868            LinkedListNode<ValueKey> node = costList.AddFirst(valueKey);
869            for (int i = 1; i < maxInList; i++)
870            {
871                node = costList.AddAfter(node, valueKey);
872            }
873        }
874
875        internal void IntegrateNewResults(LinkedList<ValueKey> costList)
876        {
877            foreach (var valueKey in costList)
878            {
879                if (_keyQualityHelper.IsBetter(valueKey.value, value_threshold))
880                {
881                    valuequeue.Enqueue(valueKey);
882                }
883            }
884
885            updateToplist();
886            UpdateWithShowProgress();
887        }
888
889        internal void updateToplist()
890        {
891            LinkedListNode<ValueKey> node;
892            while (valuequeue.Count != 0)
893            {
894                ValueKey vk = (ValueKey)valuequeue.Dequeue();
895
896                //if (costList.Contains(vk)) continue;
897                var result = costList.Where(valueKey => valueKey.key == vk.key);
898                if (result.Count() > 0)
899                {
900                    continue;
901                }
902
903                if (this.costMaster.getRelationOperator() == RelationOperator.LargerThen)
904                {
905                    if (vk.value > costList.Last().value)
906                    {
907                        node = costList.First;
908                        while (node != null)
909                        {
910                            if (vk.value > node.Value.value)
911                            {
912                                if (node == costList.First)
913                                    Top1 = vk;
914                                costList.AddBefore(node, vk);
915                                costList.RemoveLast();
916                                value_threshold = costList.Last.Value.value;
917                                break;
918                            }
919                            node = node.Next;
920                        }//end while
921                    }//end if
922                }
923                else
924                {
925                    if (vk.value < costList.Last().value)
926                    {
927                        node = costList.First;
928                        while (node != null)
929                        {
930                            if (vk.value < node.Value.value)
931                            {
932                                if (node == costList.First)
933                                    Top1 = vk;
934                                costList.AddBefore(node, vk);
935                                costList.RemoveLast();
936                                value_threshold = costList.Last.Value.value;
937                                break;
938                            }
939                            node = node.Next;
940                        }//end while
941                    }//end if
942                }
943            }
944        }
945
946        private void UpdateWithShowProgress()
947        {
948            showProgress(costList, 1, 0, 0);
949        }
950
951        #endregion
952
953        private void startThreads(IControlEncryption sender, int bytesToUse, KeyPattern[] patterns, BigInteger[] doneKeysA, BigInteger[] keycounters, BigInteger[] keysleft, Stack threadStack)
954        {
955            for (int i = 0; i < patterns.Length; i++)
956            {
957                WaitCallback worker = new WaitCallback(KeySearcherJob);
958                doneKeysA[i] = new BigInteger();
959                keycounters[i] = new BigInteger();
960                //ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, keycounters, keysleft, sender.clone(), bytesToUse, threadStack });
961                ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack });
962            }
963        }
964
965        private KeyPattern[] splitPatternForThreads(KeyPattern pattern)
966        {
967            KeyPattern[] patterns = new KeyPattern[settings.CoresUsed + 1];
968            if (settings.CoresUsed > 0)
969            {
970                KeyPattern[] patterns2 = pattern.split();
971                if (patterns2 == null)
972                {
973                    patterns2 = new KeyPattern[1];
974                    patterns2[0] = pattern;
975                    return patterns2;
976                }
977                patterns[0] = patterns2[0];
978                patterns[1] = patterns2[1];
979                int p = 1;
980                int threads = settings.CoresUsed - 1;
981                while (threads > 0)
982                {
983                    int maxPattern = -1;
984                    BigInteger max = 0;
985                    for (int i = 0; i <= p; i++)
986                        if (patterns[i].size() > max)
987                        {
988                            max = patterns[i].size();
989                            maxPattern = i;
990                        }
991                    KeyPattern[] patterns3 = patterns[maxPattern].split();
992                    if (patterns3 == null)
993                    {
994                        patterns3 = new KeyPattern[p+1];
995                        for (int i = 0; i <= p; i++)
996                            patterns3[i] = patterns[i];
997                        return patterns3;
998                    }
999                    patterns[maxPattern] = patterns3[0];
1000                    patterns[++p] = patterns3[1];
1001                    threads--;
1002                }
1003            }
1004            else
1005                patterns[0] = Pattern;
1006            return patterns;
1007        }
1008
1009        private void keyPatternChanged()
1010        {
1011            Pattern = new KeyPattern(controlMaster.getKeyPattern());
1012        }
1013
1014        // added by Arnie - 2009.12.07
1015        public delegate void BruteforcingEnded(LinkedList<ValueKey> top10List);
1016        /// <summary>
1017        /// This event gets thrown after Bruteforcing had ended. This is no evidence, that bruteforcing was successful.
1018        /// But when the returned List is filled, we have (at least a part) of the possible best keys
1019        /// </summary>
1020        public event BruteforcingEnded OnBruteforcingEnded;
1021
1022        // added by Arnie -2009.12.02
1023        // for inheritance reasons
1024        public void BruteforcePattern(KeyPattern pattern, byte[] encryptedData, byte[] initVector, IControlEncryption encryptControl, IControlCost costControl)
1025        {
1026            /* Begin: New stuff because of changing the IControl data flow - Arnie 2010.01.18 */
1027            this.encryptedData = encryptedData;
1028            this.initVector = initVector;
1029            /* End: New stuff because of changing the IControl data flow - Arnie 2010.01.18 */
1030
1031            this.sender = encryptControl;
1032            LinkedList<ValueKey> lstRet = bruteforcePattern(pattern);
1033            if(OnBruteforcingEnded != null)
1034                OnBruteforcingEnded(lstRet);
1035        }
1036
1037        #endregion
1038
1039        public void GuiLogMessage(string message, NotificationLevel loglevel)
1040        {
1041            if (OnGuiLogNotificationOccured != null)
1042                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(message, this, loglevel));
1043        }
1044
1045        public void ProgressChanged(double value, double max)
1046        {
1047            if (OnPluginProgressChanged != null)
1048            {
1049                OnPluginProgressChanged(this, new PluginProgressEventArgs(value, max));
1050
1051            }
1052        }
1053
1054        /// <summary>
1055        /// used for delivering the results from the worker threads to the main thread:
1056        /// </summary>
1057        public struct ValueKey
1058        {
1059            public double value;
1060            public String key;
1061            public byte[] decryption;
1062        };
1063    }
1064
1065    /// <summary>
1066    /// Represents one entry in our result list
1067    /// </summary>
1068    public class ResultEntry
1069    {
1070        public string Ranking { get; set; }
1071        public string Value { get; set; }
1072        public string Key { get; set; }
1073        public string Text { get; set; }
1074
1075    }
1076}
Note: See TracBrowser for help on using the repository browser.