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

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

fixed keysearcher (when no opencl device is available)

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