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

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

Added more Information to the Information-Statistic Tab

File size: 72.6 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.Net;
22using System.Text;
23using Cryptool.P2P;
24using Cryptool.P2P.Internal;
25using Cryptool.PluginBase.Analysis;
26using Cryptool.PluginBase;
27using System.Windows.Controls;
28using System.ComponentModel;
29using Cryptool.PluginBase.Control;
30using System.Collections;
31using System.Collections.Generic;
32using System.Threading;
33using System.Windows.Threading;
34using Cryptool.PluginBase.IO;
35using System.Numerics;
36using KeySearcher.Helper;
37using KeySearcher.KeyPattern;
38using KeySearcher.P2P;
39using KeySearcher.P2P.Exceptions;
40using KeySearcherPresentation;
41using KeySearcherPresentation.Controls;
42using KeySearcher.Properties;
43using OpenCLNet;
44
45namespace KeySearcher
46{
47    [Author("Sven Rech, Nils Kopal, Raoul Falk, Dennis Nolte", "rech@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-due.de")]
48    [PluginInfo("KeySearcher.Properties.Resources", false, "pluginName", "pluginToolTip", "KeySearcher/DetailedDescription/Description.xaml", "KeySearcher/Images/icon.png")]
49    public class KeySearcher : IAnalysisMisc
50    {
51        /// <summary>
52        /// used for creating the UserStatistics
53        /// </summary>
54        private Dictionary<string, Dictionary<long, Information>> statistic;
55        private Dictionary<long, Maschinfo> maschinehierarchie;
56        private bool initialized;
57        /// <summary>
58        /// used for creating the TopList
59        /// </summary>
60        private Queue valuequeue;
61        private double value_threshold;
62        /// <summary>
63        /// the thread with the most keys left
64        /// </summary>
65        private int maxThread;
66        private readonly Mutex maxThreadMutex = new Mutex();
67        private ArrayList threadsStopEvents;
68
69        public bool IsKeySearcherRunning;
70        private KeyQualityHelper keyQualityHelper;
71        private readonly P2PQuickWatchPresentation p2PQuickWatchPresentation;
72        private readonly LocalQuickWatchPresentation localQuickWatchPresentation;
73
74        private OpenCLManager oclManager = null;
75        private Mutex openCLPresentationMutex = new Mutex();
76
77        private readonly Stopwatch localBruteForceStopwatch;
78
79        private KeyPattern.KeyPattern pattern;
80        public KeyPattern.KeyPattern Pattern
81        {
82            get
83            {
84                return pattern;
85            }
86            set
87            {
88                pattern = value;
89                if ((settings.Key == null) || ((settings.Key != null) && !pattern.testWildcardKey(settings.Key)))
90                    settings.Key = pattern.giveInputPattern();
91            }
92        }
93
94        internal bool stop;
95
96        internal bool update;
97
98        #region IControlEncryption + IControlCost + InputFields
99
100        #region IControlEncryption Members
101
102        private IControlEncryption controlMaster;
103        [PropertyInfo(Direction.ControlMaster, "Control_Master", "ControlMasterDesc", "")]
104        public IControlEncryption ControlMaster
105        {
106            get { return controlMaster; }
107            set
108            {
109                if (controlMaster != null)
110                {
111                    controlMaster.keyPatternChanged -= keyPatternChanged;
112                }
113                if (value != null)
114                {
115                    Pattern = new KeyPattern.KeyPattern(value.getKeyPattern());
116                    value.keyPatternChanged += keyPatternChanged;
117                    controlMaster = value;
118                    OnPropertyChanged("ControlMaster");
119
120                }
121                else
122                    controlMaster = null;
123            }
124        }
125
126        #endregion
127
128        #region IControlCost Members
129
130        private IControlCost costMaster;
131        [PropertyInfo(Direction.ControlMaster, "Cost_Master", "CostMasterDesc", "")]
132        public IControlCost CostMaster
133        {
134            get { return costMaster; }
135            set
136            {
137                costMaster = value;
138                keyQualityHelper = new KeyQualityHelper(costMaster);
139            }
140        }
141
142        #endregion
143
144        /* BEGIN: following lines are from Arnie - 2010.01.12 */
145        ICryptoolStream csEncryptedData;
146        [PropertyInfo(Direction.InputData, "CS_Encrypted_Data", "csEncryptedDataDesc", "", false, false, QuickWatchFormat.Hex, "")]
147        public virtual ICryptoolStream CSEncryptedData
148        {
149            get { return this.csEncryptedData; }
150            set
151            {
152                if (value != this.csEncryptedData)
153                {
154                    this.csEncryptedData = value;
155                    this.encryptedData = GetByteFromCryptoolStream(value);
156                    OnPropertyChanged("CSEncryptedData");
157                }
158            }
159        }
160
161        byte[] encryptedData;
162        [PropertyInfo(Direction.InputData,"Encrypted_Data","EcryptedDataDesc","",false,false,QuickWatchFormat.Hex,"")]
163        public virtual byte[] EncryptedData
164        {
165            get { return this.encryptedData; }
166            set
167            {
168                if (value != this.encryptedData)
169                {
170                    this.encryptedData = value;
171                    OnPropertyChanged("EncryptedData");
172                }
173            }
174        }
175
176        /// <summary>
177        /// When the Input-Slot changed, set this variable to true, so the new Stream will be transformed to byte[]
178        /// </summary>
179        private byte[] GetByteFromCryptoolStream(ICryptoolStream cryptoolStream)
180        {
181            byte[] encryptedByteData = null;
182
183            if (cryptoolStream != null)
184            {
185                using (CStreamReader reader = cryptoolStream.CreateReader())
186                {
187                    if (reader.Length > Int32.MaxValue)
188                    throw(new Exception("CryptoolStream length is longer than the Int32.MaxValue"));
189
190                    encryptedByteData = reader.ReadFully();
191            }
192            }
193            return encryptedByteData;
194        }
195
196        byte[] initVector;
197        [PropertyInfo(Direction.InputData, "Initialization_Vector", "InitVecDesc", "")]
198        public virtual byte[] InitVector
199        {
200            get { return this.initVector; }
201            set
202            {
203                if (value != this.initVector)
204                {
205                    this.initVector = value;
206                    OnPropertyChanged("InitVector");
207                }
208            }
209        }
210        /* END: Lines above are from Arnie - 2010.01.12 */
211
212        private ValueKey top1ValueKey;
213        public virtual ValueKey Top1
214        {
215            set { top1ValueKey = value; OnPropertyChanged("Top1Message"); OnPropertyChanged("Top1Key"); }
216        }
217
218        [PropertyInfo(Direction.OutputData, "Top1_Message", "top1MesDesc", "")]
219        public virtual byte[] Top1Message
220        {
221            get { return top1ValueKey.decryption; }
222        }
223        [PropertyInfo(Direction.OutputData, "Top1_Key", "Top1KeyDesc", "")]
224        public virtual byte[] Top1Key
225        {
226            get
227            {
228                if (top1ValueKey.key != null)
229                {
230                    return top1ValueKey.keya;
231                }
232                else
233                    return null;
234            }
235        }
236
237        #endregion
238
239        #region IPlugin Members
240
241        public event StatusChangedEventHandler OnPluginStatusChanged;
242
243        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
244
245        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
246
247        private KeySearcherSettings settings;
248        private AutoResetEvent connectResetEvent;
249
250        #region external client variables
251        private CryptoolServer cryptoolServer;
252        private KeySearcherOpenCLCode externalKeySearcherOpenCLCode;
253        private IKeyTranslator externalKeyTranslator;
254        private BigInteger externalKeysProcessed;
255        /// <summary>
256        /// List of clients which connected while there was no job available. Will receive
257        /// a job a soon as one is available.
258        /// </summary>
259        private List<EndPoint> waitingExternalClients = new List<EndPoint>();
260        private Guid currentExternalJobGuid = Guid.NewGuid();
261        private AutoResetEvent waitForExternalClientToFinish = new AutoResetEvent(false);
262        private DateTime assignTime;
263        private bool externalClientJobsAvailable = false;
264        /// <summary>
265        /// id of the client which calculated the last pattern
266        /// </summary>
267        public Int64 ExternaClientId { get; private set; }
268        /// <summary>
269        /// Hostname of the client which calculated the last pattern
270        /// </summary>
271        public String ExternalClientHostname { get; private set; }
272        #endregion
273
274        public KeySearcher()
275        {
276            IsKeySearcherRunning = false;
277           
278            if (OpenCL.NumberOfPlatforms > 0)
279            {
280                oclManager = new OpenCLManager();
281                oclManager.AttemptUseBinaries = false;
282                oclManager.AttemptUseSource = true;
283                oclManager.RequireImageSupport = false;
284                var directoryName = Path.Combine(DirectoryHelper.DirectoryLocalTemp, "KeySearcher");
285                oclManager.BinaryPath = Path.Combine(directoryName, "openclbin");
286                oclManager.BuildOptions = "";
287                oclManager.CreateDefaultContext(0, DeviceType.ALL);
288            }
289
290            settings = new KeySearcherSettings(this, oclManager);
291           
292            QuickWatchPresentation = new QuickWatch();
293            localQuickWatchPresentation = ((QuickWatch) QuickWatchPresentation).LocalQuickWatchPresentation;
294            p2PQuickWatchPresentation = ((QuickWatch)QuickWatchPresentation).P2PQuickWatchPresentation;
295            p2PQuickWatchPresentation.UpdateSettings(this, settings);
296
297            settings.PropertyChanged += SettingsPropertyChanged;
298            ((QuickWatch)QuickWatchPresentation).IsOpenCLEnabled = (settings.DeviceSettings.Count(x => x.useDevice) > 0);
299
300            localBruteForceStopwatch = new Stopwatch();
301        }
302
303        void SettingsPropertyChanged(object sender, PropertyChangedEventArgs e)
304        {
305            p2PQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
306                                                             new Action(UpdateQuickwatchSettings));
307        }
308
309        void UpdateQuickwatchSettings()
310        {
311            ((QuickWatch)QuickWatchPresentation).IsP2PEnabled = settings.UsePeerToPeer;
312            ((QuickWatch)QuickWatchPresentation).IsOpenCLEnabled = (settings.DeviceSettings.Count(x => x.useDevice) > 0);
313            p2PQuickWatchPresentation.UpdateSettings(this, settings);
314        }
315
316        public ISettings Settings
317        {
318            get { return settings; }
319        }
320
321        public UserControl Presentation
322        {
323            get { return QuickWatchPresentation; }
324        }
325
326        public UserControl QuickWatchPresentation
327        {
328            get;
329            private set;
330        }
331
332        public void PreExecution()
333        {
334            update = false;
335        }
336
337        // because Encryption PlugIns were changed radical, the new StartPoint is here - Arnie 2010.01.12
338        public virtual void Execute()
339        {
340            IsKeySearcherRunning = true;
341            localBruteForceStopwatch.Reset();
342
343            //either byte[] CStream input or CryptoolStream Object input
344            if (encryptedData != null || csEncryptedData != null) //to prevent execution on initialization
345            {
346                if (ControlMaster != null)
347                    process(ControlMaster);
348                else
349                {
350                    GuiLogMessage(Resources.You_have_to_connect_the_KeySearcher_with_the_Decryption_Control_, NotificationLevel.Warning);
351                }
352            }
353        }
354
355        public void PostExecution()
356        {
357        }
358
359        public void Pause()
360        {
361        }
362
363        public void Stop()
364        {
365            IsKeySearcherRunning = false;
366            stop = true;
367            waitForExternalClientToFinish.Set();
368        }
369
370        public void Initialize()
371        {
372            settings.Initialize();
373        }
374
375        public void Dispose()
376        {
377        }
378
379        #endregion
380
381        #region INotifyPropertyChanged Members
382
383        public event PropertyChangedEventHandler PropertyChanged;
384
385        public void OnPropertyChanged(string name)
386        {
387            if (PropertyChanged != null)
388            {
389                PropertyChanged(this, new PropertyChangedEventArgs(name));
390            }
391        }
392
393        #endregion
394
395        #region whole KeySearcher functionality
396
397        private class ThreadStackElement
398        {
399            public AutoResetEvent ev;
400            public int threadid;
401        }
402
403        #region code for the worker threads
404
405        private void KeySearcherJob(object param)
406        {
407            AutoResetEvent stopEvent = new AutoResetEvent(false);
408            threadsStopEvents.Add(stopEvent);
409
410            object[] parameters = (object[])param;
411            KeyPattern.KeyPattern[] patterns = (KeyPattern.KeyPattern[])parameters[0];
412            int threadid = (int)parameters[1];
413            BigInteger[] doneKeysArray = (BigInteger[])parameters[2];
414            BigInteger[] openCLDoneKeysArray = (BigInteger[])parameters[3];
415            BigInteger[] keycounterArray = (BigInteger[])parameters[4];
416            BigInteger[] keysLeft = (BigInteger[])parameters[5];
417            IControlEncryption sender = (IControlEncryption)parameters[6];
418            int bytesToUse = (int)parameters[7];
419            Stack threadStack = (Stack)parameters[8];
420            var openCLDeviceSettings = (KeySearcherSettings.OpenCLDeviceSettings)parameters[9];
421
422            KeySearcherOpenCLCode keySearcherOpenCLCode = null;
423            KeySearcherOpenCLSubbatchOptimizer keySearcherOpenCLSubbatchOptimizer = null;
424            if (openCLDeviceSettings != null)
425            {
426                keySearcherOpenCLCode = new KeySearcherOpenCLCode(this, encryptedData, sender, CostMaster, 256 * 256 * 256 * 16);
427                keySearcherOpenCLSubbatchOptimizer = new KeySearcherOpenCLSubbatchOptimizer(openCLDeviceSettings.mode, 
428                        oclManager.CQ[openCLDeviceSettings.index].Device.MaxWorkItemSizes.Aggregate(1, (x, y) => (x * (int)y)) / 8);
429
430                ((QuickWatch)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
431                {
432                    openCLPresentationMutex.WaitOne();
433                    ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.AmountOfDevices++;
434                    openCLPresentationMutex.ReleaseMutex();
435                }, null);
436                Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
437            }
438
439            try
440            {
441                while (patterns[threadid] != null)
442                {
443                    BigInteger size = patterns[threadid].size();
444                    keysLeft[threadid] = size;
445                   
446                    IKeyTranslator keyTranslator = ControlMaster.getKeyTranslator();
447                    keyTranslator.SetKeys(patterns[threadid]);
448
449                    bool finish = false;
450
451                    do
452                    {
453                        //if we are the thread with most keys left, we have to share them:
454                        keyTranslator = ShareKeys(patterns, threadid, keysLeft, keyTranslator, threadStack);
455
456                        if (openCLDeviceSettings == null || !openCLDeviceSettings.useDevice)         //CPU
457                        {
458                            finish = BruteforceCPU(keyTranslator, sender, bytesToUse);
459                        }
460                        else                    //OpenCL
461                        {
462                            try
463                            {
464                                finish = BruteforceOpenCL(keySearcherOpenCLCode, keySearcherOpenCLSubbatchOptimizer, keyTranslator, sender, bytesToUse, parameters);
465                            }
466                            catch (Exception)
467                            {
468                                openCLDeviceSettings.useDevice = false;
469                                ((QuickWatch)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
470                                {
471                                    openCLPresentationMutex.WaitOne();
472                                    ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.AmountOfDevices--;
473                                    openCLPresentationMutex.ReleaseMutex();
474                                }, null);
475                                continue;
476                            }
477                        }
478                       
479                        int progress = keyTranslator.GetProgress();
480
481                        if (openCLDeviceSettings == null)
482                        {
483                            doneKeysArray[threadid] += progress;
484                            keycounterArray[threadid] += progress;
485                            keysLeft[threadid] -= progress;
486                        }
487
488                    } while (!finish && !stop);
489
490                    if (stop)
491                        return;
492
493                    //Let's wait until another thread is willing to share with us:
494                    WaitForNewPattern(patterns, threadid, threadStack);
495                }
496            }
497            finally
498            {
499                sender.Dispose();
500                stopEvent.Set();
501            }
502        }
503
504        private unsafe bool BruteforceOpenCL(KeySearcherOpenCLCode keySearcherOpenCLCode, KeySearcherOpenCLSubbatchOptimizer keySearcherOpenCLSubbatchOptimizer, IKeyTranslator keyTranslator, IControlEncryption sender, int bytesToUse, object[] parameters)
505        {
506            int threadid = (int)parameters[1];
507            BigInteger[] doneKeysArray = (BigInteger[])parameters[2];
508            BigInteger[] openCLDoneKeysArray = (BigInteger[])parameters[3];
509            BigInteger[] keycounterArray = (BigInteger[])parameters[4];
510            BigInteger[] keysLeft = (BigInteger[])parameters[5];
511            var openCLDeviceSettings = (KeySearcherSettings.OpenCLDeviceSettings)parameters[9];
512            try
513            {
514                Kernel bruteforceKernel = keySearcherOpenCLCode.GetBruteforceKernel(oclManager, keyTranslator);
515
516                int deviceIndex = openCLDeviceSettings.index;
517               
518                Mem userKey;
519                var key = keyTranslator.GetKey();
520                fixed (byte* ukp = key)
521                    userKey = oclManager.Context.CreateBuffer(MemFlags.USE_HOST_PTR, key.Length, new IntPtr((void*)ukp));
522
523                int subbatches = keySearcherOpenCLSubbatchOptimizer.GetAmountOfSubbatches(keyTranslator);
524                int subbatchSize = keyTranslator.GetOpenCLBatchSize() / subbatches;
525                ((QuickWatch) QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback) delegate
526                                                                    {
527                                                                        ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.workItems.Content = subbatchSize;
528                                                                    }, null);
529                //GuiLogMessage(string.Format("Now using {0} subbatches", subbatches), NotificationLevel.Info);
530               
531                float[] costArray = new float[subbatchSize];
532                Mem costs = oclManager.Context.CreateBuffer(MemFlags.READ_WRITE, costArray.Length * 4);
533
534                IntPtr[] globalWorkSize = { (IntPtr)subbatchSize, (IntPtr)1, (IntPtr)1 };
535
536                keySearcherOpenCLSubbatchOptimizer.BeginMeasurement();
537
538                try
539                {
540                    for (int i = 0; i < subbatches; i++)
541                    {
542                        bruteforceKernel.SetArg(0, userKey);
543                        bruteforceKernel.SetArg(1, costs);
544                        bruteforceKernel.SetArg(2, i * subbatchSize);
545                        oclManager.CQ[deviceIndex].EnqueueNDRangeKernel(bruteforceKernel, 3, null, globalWorkSize, null);
546                        oclManager.CQ[deviceIndex].EnqueueBarrier();
547
548                        Event e;
549                        fixed (float* costa = costArray)
550                            oclManager.CQ[deviceIndex].EnqueueReadBuffer(costs, true, 0, costArray.Length * 4, new IntPtr((void*)costa), 0, null, out e);
551
552                        e.Wait();
553
554                        checkOpenCLResults(keyTranslator, costArray, sender, bytesToUse, i * subbatchSize);
555
556                        doneKeysArray[threadid] += subbatchSize;
557                        openCLDoneKeysArray[threadid] += subbatchSize;
558                        keycounterArray[threadid] += subbatchSize;
559                        keysLeft[threadid] -= subbatchSize;
560
561                        if (stop)
562                            return false;
563                    }
564
565                    keySearcherOpenCLSubbatchOptimizer.EndMeasurement();
566                }
567                finally
568                {
569                    costs.Dispose();
570                }
571            }
572            catch (Exception ex)
573            {
574                GuiLogMessage(ex.Message, NotificationLevel.Error);
575                GuiLogMessage("Bruteforcing with OpenCL failed! Using CPU instead.", NotificationLevel.Error);
576                throw new Exception("Bruteforcing with OpenCL failed!");
577            }
578
579            return !keyTranslator.NextOpenCLBatch();
580        }
581
582        private void checkOpenCLResults(IKeyTranslator keyTranslator, float[] costArray, IControlEncryption sender, int bytesToUse, int add)
583        {
584            var op = this.costMaster.getRelationOperator();
585            for (int i = 0; i < costArray.Length; i++)
586            {
587                float cost = costArray[i];
588                if (((op == RelationOperator.LargerThen) && (cost > value_threshold))
589                    || (op == RelationOperator.LessThen) && (cost < value_threshold))
590                {
591                    ValueKey valueKey = new ValueKey { value = cost, key = keyTranslator.GetKeyRepresentation(i + add) };
592                    valueKey.keya = keyTranslator.GetKeyFromRepresentation(valueKey.key);
593                    valueKey.decryption = sender.Decrypt(this.encryptedData, valueKey.keya, InitVector, bytesToUse);
594                    EnhanceUserName(ref valueKey);
595                    valuequeue.Enqueue(valueKey);
596                }
597            }
598        }
599
600        private bool BruteforceCPU(IKeyTranslator keyTranslator, IControlEncryption sender, int bytesToUse)
601        {
602            bool finish = false;
603            for (int count = 0; count < 256 * 256; count++)
604            {
605                byte[] keya = keyTranslator.GetKey();
606
607                if (!decryptAndCalculate(sender, bytesToUse, keya, keyTranslator))
608                    throw new Exception("Bruteforcing not possible!");
609
610                finish = !keyTranslator.NextKey();
611                if (finish)
612                    break;
613            }
614            return finish;
615        }
616
617        private IKeyTranslator ShareKeys(KeyPattern.KeyPattern[] patterns, int threadid, BigInteger[] keysLeft, IKeyTranslator keyTranslator, Stack threadStack)
618        {
619            BigInteger size;
620            if (maxThread == threadid && threadStack.Count != 0)
621            {
622                try
623                {
624                    maxThreadMutex.WaitOne();
625                    if (maxThread == threadid && threadStack.Count != 0)
626                    {
627                        KeyPattern.KeyPattern[] split = patterns[threadid].split();
628                        if (split != null)
629                        {
630                            patterns[threadid] = split[0];
631                            keyTranslator = ControlMaster.getKeyTranslator();
632                            keyTranslator.SetKeys(patterns[threadid]);
633
634                            ThreadStackElement elem = (ThreadStackElement)threadStack.Pop();
635                            patterns[elem.threadid] = split[1];
636                            elem.ev.Set();    //wake the other thread up                                   
637                            size = patterns[threadid].size();
638                            keysLeft[threadid] = size;
639                        }
640                        maxThread = -1;
641                    }
642                }
643                finally
644                {
645                    maxThreadMutex.ReleaseMutex();
646                }
647            }
648            return keyTranslator;
649        }
650
651        private void WaitForNewPattern(KeyPattern.KeyPattern[] patterns, int threadid, Stack threadStack)
652        {
653            ThreadStackElement el = new ThreadStackElement();
654            el.ev = new AutoResetEvent(false);
655            el.threadid = threadid;
656            patterns[threadid] = null;
657            threadStack.Push(el);
658            GuiLogMessage("Thread waiting for new keys.", NotificationLevel.Debug);
659            el.ev.WaitOne();
660            if (!stop)
661            {
662                GuiLogMessage("Thread waking up with new keys.", NotificationLevel.Debug);
663            }
664        }
665
666        #region bruteforce methods
667
668        private bool decryptAndCalculate(IControlEncryption sender, int bytesToUse, byte[] keya, IKeyTranslator keyTranslator)
669        {
670            ValueKey valueKey = new ValueKey();
671
672            try
673            {
674                if (this.encryptedData != null && this.encryptedData.Length > 0)
675                {
676                    valueKey.decryption = sender.Decrypt(this.encryptedData, keya, InitVector, bytesToUse);
677                }
678                else
679                {
680                    GuiLogMessage("Can't bruteforce empty input!", NotificationLevel.Error);
681                    return false;
682                }
683            }
684            catch (Exception ex)
685            {
686                GuiLogMessage("Decryption is not possible: " + ex.Message, NotificationLevel.Error);
687                GuiLogMessage("Stack Trace: " + ex.StackTrace, NotificationLevel.Error);
688                return false;
689            }
690
691            try
692            {
693                valueKey.value = CostMaster.calculateCost(valueKey.decryption);
694            }
695            catch (Exception ex)
696            {
697                GuiLogMessage("Cost calculation is not possible: " + ex.Message, NotificationLevel.Error);
698                return false;
699            }
700
701            if (this.costMaster.getRelationOperator() == RelationOperator.LargerThen)
702            {
703                if (valueKey.value > value_threshold)
704                {
705                    valueKey.key = keyTranslator.GetKeyRepresentation();
706                    valueKey.keya = (byte[])keya.Clone();
707                    EnhanceUserName(ref valueKey);
708                    valuequeue.Enqueue(valueKey);
709                }
710            }
711            else
712            {
713                if (valueKey.value < value_threshold)
714                {
715                    valueKey.key = keyTranslator.GetKeyRepresentation();
716                    valueKey.keya = (byte[])keya.Clone();
717                    EnhanceUserName(ref valueKey);
718                    valuequeue.Enqueue(valueKey);
719                }
720            }
721            return true;
722        }
723
724        #endregion
725
726        #endregion
727
728        public void process(IControlEncryption sender)
729        {
730            if (sender == null || costMaster == null)
731                return;
732            if (!Pattern.testWildcardKey(settings.Key))
733            {
734                GuiLogMessage("Wrong key pattern!", NotificationLevel.Error);
735                return;
736            }
737            Pattern.WildcardKey = settings.Key;
738            this.sender = sender;
739
740            bruteforcePattern(Pattern);
741        }
742
743        internal LinkedList<ValueKey> costList = new LinkedList<ValueKey>();
744        private int bytesToUse;
745        private IControlEncryption sender;
746        private DateTime beginBruteforcing;
747        private DistributedBruteForceManager distributedBruteForceManager;
748        private BigInteger keysInThisChunk;
749
750        // main entry point to the KeySearcher
751        private LinkedList<ValueKey> bruteforcePattern(KeyPattern.KeyPattern pattern)
752        {
753            beginBruteforcing = DateTime.Now;
754            GuiLogMessage(Resources.Start_bruteforcing_pattern__ + pattern.getKey() + "'", NotificationLevel.Debug);
755                       
756            int maxInList = 10;
757            costList = new LinkedList<ValueKey>();
758            FillListWithDummies(maxInList, costList);
759            valuequeue = Queue.Synchronized(new Queue());
760
761            statistic = new Dictionary<string, Dictionary<long, Information>>();
762            maschinehierarchie = new Dictionary<long, Maschinfo>();
763            initialized = false;
764
765            stop = false;
766            if (!pattern.testWildcardKey(settings.Key))
767            {
768                GuiLogMessage(Resources.Wrong_key_pattern_, NotificationLevel.Error);
769                return null;
770            }
771
772            // bytesToUse = 0;
773
774            try
775            {
776                bytesToUse = CostMaster.getBytesToUse();
777            }
778            catch (Exception ex)
779            {
780                GuiLogMessage(Resources.Bytes_used_not_valid__ + ex.Message, NotificationLevel.Error);
781                return null;
782            }
783
784            Thread serverThread = null;
785            try
786            {
787                if (settings.UseExternalClient)
788                {
789                    GuiLogMessage(Resources.Waiting_for_external_client_, NotificationLevel.Info);
790                    if (cryptoolServer != null)
791                    {
792
793                    }
794                    cryptoolServer = new CryptoolServer();
795                    waitingExternalClients.Clear();
796                    cryptoolServer.Port = settings.Port;
797                    cryptoolServer.OnJobCompleted += cryptoolServer_OnJobCompleted;
798                    cryptoolServer.OnClientAuth = cryptoolServer_OnClientAuth;
799                    cryptoolServer.OnClientDisconnected += cryptoolServer_OnClientDisconnected;
800                    cryptoolServer.OnClientRequestedJob += cryptoolServer_OnClientRequestedJob;
801                    cryptoolServer.OnErrorLog += cryptoolServer_OnErrorLog;
802                    serverThread = new Thread(new ThreadStart(delegate
803                                                                      {
804                                                                          cryptoolServer.Run();
805                                                                      }));
806                    serverThread.Start();
807                }
808
809                if (settings.UsePeerToPeer)
810                {
811                    BruteForceWithPeerToPeerSystem();
812                    return null;
813                }
814
815                return BruteForceWithLocalSystem(pattern);
816            }
817            finally
818            {
819                if (serverThread != null)
820                {
821                    //stop server here!
822                    cryptoolServer.Shutdown();
823                    cryptoolServer.OnJobCompleted -= cryptoolServer_OnJobCompleted;
824                    cryptoolServer.OnClientAuth = null;
825                    cryptoolServer.OnClientDisconnected -= cryptoolServer_OnClientDisconnected;
826                    cryptoolServer.OnClientRequestedJob -= cryptoolServer_OnClientRequestedJob;
827                    cryptoolServer.OnErrorLog -= cryptoolServer_OnErrorLog;
828                }
829            }
830        }
831
832        private void BruteForceWithPeerToPeerSystem()
833        {
834            if (!update)
835            {
836                GuiLogMessage(Resources.Launching_p2p_based_bruteforce_logic___, NotificationLevel.Info);
837
838                try
839                {
840                    distributedBruteForceManager = new DistributedBruteForceManager(this, pattern, settings,
841                                                                                    keyQualityHelper,
842                                                                                    p2PQuickWatchPresentation);
843                    distributedBruteForceManager.Execute();
844                }
845                catch (NotConnectedException)
846                {
847                    GuiLogMessage(Resources.P2P_not_connected_, NotificationLevel.Error);
848                }
849                catch (KeySearcherStopException)
850                {
851                    update = true;
852                    return;
853                }
854            }
855            else
856            {
857                GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Error);
858                Thread.Sleep(3000);
859            }
860        }
861
862        internal LinkedList<ValueKey> BruteForceWithLocalSystem(KeyPattern.KeyPattern pattern, bool redirectResultsToStatisticsGenerator = false)
863        {
864            ((QuickWatch)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
865            {
866                openCLPresentationMutex.WaitOne();
867                ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.AmountOfDevices = 0;
868                openCLPresentationMutex.ReleaseMutex();
869            }, null);
870
871            if (!redirectResultsToStatisticsGenerator)
872            {
873                localQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(SetStartDate));
874                localBruteForceStopwatch.Start();
875            }
876
877            keysInThisChunk = pattern.size();
878
879            if (settings.UseExternalClient)
880            {
881                GuiLogMessage(Resources.Only_using_external_client_to_bruteforce_, NotificationLevel.Info);
882                lock (this)
883                {
884                    externalKeySearcherOpenCLCode = new KeySearcherOpenCLCode(this, encryptedData, sender, CostMaster,
885                                                                              256*256*256*64);
886                    externalKeysProcessed = 0;
887                    externalKeyTranslator = ControlMaster.getKeyTranslator();
888                    externalKeyTranslator.SetKeys(pattern);
889                    currentExternalJobGuid = Guid.NewGuid();
890                    foreach (var client in waitingExternalClients)
891                    {
892                        AssignJobToClient(client, externalKeySearcherOpenCLCode.CreateOpenCLBruteForceCode(externalKeyTranslator));
893                    }
894                    waitingExternalClients.Clear();
895                    externalClientJobsAvailable = true;
896                }
897                waitForExternalClientToFinish.Reset();
898                waitForExternalClientToFinish.WaitOne();
899                lock (this)
900                {
901                    externalClientJobsAvailable = false;
902                }
903            }
904            else
905            {
906                KeyPattern.KeyPattern[] patterns = splitPatternForThreads(pattern);
907                if (patterns == null || patterns.Length == 0)
908                {
909                    GuiLogMessage(Resources.No_ressources_to_BruteForce_available__Check_the_KeySearcher_settings_, NotificationLevel.Error);
910                    throw new Exception("No ressources to BruteForce available. Check the KeySearcher settings!");
911                }
912
913                BigInteger[] doneKeysA = new BigInteger[patterns.Length];
914                BigInteger[] openCLDoneKeysA = new BigInteger[patterns.Length];
915                BigInteger[] keycounters = new BigInteger[patterns.Length];
916                BigInteger[] keysleft = new BigInteger[patterns.Length];
917                Stack threadStack = Stack.Synchronized(new Stack());
918                threadsStopEvents = ArrayList.Synchronized(new ArrayList());
919                StartThreads(sender, bytesToUse, patterns, doneKeysA, openCLDoneKeysA, keycounters, keysleft, threadStack);
920
921                DateTime lastTime = DateTime.Now;
922
923                //update message:
924                while (!stop)
925                {
926                    Thread.Sleep(2000);
927
928                    updateToplist();
929
930                    #region calculate global counters from local counters
931                    BigInteger keycounter = 0;
932                    BigInteger doneKeys = 0;
933                    BigInteger openCLdoneKeys = 0;
934                    foreach (BigInteger dk in doneKeysA)
935                        doneKeys += dk;
936                    foreach (BigInteger dk in openCLDoneKeysA)
937                        openCLdoneKeys += dk;
938                    foreach (BigInteger kc in keycounters)
939                        keycounter += kc;
940                    #endregion
941
942                    if (keycounter > keysInThisChunk)
943                        GuiLogMessage(Resources.There_must_be_an_error__because_we_bruteforced_too_much_keys___, NotificationLevel.Error);
944
945                    #region determination of the thread with most keys
946                    if (keysInThisChunk - keycounter > 1000)
947                    {
948                        try
949                        {
950                            maxThreadMutex.WaitOne();
951                            BigInteger max = 0;
952                            int id = -1;
953                            for (int i = 0; i < patterns.Length; i++)
954                                if (keysleft[i] != null && keysleft[i] > max)
955                                {
956                                    max = keysleft[i];
957                                    id = i;
958                                }
959                            maxThread = id;
960                        }
961                        finally
962                        {
963                            maxThreadMutex.ReleaseMutex();
964                        }
965                    }
966                    #endregion
967
968                    long keysPerSecond = (long)((long)doneKeys / (DateTime.Now - lastTime).TotalSeconds);
969                    long openCLKeysPerSecond = (long)((long)openCLdoneKeys / (DateTime.Now - lastTime).TotalSeconds);
970                    lastTime = DateTime.Now;
971                    if (redirectResultsToStatisticsGenerator)
972                    {
973                        distributedBruteForceManager.StatisticsGenerator.ShowProgress(costList, keysInThisChunk, keycounter, keysPerSecond);
974                    }
975                    else
976                    {
977                        showProgress(costList, keysInThisChunk, keycounter, keysPerSecond);
978                    }
979
980                    //show OpenCL keys/sec:
981                    var ratio = (double)openCLdoneKeys / (double)doneKeys;
982                    ((QuickWatch)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
983                    {
984                        ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.keysPerSecondOpenCL.Content = String.Format("{0:N}", openCLKeysPerSecond);
985                        ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.keysPerSecondCPU.Content = String.Format("{0:N}", (keysPerSecond - openCLKeysPerSecond));
986                        ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.ratio.Content = String.Format("{0:P}", ratio);
987                    }, null);
988
989
990                    #region set doneKeys to 0
991                    doneKeys = 0;
992                    for (int i = 0; i < doneKeysA.Length; i++)
993                        doneKeysA[i] = 0;
994                    openCLdoneKeys = 0;
995                    for (int i = 0; i < openCLDoneKeysA.Length; i++)
996                        openCLDoneKeysA[i] = 0;
997                    #endregion
998
999                    if (keycounter >= keysInThisChunk)
1000                        break;
1001                }//end while
1002
1003                showProgress(costList, 1, 1, 1);
1004
1005                //wake up all sleeping threads, so they can stop:
1006                while (threadStack.Count != 0)
1007                    ((ThreadStackElement)threadStack.Pop()).ev.Set();
1008
1009                //wait until all threads finished:
1010                foreach (AutoResetEvent stopEvent in threadsStopEvents)
1011                {
1012                    stopEvent.WaitOne();
1013                }
1014
1015                if (!stop && !redirectResultsToStatisticsGenerator)
1016                    ProgressChanged(1, 1);
1017
1018            }
1019
1020            /* BEGIN: For evaluation issues - added by Arnold 2010.03.17 */
1021            TimeSpan bruteforcingTime = DateTime.Now.Subtract(beginBruteforcing);
1022            StringBuilder sbBFTime = new StringBuilder();
1023            if (bruteforcingTime.Days > 0)
1024                sbBFTime.Append(bruteforcingTime.Days.ToString() + Resources._days_);
1025            if (bruteforcingTime.Hours > 0)
1026            {
1027                if (bruteforcingTime.Hours <= 9)
1028                    sbBFTime.Append("0");
1029                sbBFTime.Append(bruteforcingTime.Hours.ToString() + ":");
1030            }
1031            if (bruteforcingTime.Minutes <= 9)
1032                sbBFTime.Append("0");
1033            sbBFTime.Append(bruteforcingTime.Minutes.ToString() + ":");
1034            if (bruteforcingTime.Seconds <= 9)
1035                sbBFTime.Append("0");
1036            sbBFTime.Append(bruteforcingTime.Seconds.ToString() + "-");
1037            if (bruteforcingTime.Milliseconds <= 9)
1038                sbBFTime.Append("00");
1039            if (bruteforcingTime.Milliseconds <= 99)
1040                sbBFTime.Append("0");
1041            sbBFTime.Append(bruteforcingTime.Milliseconds.ToString());
1042
1043            GuiLogMessage(Resources.Ended_bruteforcing_pattern__ + pattern.getKey() + Resources.___Bruteforcing_TimeSpan__ + sbBFTime.ToString(), NotificationLevel.Debug);
1044            /* END: For evaluation issues - added by Arnold 2010.03.17 */
1045
1046            return costList;
1047        }
1048
1049        #region External Client
1050
1051        void cryptoolServer_OnClientDisconnected(EndPoint client)
1052        {
1053            GuiLogMessage(Resources.Client_disconnected_, NotificationLevel.Info);
1054            lock (this)
1055            {
1056                waitingExternalClients.Remove(client);
1057            }
1058        }
1059
1060        bool cryptoolServer_OnClientAuth(System.Net.EndPoint client, string name, string password)
1061        {
1062            if(settings.ExternalClientPassword.Length == 0 ||
1063                settings.ExternalClientPassword == password)
1064            {
1065                GuiLogMessage(string.Format(Resources.Client__0__connected_, name), NotificationLevel.Info);
1066                return true;
1067            }
1068            GuiLogMessage(string.Format(Resources.Client__0__tried_to_auth_with_invalid_password, name), NotificationLevel.Info);
1069            return false;
1070        }
1071
1072        private void AssignJobToClient(EndPoint client, string src)
1073        {
1074            JobInput j = new JobInput();
1075            j.Guid = currentExternalJobGuid.ToString();
1076            j.Src = src;
1077            var key = externalKeyTranslator.GetKey();
1078            j.Key = key;
1079            j.LargerThen = (costMaster.getRelationOperator() == RelationOperator.LargerThen);
1080            j.Size = externalKeyTranslator.GetOpenCLBatchSize();
1081            j.ResultSize = 10;
1082            GuiLogMessage(string.Format(Resources.Assigning_new_job_with_Guid__0__to_client_, j.Guid), NotificationLevel.Info);
1083            cryptoolServer.SendJob(j, client);
1084            assignTime = DateTime.Now;
1085        }
1086
1087        void cryptoolServer_OnJobCompleted(System.Net.EndPoint client, JobResult jr, String clientName)
1088        {
1089            GuiLogMessage(string.Format(Resources.Client_returned_result_of_job_with_Guid__0__, jr.Guid), NotificationLevel.Info);
1090            lock (this)
1091            {
1092                if (!jr.Guid.Equals(currentExternalJobGuid.ToString()))
1093                {
1094                    GuiLogMessage(string.Format(Resources.Received_late_job_result_0_from_client_1, jr.Guid, client), NotificationLevel.Warning);
1095                    return;
1096                }
1097
1098                // Set new guid. Will prevent concurrent clients
1099                // from supplying old results for new chunks.
1100                currentExternalJobGuid = Guid.NewGuid();
1101            }
1102
1103            Int64 id = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID(clientName);
1104            String hostname = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetHostName() + "/" + clientName;
1105
1106            ExternalClientHostname = hostname;
1107            ExternaClientId = id;
1108
1109            //check:
1110            var op = this.costMaster.getRelationOperator();
1111            foreach (var res in jr.ResultList)
1112            {
1113                float cost = res.Key;
1114                if (((op == RelationOperator.LargerThen) && (cost > value_threshold))
1115                    || (op == RelationOperator.LessThen) && (cost < value_threshold))
1116                {
1117                    ValueKey valueKey = new ValueKey { value = cost, key = externalKeyTranslator.GetKeyRepresentation(res.Value) };
1118                    valueKey.keya = externalKeyTranslator.GetKeyFromRepresentation(valueKey.key);
1119                    valueKey.decryption = sender.Decrypt(this.encryptedData, valueKey.keya, InitVector, bytesToUse);
1120
1121                    EnhanceUserName(ref valueKey);
1122
1123                    // special treatment for external client
1124                    valueKey.maschid = id;
1125                    valueKey.maschname = hostname;
1126
1127                    valuequeue.Enqueue(valueKey);
1128                }
1129            }
1130            updateToplist();
1131
1132            //progress:
1133            externalKeyTranslator.NextOpenCLBatch();
1134            int progress = externalKeyTranslator.GetProgress();
1135            externalKeysProcessed += progress;
1136            int keysPerSec = (int)(progress / (DateTime.Now - assignTime).TotalSeconds);
1137
1138            QuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1139                                                                                    {
1140                                                                                        if (!((QuickWatch)QuickWatchPresentation).IsP2PEnabled)
1141                                                                                            showProgress(costList, keysInThisChunk, externalKeysProcessed, keysPerSec);
1142                                                                                        else
1143                                                                                            distributedBruteForceManager.StatisticsGenerator.ShowProgress(costList,
1144                                                                                                             keysInThisChunk, externalKeysProcessed, keysPerSec);
1145                                                                                    }, null);
1146
1147            if (externalKeysProcessed == keysInThisChunk)
1148            {
1149                waitForExternalClientToFinish.Set();
1150                lock (this)
1151                {
1152                    externalClientJobsAvailable = false;
1153                }
1154            }
1155        }
1156
1157        void cryptoolServer_OnErrorLog(string str)
1158        {
1159            GuiLogMessage(str, NotificationLevel.Error);
1160        }
1161
1162        void cryptoolServer_OnClientRequestedJob(EndPoint ipep)
1163        {
1164            lock (this)
1165            {
1166                if(externalClientJobsAvailable)
1167                {
1168                    AssignJobToClient(ipep, externalKeySearcherOpenCLCode.CreateOpenCLBruteForceCode(externalKeyTranslator));
1169                }
1170                else
1171                {
1172                    waitingExternalClients.Add(ipep);
1173                }
1174            }
1175       
1176        }
1177
1178        #endregion
1179
1180        private void SetStartDate()
1181        {
1182            localQuickWatchPresentation.startTime.Content = DateTime.Now.ToString("g", Thread.CurrentThread.CurrentCulture); ;
1183        }
1184
1185        internal void showProgress(LinkedList<ValueKey> costList, BigInteger size, BigInteger keycounter, long keysPerSecond)
1186        {
1187            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
1188
1189            LinkedListNode<ValueKey> linkedListNode;
1190            ProgressChanged((double)keycounter / (double)size, 1.0);
1191
1192            if (localQuickWatchPresentation.IsVisible && keysPerSecond != 0 && !stop)
1193            {
1194                double time = (Math.Pow(10, BigInteger.Log((size - keycounter), 10) - Math.Log10(keysPerSecond)));
1195                TimeSpan timeleft = new TimeSpan(-1);
1196
1197                try
1198                {
1199                    if (time / (24 * 60 * 60) <= int.MaxValue)
1200                    {
1201                        int days = (int)(time / (24 * 60 * 60));
1202                        time = time - (days * 24 * 60 * 60);
1203                        int hours = (int)(time / (60 * 60));
1204                        time = time - (hours * 60 * 60);
1205                        int minutes = (int)(time / 60);
1206                        time = time - (minutes * 60);
1207                        int seconds = (int)time;
1208
1209                        timeleft = new TimeSpan(days, hours, minutes, (int)seconds, 0);
1210                    }
1211                }
1212                catch
1213                {
1214                    //can not calculate time span
1215                }
1216
1217                localQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1218                {
1219                    localQuickWatchPresentation.elapsedTime.Content = localBruteForceStopwatch.Elapsed;
1220                    localQuickWatchPresentation.keysPerSecond.Content = String.Format("{0:0,0}", keysPerSecond);
1221                    if (timeleft != new TimeSpan(-1))
1222                    {
1223                        localQuickWatchPresentation.timeLeft.Content = "" + timeleft;
1224                        try
1225                        {
1226                            localQuickWatchPresentation.endTime.Content = "" + DateTime.Now.Add(timeleft);
1227                        }
1228                        catch
1229                        {
1230                            localQuickWatchPresentation.endTime.Content = Resources.in_a_galaxy_far__far_away___;
1231                        }
1232                    }
1233                    else
1234                    {
1235                        localQuickWatchPresentation.timeLeft.Content = Resources.incalculable____;
1236                        localQuickWatchPresentation.endTime.Content = Resources.in_a_galaxy_far__far_away___;
1237                    }
1238
1239                    localQuickWatchPresentation.entries.Clear();
1240                    linkedListNode = costList.First;
1241
1242                    int i = 0;
1243                    while (linkedListNode != null)
1244                    {
1245                        i++;
1246
1247                        ResultEntry entry = new ResultEntry();
1248                        entry.Ranking = "" + i;
1249                        entry.Value = "" + Math.Round(linkedListNode.Value.value, 3);
1250                        entry.Key = linkedListNode.Value.key;
1251                        entry.Text = enc.GetString(linkedListNode.Value.decryption);
1252
1253                        localQuickWatchPresentation.entries.Add(entry);
1254                        linkedListNode = linkedListNode.Next;
1255                    }
1256                }
1257                , null);
1258            }//end if
1259            else if (!stop && localQuickWatchPresentation.IsVisible)
1260            {
1261
1262                localQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1263                {
1264                    localQuickWatchPresentation.entries.Clear();
1265                    linkedListNode = costList.First;
1266                    int i = 0;
1267
1268                    while (linkedListNode != null)
1269                    {
1270                        i++;
1271
1272                        ResultEntry entry = new ResultEntry();
1273                        entry.Ranking = "" + i;
1274                        entry.Value = "" + Math.Round(linkedListNode.Value.value, 3);
1275                        entry.Key = linkedListNode.Value.key;
1276                        entry.Text = enc.GetString(linkedListNode.Value.decryption);
1277
1278                        localQuickWatchPresentation.entries.Add(entry);
1279                        linkedListNode = linkedListNode.Next;
1280                    }
1281                }
1282                , null);
1283            }
1284        }
1285
1286        #region For TopList
1287
1288        private void FillListWithDummies(int maxInList, LinkedList<ValueKey> costList)
1289        {
1290            ValueKey valueKey = new ValueKey();
1291            if (this.costMaster.getRelationOperator() == RelationOperator.LessThen)
1292                valueKey.value = double.MaxValue;
1293            else
1294                valueKey.value = double.MinValue;
1295            valueKey.key = Resources.dummykey;
1296            valueKey.decryption = new byte[0];
1297            value_threshold = valueKey.value;
1298            LinkedListNode<ValueKey> node = costList.AddFirst(valueKey);
1299            for (int i = 1; i < maxInList; i++)
1300            {
1301                node = costList.AddAfter(node, valueKey);
1302            }
1303        }
1304
1305        public void SetInitialized(bool ini)
1306        {
1307            this.initialized = ini;
1308        }
1309
1310        public Dictionary<string, Dictionary<long, Information>> GetStatistics()
1311        {
1312            return statistic;
1313        }
1314
1315        private DateTime startDate;
1316        public void SetBeginningDate(DateTime sd)
1317        {
1318            startDate = sd;
1319        }
1320
1321        public void ResetStatistics()
1322        {
1323            statistic = null;
1324            statistic = new Dictionary<string, Dictionary<long, Information>>();
1325            maschinehierarchie = null;
1326            maschinehierarchie = new Dictionary<long, Maschinfo>();
1327        }
1328
1329        public void InitialiseInformationQuickwatch()
1330        {
1331            if (Pattern == null || !Pattern.testWildcardKey(settings.Key) || settings.ChunkSize == 0)
1332            {
1333                return;
1334            }
1335
1336            var keyPattern = Pattern;
1337            var keysPerChunk = Math.Pow(2, settings.ChunkSize);
1338            var keyPatternPool = new KeyPatternPool(keyPattern, new BigInteger(keysPerChunk));
1339
1340            ((QuickWatch) QuickWatchPresentation).StatisticsPresentation.TotalBlocks = keyPatternPool.Length;
1341            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.TotalKeys = new BigInteger(keysPerChunk) * keyPatternPool.Length;   
1342            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Days = DateTime.UtcNow.Subtract(startDate).Days + " Days";
1343            UpdateStatisticsPresentation();
1344        }
1345
1346        internal void IntegrateNewResults(LinkedList<ValueKey> updatedCostList, Dictionary<string, Dictionary<long, Information>> updatedStatistics, string dataIdentifier)
1347        {
1348            foreach (var valueKey in updatedCostList)
1349            {
1350                if (keyQualityHelper.IsBetter(valueKey.value, value_threshold))
1351                {
1352                    valuequeue.Enqueue(valueKey);
1353                }
1354            }
1355
1356            foreach (string avname in updatedStatistics.Keys)
1357            {
1358                //taking the dictionary in this avatarname
1359                Dictionary<long, Information> MaschCount = updatedStatistics[avname];
1360               
1361                //if the avatarname already exists in the statistics
1362                if (statistic.ContainsKey(avname))
1363                {
1364                    foreach (long id in MaschCount.Keys)
1365                    {
1366                        //get the statistic maschcount for this avatarname
1367                        Dictionary<long, Information> statMaschCount = statistic[avname];
1368
1369                        //if the id of the Maschine already exists for this avatarname
1370                        if (statMaschCount.ContainsKey(id))
1371                        {
1372                            if (!initialized || ((MaschCount[id].Count == 1) && (MaschCount.Keys.Count == 1)))
1373                            {
1374                                statMaschCount[id].Count = statMaschCount[id].Count + MaschCount[id].Count;
1375                                statMaschCount[id].Hostname = MaschCount[id].Hostname;
1376                                statMaschCount[id].Date = MaschCount[id].Date;
1377                                statistic[avname] = statMaschCount;
1378                            }
1379                        }
1380                        else
1381                        {
1382                            //add a new id,information value for this avatarname
1383                            statistic[avname].Add(id, MaschCount[id]);
1384                        }
1385                    }
1386                }
1387                else
1388                {
1389                    //add the maschinecount dictionary to this avatarname
1390                    statistic[avname] = MaschCount;
1391                }
1392                statistic[avname] = statistic[avname].OrderByDescending((x) => x.Value.Count).ToDictionary(x => x.Key, y => y.Value);
1393            }
1394            GenerateMaschineStats();
1395            //The following Method can be used to write a local csv file with the User/Maschine Statistics.
1396            //WriteStatistics(dataIdentifier);
1397            UpdateStatisticsPresentation();
1398           
1399            updateToplist();
1400        }
1401
1402        //Update the Statistic Presentation
1403        internal void UpdateStatisticsPresentation()
1404        {
1405            var calcChunks = calculatedChunks();
1406            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Statistics = statistic;
1407            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.MachineHierarchy = maschinehierarchie;
1408            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Days = DateTime.UtcNow.Subtract(startDate).Days + " Days";
1409            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.CalculatedBlocks = calcChunks;
1410            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.CalculatedKeys = calcChunks * (BigInteger)Math.Pow(2, settings.ChunkSize);
1411            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Percent = (double)calcChunks;
1412            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Users = statistic.Keys.Count;
1413            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Machines = maschinehierarchie.Keys.Count;
1414            if (statistic.Count > 0)
1415            {
1416                ((QuickWatch) QuickWatchPresentation).StatisticsPresentation.BeeUsers = statistic.Keys.First();
1417                ((QuickWatch) QuickWatchPresentation).StatisticsPresentation.BeeMachines = maschinehierarchie[maschinehierarchie.Keys.First()].Hostname;
1418            }
1419        }
1420
1421        //Write the User Statistics to an external csv-document
1422        internal void WriteStatistics(String dataIdentifier)
1423        {
1424            //using the chosen csv file
1425            String path = settings.CsvPath;
1426
1427            if (path == "")
1428            {
1429                //using the default save folder %APPDATA%\Local\Cryptool2
1430                path = string.Format("{0}\\UserRanking{1}.csv", DirectoryHelper.DirectoryLocal, dataIdentifier);
1431            }
1432
1433            try
1434            {
1435                using (StreamWriter sw = new StreamWriter(path))
1436                {
1437                    sw.WriteLine("Avatarname" + ";" + "MaschineID" + ";" + "Hostname" + ";" + "Pattern Count" + ";" + "Last Update");
1438                    foreach (string avatar in statistic.Keys)
1439                    {
1440                        foreach (long mID in statistic[avatar].Keys)
1441                        {
1442                            sw.WriteLine(avatar + ";" + mID.ToString() + ";" + statistic[avatar][mID].Hostname + ";" + statistic[avatar][mID].Count + ";" + statistic[avatar][mID].Date);
1443                        }
1444                    }
1445                }
1446            }
1447            catch (Exception)
1448            {
1449                GuiLogMessage(string.Format("Failed to write Userstatistics to {0}", path), NotificationLevel.Error);
1450            }
1451
1452            //For testing purpose. This writes the Maschinestatistics to the main folder if no different path was chosen
1453            if (settings.CsvPath == "")
1454            {
1455                try
1456                {
1457                    //using the default save folder %APPDATA%\Local\Cryptool2
1458                    using (StreamWriter sw = new StreamWriter(string.Format("{0}\\Maschine{1}.csv", DirectoryHelper.DirectoryLocal, dataIdentifier)))
1459                    {
1460                        sw.WriteLine("Maschineid" + ";" + "Name" + ";" + "Sum" + ";" + "Users");
1461                        foreach (long mID in maschinehierarchie.Keys)
1462                        {
1463                            sw.WriteLine(mID + ";" + maschinehierarchie[mID].Hostname + ";" + maschinehierarchie[mID].Sum + ";" + maschinehierarchie[mID].Users);
1464                        }
1465                    }
1466                }
1467                catch (Exception)
1468                {
1469                    GuiLogMessage(string.Format("Failed to write Maschinestatistics to {0}", path), NotificationLevel.Error);
1470                }
1471            }             
1472        }
1473
1474        internal void GenerateMaschineStats()
1475        {
1476            maschinehierarchie = null;
1477            maschinehierarchie = new Dictionary<long, Maschinfo>();
1478
1479            foreach (string avatar in statistic.Keys)
1480            {
1481                Dictionary<long, Information> Maschines = statistic[avatar];
1482
1483                //add the maschine count to the maschinestatistics
1484                foreach (long mid in Maschines.Keys)
1485                {
1486                    //if the maschine exists in maschinestatistic add it to the sum
1487                    if (maschinehierarchie.ContainsKey(mid))
1488                    {
1489
1490                        maschinehierarchie[mid].Sum = maschinehierarchie[mid].Sum + Maschines[mid].Count;
1491                        maschinehierarchie[mid].Hostname = Maschines[mid].Hostname;
1492                        maschinehierarchie[mid].Users = maschinehierarchie[mid].Users + avatar + " | ";
1493                    }
1494                    else
1495                    {
1496                        //else make a new entry
1497                        maschinehierarchie.Add(mid, new Maschinfo() { Sum = Maschines[mid].Count , Hostname = Maschines[mid].Hostname , Users = "| " + avatar + " | "});
1498                    }
1499                }
1500            }
1501
1502            maschinehierarchie = maschinehierarchie.OrderByDescending((x) => x.Value.Sum).ToDictionary(x => x.Key, y => y.Value);
1503        }
1504
1505        internal BigInteger calculatedChunks()
1506        {
1507            return maschinehierarchie.Keys.Aggregate<long, BigInteger>(0, (current, mid) => current + maschinehierarchie[mid].Sum);
1508        }
1509
1510        private static DateTime defaultstart = DateTime.MinValue;
1511        private static string username = P2PSettings.Default.PeerName;
1512        private static long maschineid = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
1513        private static string maschinename = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetHostName();
1514
1515        private static void EnhanceUserName(ref ValueKey vk)
1516        {
1517            DateTime chunkstart = DateTime.UtcNow;
1518            username = P2PSettings.Default.PeerName;
1519
1520            //enhance our userdata:
1521            if ((username != null) && (!username.Equals("")))
1522            {
1523                vk.user = username;
1524                vk.time = chunkstart;
1525                vk.maschid = maschineid;
1526                vk.maschname = maschinename;
1527            }
1528            else
1529            {
1530                vk.user = "Unknown";
1531                vk.time = defaultstart;
1532                vk.maschid = 666;
1533                vk.maschname = "Devil";
1534            }
1535        }
1536
1537        internal void updateToplist()
1538        {
1539            LinkedListNode<ValueKey> node;
1540            while (valuequeue.Count != 0)
1541            {
1542                ValueKey vk = (ValueKey)valuequeue.Dequeue();
1543
1544                //if (costList.Contains(vk)) continue;
1545                var result = costList.Where(valueKey => valueKey.key == vk.key);
1546                if (result.Count() > 0)
1547                {
1548                    continue;
1549                }
1550
1551                if (this.costMaster.getRelationOperator() == RelationOperator.LargerThen)
1552                {
1553                    if (vk.value > costList.Last().value)
1554                    {
1555                        node = costList.First;
1556                        while (node != null)
1557                        {
1558                            if (vk.value > node.Value.value)
1559                            {
1560                                if (node == costList.First)
1561                                    Top1 = vk;
1562                                costList.AddBefore(node, vk);
1563                                costList.RemoveLast();
1564                                value_threshold = costList.Last.Value.value;
1565                                break;
1566                            }
1567                            node = node.Next;
1568                        }//end while
1569                    }//end if
1570                }
1571                else
1572                {
1573                    if (vk.value < costList.Last().value)
1574                    {
1575                        node = costList.First;
1576                        while (node != null)
1577                        {
1578                            if (vk.value < node.Value.value)
1579                            {
1580                                if (node == costList.First)
1581                                    Top1 = vk;
1582                                costList.AddBefore(node, vk);
1583                                costList.RemoveLast();
1584                                value_threshold = costList.Last.Value.value;
1585                                break;
1586                            }
1587                            node = node.Next;
1588                        }//end while
1589                    }//end if
1590                }
1591            }
1592        }
1593
1594        #endregion
1595
1596        private void StartThreads(IControlEncryption sender, int bytesToUse, KeyPattern.KeyPattern[] patterns, BigInteger[] doneKeysA, BigInteger[] openCLDoneKeysA, BigInteger[] keycounters, BigInteger[] keysleft, Stack threadStack)
1597        {
1598            //First start the opencl threads:
1599            int i = 0;
1600            foreach (var ds in settings.DeviceSettings)
1601            {
1602                if (ds.useDevice)
1603                {
1604                    WaitCallback worker = new WaitCallback(KeySearcherJob);
1605                    doneKeysA[i] = new BigInteger();
1606                    openCLDoneKeysA[i] = new BigInteger();
1607                    keycounters[i] = new BigInteger();
1608
1609                    ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, openCLDoneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack, ds });
1610                    i++;
1611                }
1612            }
1613
1614            //Then the CPU threads:
1615            for (; i < patterns.Length; i++)
1616            {
1617                WaitCallback worker = new WaitCallback(KeySearcherJob);
1618                doneKeysA[i] = new BigInteger();
1619                openCLDoneKeysA[i] = new BigInteger();
1620                keycounters[i] = new BigInteger();
1621
1622                ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, openCLDoneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack, null });
1623            }
1624        }
1625
1626        private KeyPattern.KeyPattern[] splitPatternForThreads(KeyPattern.KeyPattern pattern)
1627        {
1628            int threads = settings.CoresUsed;
1629            threads += settings.DeviceSettings.Count(x => x.useDevice); 
1630
1631            if (threads < 1)
1632                return null;
1633
1634            KeyPattern.KeyPattern[] patterns = new KeyPattern.KeyPattern[threads];
1635            if (threads > 1)
1636            {
1637                KeyPattern.KeyPattern[] patterns2 = pattern.split();
1638                if (patterns2 == null)
1639                {
1640                    patterns2 = new KeyPattern.KeyPattern[1];
1641                    patterns2[0] = pattern;
1642                    return patterns2;
1643                }
1644                patterns[0] = patterns2[0];
1645                patterns[1] = patterns2[1];
1646                int p = 1;
1647                threads -= 2;
1648
1649                while (threads > 0)
1650                {
1651                    int maxPattern = -1;
1652                    BigInteger max = 0;
1653                    for (int i = 0; i <= p; i++)
1654                        if (patterns[i].size() > max)
1655                        {
1656                            max = patterns[i].size();
1657                            maxPattern = i;
1658                        }
1659                    KeyPattern.KeyPattern[] patterns3 = patterns[maxPattern].split();
1660                    if (patterns3 == null)
1661                    {
1662                        patterns3 = new KeyPattern.KeyPattern[p+1];
1663                        for (int i = 0; i <= p; i++)
1664                            patterns3[i] = patterns[i];
1665                        return patterns3;
1666                    }
1667                    patterns[maxPattern] = patterns3[0];
1668                    patterns[++p] = patterns3[1];
1669                    threads--;
1670                }
1671            }
1672            else
1673                patterns[0] = pattern;
1674            return patterns;
1675        }
1676
1677        private void keyPatternChanged()
1678        {
1679            Pattern = new KeyPattern.KeyPattern(controlMaster.getKeyPattern());
1680        }
1681
1682        #endregion
1683
1684        public void GuiLogMessage(string message, NotificationLevel loglevel)
1685        {
1686            if (OnGuiLogNotificationOccured != null)
1687                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(message, this, loglevel));
1688        }
1689
1690        public void ProgressChanged(double value, double max)
1691        {
1692            if (OnPluginProgressChanged != null)
1693            {
1694                OnPluginProgressChanged(this, new PluginProgressEventArgs(value, max));
1695
1696            }
1697        }
1698
1699        /// <summary>
1700        /// used for delivering the results from the worker threads to the main thread:
1701        /// </summary>
1702        public struct ValueKey
1703        {
1704            public override bool Equals(object obj)
1705            {
1706                if (obj != null && obj is ValueKey && keya != null && ((ValueKey)obj).keya != null)
1707                    return (keya.SequenceEqual(((ValueKey)obj).keya));
1708                else
1709                    return false;
1710            }
1711
1712            public double value;
1713            public String key;
1714            public byte[] decryption;
1715            public byte[] keya;
1716            //---------------------
1717            public string user { get; set; }
1718            public DateTime time { get; set; }
1719            public long maschid { get; set; }
1720            public string maschname { get; set; }
1721            //---------------------
1722        };
1723    }
1724
1725    /// <summary>
1726    /// Represents one entry in our result list
1727    /// </summary>
1728    public class ResultEntry
1729    {
1730        public string Ranking { get; set; }
1731        public string Value { get; set; }
1732        public string Key { get; set; }
1733        public string Text { get; set; }
1734        //-------
1735        public string User { get; set; }
1736        public DateTime Time { get; set; }
1737        public long Maschid { get; set; }
1738        public string Maschname { get; set; }
1739        //-------
1740    }
1741    /// <summary>
1742    /// Represents one entry in our statistic list
1743    /// </summary>
1744    public class Information
1745    {
1746        public int Count { get; set; }
1747        public string Hostname { get; set; }
1748        public DateTime Date { get; set; }
1749    }
1750    /// <summary>
1751    /// Represents one entry in our maschine statistic list
1752    /// </summary>
1753    public class Maschinfo
1754    {
1755        public int Sum { get; set; }
1756        public string Hostname { get; set; }
1757        public string Users { get; set; }
1758    } 
1759}
Note: See TracBrowser for help on using the repository browser.