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

Last change on this file since 2152 was 2152, checked in by nolte, 11 years ago

Versionnumbers final version.
Use of the versionnumber starts this evening (7-8 PM).

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