source: trunk/CrypPlugins/KeySearcher/KeySearcher.cs

Last change on this file was 8983, checked in by kopal, 8 months ago

Complete CrypTool 2 project

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