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

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

keysearcher presentation changes

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