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

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

some p2p keysearcher changes (all related to better disconnect handling)

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