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

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

another opencl fix

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