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

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

o KeySearcher: improved visualization of local and distributed components

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