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

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

KeySearcher OpenCL implementation

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