///<inheritdoc/>
        public override List <AttackPossibility> Hack(string input)
        {
            var storedKey = Key;
            var result    = new List <AttackPossibility>();

            try
            {
                if (!dictLoaded)
                {
                    throw new InvalidOperationException("Dictionary not loaded");
                }

                foreach (var key in KeyDictionary)
                {
                    Key = key;
                    var output = Decrypt(input);
                    if (CheckDictionary(output))
                    {
                        var poss = new AttackPossibility(key, output);
                        result.Add(poss);
                    }
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                Key = storedKey;
            }
            return(result);
        }
        ///<inheritdoc/>
        public override async Task <List <AttackPossibility> > HackAsync(string input, CancellationToken cancellationToken = default, IProgress <float> progress = null)
        {
            return(await Task.Run(() =>
            {
                var storedKey = Key;

                var result = new List <AttackPossibility>();
                try
                {
                    if (!dictLoaded)
                    {
                        throw new InvalidOperationException("Dictionary not loaded");
                    }
                    float index = 0;
                    float size = KeyDictionary.Count;
                    foreach (var key in KeyDictionary)
                    {
                        //Check if we have been cancelled;
                        if (cancellationToken != default &&
                            cancellationToken.IsCancellationRequested)
                        {
                            result.Clear();
                            Key = storedKey;
                            cancellationToken.ThrowIfCancellationRequested();
                        }

                        //Run the decryption
                        Key = key;
                        var output = Decrypt(input);
                        if (CheckDictionary(output))
                        {
                            var poss = new AttackPossibility(key, output);
                            result.Add(poss);
                        }

                        index++;
                        //Report on progress:
                        if (progress != null)
                        {
                            progress.Report(index / size);
                        }
                    }

                    return result;
                }
                catch
                {
                    throw;
                }
                finally
                {
                    Key = storedKey;
                }
            }));
        }