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

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

OpenCL Threadamount GuiLogMessage

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