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

Last change on this file since 2091 was 2091, checked in by Sven Rech, 11 years ago

better keys/sec representation in KeySearcher

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