예제 #1
0
        private IEnumerable <string> SelectPasswords(IRandomNumberGenerator random, IEnumerable <string> blacklist, int length, int count)
        {
            length = Math.Min(length, MaxLength);
            count  = Math.Min(count, MaxCount);
            if (count <= 0 || length <= 0)
            {
                yield break;
            }

            var sw = System.Diagnostics.Stopwatch.StartNew();
            var sb = new StringBuilder();

            for (int c = 0; c < count; c++)
            {
                for (int l = 0; l < length; l++)
                {
                    sb.Append(Characters[random.GetRandomInt32(Characters.Length)]);
                }

                var candidate = sb.ToString();
                if (!blacklist.Contains(candidate)
                    // 4 digit PINs starting with '19' are more likely, so weight them lower.
                    || (length == 4 && candidate.Substring(0, 2) == "19" && random.GetRandomInt32(0, 3) == 0))
                {
                    yield return(candidate);
                }

                sb.Clear();
            }
            sw.Stop();

            PostSelectionAction("Pin", count, sw.Elapsed, random);
        }
        private IEnumerable <string> SelectPasswords(IRandomNumberGenerator random, int syllableCount, int count, bool hyphansBetweenSyllables)
        {
            syllableCount = Math.Min(syllableCount, MaxSyllableCount);
            count         = Math.Min(count, MaxCount);
            if (count <= 0 || syllableCount <= 0)
            {
                yield break;
            }

            var sw = System.Diagnostics.Stopwatch.StartNew();
            var sb = new StringBuilder();

            for (int c = 0; c < count; c++)
            {
                // Generate a password.
                for (int l = 0; l < syllableCount; l++)
                {
                    sb.Append(ConsonantSounds[random.GetRandomInt32(ConsonantSounds.Length)]);
                    sb.Append(VowelSounds[random.GetRandomInt32(VowelSounds.Length)]);
                    if (sb[sb.Length - 2] != 'g' && sb[sb.Length - 1] != 'h' &&
                        random.GetRandomSingle() < ProbabilityOfTwoConsonantsInOneSyllable)
                    {
                        sb.Append(ConsonantSounds[random.GetRandomInt32(ConsonantSounds.Length)]);
                    }

                    if (hyphansBetweenSyllables)
                    {
                        sb.Append('-');
                    }
                }
                if (hyphansBetweenSyllables && sb[sb.Length - 1] == '-')
                {
                    sb.Remove(sb.Length - 1, 1);
                }


                // Yield the phrase and reset state.
                var result = sb.ToString();
                yield return(result);

                sb.Clear();
            }
            sw.Stop();

            var bytesRequested = (int)((random as Terninger.Random.CypherBasedPrngGenerator)?.BytesRequested).GetValueOrDefault();

            RandomService.LogPasswordStat("Pronouncable", count, sw.Elapsed, bytesRequested, IPAddressHelpers.GetHostOrCacheIp(Request).AddressFamily, HttpContext.GetApiKeyId());
            if (!IpThrottlerService.HasAnyUsage(IPAddressHelpers.GetHostOrCacheIp(this.HttpContext.Request)))
            {
                RandomService.AddWebRequestEntropy(this.Request);
            }
            IpThrottlerService.IncrementUsage(IPAddressHelpers.GetHostOrCacheIp(this.HttpContext.Request), count);
        }
        private IEnumerable <string> SelectPasswords(IRandomNumberGenerator random, int length, int count, bool includeSymbols)
        {
            length = Math.Min(length, MaxLength);
            count  = Math.Min(count, MaxCount);
            if (count <= 0 || length <= 0)
            {
                yield break;
            }

            var sw    = System.Diagnostics.Stopwatch.StartNew();
            var chars = includeSymbols ? AllCharacters : AlphanumericCharacters;
            var sb    = new StringBuilder();

            for (int c = 0; c < count; c++)
            {
                for (int l = 0; l < length; l++)
                {
                    sb.Append(chars[random.GetRandomInt32(chars.Length)]);
                }

                var result = sb.ToString();
                yield return(result);

                sb.Clear();
            }
            sw.Stop();

            PostSelectionAction("AlphaNumeric", count, sw.Elapsed, random);
        }
예제 #4
0
        private IEnumerable <string> SelectPasswords(IRandomNumberGenerator random, int syllableCount, int count, bool hyphansBetweenSyllables)
        {
            syllableCount = Math.Min(syllableCount, MaxSyllableCount);
            count         = Math.Min(count, MaxCount);
            if (count <= 0 || syllableCount <= 0)
            {
                yield break;
            }

            var sw = System.Diagnostics.Stopwatch.StartNew();
            var sb = new StringBuilder();

            for (int c = 0; c < count; c++)
            {
                // Generate a password.
                for (int l = 0; l < syllableCount; l++)
                {
                    sb.Append(ConsonantSounds[random.GetRandomInt32(ConsonantSounds.Length)]);
                    sb.Append(VowelSounds[random.GetRandomInt32(VowelSounds.Length)]);
                    if (sb[sb.Length - 2] != 'g' && sb[sb.Length - 1] != 'h' &&
                        random.GetRandomSingle() < ProbabilityOfTwoConsonantsInOneSyllable)
                    {
                        sb.Append(ConsonantSounds[random.GetRandomInt32(ConsonantSounds.Length)]);
                    }

                    if (hyphansBetweenSyllables)
                    {
                        sb.Append('-');
                    }
                }
                if (hyphansBetweenSyllables && sb[sb.Length - 1] == '-')
                {
                    sb.Remove(sb.Length - 1, 1);
                }


                // Yield the phrase and reset state.
                var result = sb.ToString();
                yield return(result);

                sb.Clear();
            }
            sw.Stop();

            PostSelectionAction("Pronounceable", count, sw.Elapsed, random);
        }
예제 #5
0
        private IEnumerable <string> SelectPins(IRandomNumberGenerator random, int length, int count)
        {
            length = Math.Min(length, MaxLength);
            count  = Math.Min(count, MaxCount);
            if (count <= 0 || length <= 0)
            {
                yield break;
            }

            var sw        = System.Diagnostics.Stopwatch.StartNew();
            var sb        = new StringBuilder();
            var blacklist = Blacklist.Value;

            for (int c = 0; c < count; c++)
            {
                for (int l = 0; l < length; l++)
                {
                    sb.Append(Characters[random.GetRandomInt32(Characters.Length)]);
                }

                var candidate = sb.ToString();
                if (!blacklist.Contains(candidate)
                    // 4 digit PINs starting with '19' are more likely, so weight them lower.
                    || (length == 4 && candidate.Substring(0, 2) == "19" && random.GetRandomInt32(0, 3) == 0))
                {
                    yield return(candidate);
                }

                sb.Clear();
            }
            sw.Stop();

            var bytesRequested = (int)((random as Terninger.Random.CypherBasedPrngGenerator)?.BytesRequested).GetValueOrDefault();

            RandomService.LogPasswordStat("Pin", count, sw.Elapsed, bytesRequested, IPAddressHelpers.GetHostOrCacheIp(Request).AddressFamily, HttpContext.GetApiKeyId());
            if (!IpThrottlerService.HasAnyUsage(IPAddressHelpers.GetHostOrCacheIp(this.HttpContext.Request)))
            {
                RandomService.AddWebRequestEntropy(this.Request);
            }
            IpThrottlerService.IncrementUsage(IPAddressHelpers.GetHostOrCacheIp(this.HttpContext.Request), count);
        }
예제 #6
0
        public void Accumulator_RandomEntropyPacketSizes()
        {
            var a            = new EntropyAccumulator(32, 0, _Rng);
            int totalEntropy = 0;

            for (int i = 0; i < 1000; i++)
            {
                var bytes = new byte[_Rng.GetRandomInt32(128) + 1];
                a.Add(EventFromBytes(bytes));
                totalEntropy = totalEntropy + bytes.Length;
            }
            Assert.AreEqual(a.TotalEntropyBytes, totalEntropy);
            Assert.AreEqual(a.AvailableEntropyBytesSinceLastSeed, totalEntropy);
            Assert.AreEqual(a.TotalReseedEvents, 0);
        }
예제 #7
0
        public static void ShuffleInPlace <T>(this T[] array, IRandomNumberGenerator generator)
        {
            if (array == null)
            {
                throw new ArgumentNullException(nameof(array));
            }
            if (generator == null)
            {
                throw new ArgumentNullException(nameof(generator));
            }

            for (int i = array.Length - 1; i > 0; i--)
            {
                // Swap element "i" with a random earlier element it (or itself)
                int swapIndex = generator.GetRandomInt32(i + 1);
                T   tmp       = array[i];
                array[i]         = array[swapIndex];
                array[swapIndex] = tmp;
            }
        }
예제 #8
0
        public static void ShuffleInPlace <T>(this IList <T> list, IRandomNumberGenerator generator)
        {
            if (list == null)
            {
                throw new ArgumentNullException(nameof(list));
            }
            if (generator == null)
            {
                throw new ArgumentNullException(nameof(generator));
            }

            for (int i = list.Count - 1; i > 0; i--)
            {
                // Swap element "i" with a random earlier element it (or itself)
                int swapIndex = generator.GetRandomInt32(i + 1);
                T   tmp       = list[i];
                list[i]         = list[swapIndex];
                list[swapIndex] = tmp;
            }
        }
        private IEnumerable <string> SelectPasswords(IRandomNumberGenerator random, int length, int count, bool includeSymbols)
        {
            length = Math.Min(length, MaxLength);
            count  = Math.Min(count, MaxCount);
            if (count <= 0 || length <= 0)
            {
                yield break;
            }

            var sw    = System.Diagnostics.Stopwatch.StartNew();
            var chars = includeSymbols ? AllCharacters : AlphanumericCharacters;
            var sb    = new StringBuilder();

            for (int c = 0; c < count; c++)
            {
                for (int l = 0; l < length; l++)
                {
                    sb.Append(chars[random.GetRandomInt32(chars.Length)]);
                }

                var result = sb.ToString();
                yield return(result);

                sb.Clear();
            }
            sw.Stop();

            var bytesRequested = (int)((random as Terninger.Random.CypherBasedPrngGenerator)?.BytesRequested).GetValueOrDefault();

            RandomService.LogPasswordStat("AlphaNumeric", count, sw.Elapsed, bytesRequested, IPAddressHelpers.GetHostOrCacheIp(Request).AddressFamily, HttpContext.GetApiKeyId());
            if (!IpThrottlerService.HasAnyUsage(IPAddressHelpers.GetHostOrCacheIp(this.HttpContext.Request)))
            {
                RandomService.AddWebRequestEntropy(this.Request);
            }
            IpThrottlerService.IncrementUsage(IPAddressHelpers.GetHostOrCacheIp(this.HttpContext.Request), count);
        }
        private IEnumerable <string> SelectPhrases(IRandomNumberGenerator random, int wordCount, int phraseCount, bool spaces, int minChars, int maxChars, NumericStyles whenNumeric, int numbersToAdd, AllUppercaseStyles whenUpper, int uppersToAdd)
        {
            if (minChars > maxChars)
            {
                yield break;
            }

            phraseCount = Math.Min(phraseCount, MaxCount);
            wordCount   = Math.Min(wordCount, MaxWords);
            if (phraseCount <= 0 || wordCount <= 0)
            {
                yield break;
            }

            var sw       = System.Diagnostics.Stopwatch.StartNew();
            var sb       = new StringBuilder();
            var dict     = Dictionary.Value;
            int attempts = 0;

            ICollection <IMutator> mutators = null;

            if (whenNumeric != NumericStyles.Never || whenUpper != AllUppercaseStyles.Never)
            {
                mutators = new List <IMutator>();
            }
            if (whenNumeric != NumericStyles.Never)
            {
                mutators.Add(new NumericMutator()
                {
                    When = whenNumeric, NumberOfNumbersToAdd = numbersToAdd
                });
            }
            if (whenUpper == AllUppercaseStyles.Anywhere)
            {
                mutators.Add(new UppercaseMutator()
                {
                    When = UppercaseStyles.Anywhere, NumberOfCharactersToCapitalise = uppersToAdd
                });
            }
            else if (whenUpper == AllUppercaseStyles.StartOfWord)
            {
                mutators.Add(new UppercaseMutator()
                {
                    When = UppercaseStyles.StartOfWord, NumberOfCharactersToCapitalise = uppersToAdd
                });
            }
            else if (whenUpper == AllUppercaseStyles.WholeWord)
            {
                mutators.Add(new UppercaseWordMutator()
                {
                    NumberOfWordsToCapitalise = uppersToAdd
                });
            }
            else if (whenUpper == AllUppercaseStyles.RunOfLetters)
            {
                mutators.Add(new UppercaseRunMutator()
                {
                    NumberOfRuns = uppersToAdd
                });
            }
            MurrayGrant.ReadablePassphrase.Random.RandomSourceBase randomWrapper = null;
            if (mutators != null)
            {
                randomWrapper = new MurrayGrant.ReadablePassphrase.Random.ExternalRandomSource(random.GetRandomBytes);
            }

            for (int c = 0; c < phraseCount; c++)
            {
                do
                {
                    // Generate a phrase.
                    for (int l = 0; l < wordCount; l++)
                    {
                        sb.Append(dict[random.GetRandomInt32(dict.Count)]);
                        sb.Append(' ');
                    }
                    sb.Remove(sb.Length - 1, 1);

                    // Apply mutators.
                    if (mutators != null)
                    {
                        foreach (var m in mutators)
                        {
                            m.Mutate(sb, randomWrapper);
                        }
                    }

                    // Finally, remove spaces if required (as the mutators depend on whitespace to do their work).
                    if (!spaces)
                    {
                        for (int i = sb.Length - 1; i >= 0; i--)
                        {
                            if (sb[i] == ' ')
                            {
                                sb.Remove(i, 1);
                            }
                        }
                    }

                    attempts++;

                    // Ensure the final phrase is within the min / max chars.
                } while (attempts < MaxAttemptsPerCount && (sb.Length < minChars || sb.Length > maxChars));
                if (attempts >= MaxAttemptsPerCount)
                {
                    sb.Clear();
                    sb.Append("A passphrase could not be found matching your minimum and maximum length requirements");
                }


                // Yield the phrase and reset state.
                var result = sb.ToString();
                yield return(result);

                sb.Clear();
                attempts = 0;
            }
            sw.Stop();

            var bytesRequested = (int)((random as Terninger.Random.CypherBasedPrngGenerator)?.BytesRequested).GetValueOrDefault();

            RandomService.LogPasswordStat("Passphrase", phraseCount, sw.Elapsed, bytesRequested, IPAddressHelpers.GetHostOrCacheIp(Request).AddressFamily, HttpContext.GetApiKeyId());
            if (!IpThrottlerService.HasAnyUsage(IPAddressHelpers.GetHostOrCacheIp(this.HttpContext.Request)))
            {
                RandomService.AddWebRequestEntropy(this.Request);
            }
            IpThrottlerService.IncrementUsage(IPAddressHelpers.GetHostOrCacheIp(this.HttpContext.Request), phraseCount);
        }
예제 #11
0
        private IEnumerable <IEnumerable <int> > SelectPatterns(IRandomNumberGenerator random, int gridSize, int pointCount, int count)
        {
            gridSize = Math.Min(gridSize, MaxGridSize);
            count    = Math.Min(count, MaxCount);
            var gridPoints = gridSize * gridSize;

            pointCount = Math.Min(pointCount, gridPoints);
            if (count <= 0 || gridSize <= 0 || pointCount <= 0)
            {
                yield break;
            }

            var sw = System.Diagnostics.Stopwatch.StartNew();

            // On my Nexus 5X, connected dots must be adjacent, or already chosen.
            // Ie: if I choose the top left dot, and then the bottom right dot (even if I slide my finger around the screen so I don't touch any other dot),
            //     then it still connects the top left, middle and bottom right dots.
            // Only if a dot is already part of the pattern can it be "bypassed".

            for (int c = 0; c < count; c++)
            {
                if (gridSize == 1)
                {
                    // If someone wants to use a 1x1 grid, well, it won't break!
                    yield return new int[] { 1 }
                }
                ;
                else if (gridSize == 2)
                {
                    // Although a 2x2 grid works with the code below, we just choose points at random.
                    var result = Enumerable.Range(1, gridPoints).ToList();

                    result.ShuffleInPlace(random);
                    yield return(result);
                }
                else
                {
                    // Normal sized grids (minimum 3x3).
                    var result = new List <int>(pointCount);
                    var grid   = new bool[gridSize, gridSize];

                    // Choose any point on the grid and mark it as taken.
                    int x = random.GetRandomInt32(gridSize - 1);
                    int y = random.GetRandomInt32(gridSize - 1);
                    grid[y, x] = true;
                    result.Add((y * gridSize) + x + 1);

                    while (result.Count < pointCount)
                    {
                        // Find the distance to the nearest point.
                        var distance = DistanceToNearestUntakenPoint(grid, y, x);
                        if (distance <= -1)
                        {
                            break;
                        }

                        // Count available points at that distance.
                        var availablePoints = AvailablePointsAtDistance(grid, y, x, distance).ToList();
                        var countAtDistance = availablePoints.Count;
                        if (countAtDistance == 0)
                        {
                            break;      // Should be impossible, but you never know.
                        }
                        // Choose one at random.
                        var choice = countAtDistance <= 1 ? 0 : random.GetRandomInt32(countAtDistance - 1);
                        (y, x)     = availablePoints[choice];
                        grid[y, x] = true;
                        result.Add((y * gridSize) + x + 1);
                    }

                    yield return(result);
                }
            }
            sw.Stop();

            PostSelectionAction("Pattern", count, sw.Elapsed, random);
        }
예제 #12
0
        private IEnumerable <string> SelectPasswords(IRandomNumberGenerator random, int length, int count, bool onlyFromBasicMultilingualPlane, bool includeEastAsianCharacters)
        {
            length = Math.Min(length, MaxLength);
            count  = Math.Min(count, MaxCount);
            if (count <= 0 || length <= 0)
            {
                yield break;
            }
            var allowedCategories = includeEastAsianCharacters ? AsianCategories : DefaultCategories;

            var sw = System.Diagnostics.Stopwatch.StartNew();
            int numberOfCharacters = 0, attempts = 0;
            var mask        = onlyFromBasicMultilingualPlane ? 0x0000ffff : 0x001fffff;
            var maxAttempts = MaxAttemptsPerCodePoint * length;
            var sb          = new StringBuilder();

            for (int i = 0; i < count; i++)
            {
                numberOfCharacters = 0;
                attempts           = 0;
                sb.Clear();

                while (numberOfCharacters < length)
                {
                    // Get random int32 and create a code point from it.
                    // PERF: can reduce number of bytes required here based on the mask.
                    var codePoint = random.GetRandomInt32();
                    codePoint = codePoint & mask;       // Mask off the top bits, which aren't used.
                    attempts++;

                    // Break if too many attempts.
                    if (attempts > maxAttempts)
                    {
                        break;
                    }

                    // Surrogate code points are invalid.
                    if (this.InvalidSurrogateCodePoints(codePoint))
                    {
                        continue;
                    }
                    // Ensure the code point is not outside the maximum range.
                    if (this.InvalidMaxCodePoints(codePoint))
                    {
                        continue;
                    }

                    // the Int32 to up to 2 Char structs (in a string).
                    var s        = Char.ConvertFromUtf32(codePoint);
                    var category = Char.GetUnicodeCategory(s, 0);
                    if (!allowedCategories.Contains(category))
                    {
                        // Not allowed category.
                        continue;
                    }
                    sb.Append(s);
                    numberOfCharacters++;
                }

                if (attempts >= maxAttempts)
                {
                    sb.Clear();
                    sb.Append("A password could not be found matching your requirements.");
                    if (!onlyFromBasicMultilingualPlane)
                    {
                        sb.Append(" Try only selecting characters from the Basic Multilingual Plane (`bmp` parameter).");
                    }
                }

                var result = sb.ToString();
                yield return(result);

                attempts = 0;
            }
            sw.Stop();

            PostSelectionAction("Unicode", count, sw.Elapsed, random);
        }
        private IEnumerable <string> SelectPhrases(IList <string> dict, IRandomNumberGenerator random, int wordCount, int phraseCount, bool spaces, int minChars, int maxChars, NumericStyles whenNumeric, int numbersToAdd, AllUppercaseStyles whenUpper, int uppersToAdd)
        {
            if (minChars > maxChars)
            {
                yield break;
            }

            phraseCount = Math.Min(phraseCount, MaxCount);
            wordCount   = Math.Min(wordCount, MaxWords);
            if (phraseCount <= 0 || wordCount <= 0)
            {
                yield break;
            }

            var sw       = System.Diagnostics.Stopwatch.StartNew();
            var sb       = new StringBuilder();
            int attempts = 0;

            // Setup any mutators required.
            ICollection <IMutator> mutators = null;

            if (whenNumeric != NumericStyles.Never || whenUpper != AllUppercaseStyles.Never)
            {
                mutators = new List <IMutator>();
            }
            if (whenNumeric != NumericStyles.Never)
            {
                mutators.Add(new NumericMutator()
                {
                    When = whenNumeric, NumberOfNumbersToAdd = numbersToAdd
                });
            }
            if (whenUpper == AllUppercaseStyles.Anywhere)
            {
                mutators.Add(new UppercaseMutator()
                {
                    When = UppercaseStyles.Anywhere, NumberOfCharactersToCapitalise = uppersToAdd
                });
            }
            else if (whenUpper == AllUppercaseStyles.StartOfWord)
            {
                mutators.Add(new UppercaseMutator()
                {
                    When = UppercaseStyles.StartOfWord, NumberOfCharactersToCapitalise = uppersToAdd
                });
            }
            else if (whenUpper == AllUppercaseStyles.WholeWord)
            {
                mutators.Add(new UppercaseWordMutator()
                {
                    NumberOfWordsToCapitalise = uppersToAdd
                });
            }
            else if (whenUpper == AllUppercaseStyles.RunOfLetters)
            {
                mutators.Add(new UppercaseRunMutator()
                {
                    NumberOfRuns = uppersToAdd
                });
            }
            MurrayGrant.ReadablePassphrase.Random.RandomSourceBase randomWrapper = null;
            if (mutators != null)
            {
                randomWrapper = new MurrayGrant.ReadablePassphrase.Random.ExternalRandomSource(random.GetRandomBytes);
            }

            for (int c = 0; c < phraseCount; c++)
            {
                do
                {
                    // Generate a phrase.
                    for (int l = 0; l < wordCount; l++)
                    {
                        sb.Append(dict[random.GetRandomInt32(dict.Count)]);
                        sb.Append(' ');
                    }
                    sb.Remove(sb.Length - 1, 1);

                    // Apply mutators.
                    if (mutators != null)
                    {
                        foreach (var m in mutators)
                        {
                            m.Mutate(sb, randomWrapper);
                        }
                    }

                    // Finally, remove spaces if required (as the mutators depend on whitespace to do their work).
                    if (!spaces)
                    {
                        for (int i = sb.Length - 1; i >= 0; i--)
                        {
                            if (sb[i] == ' ')
                            {
                                sb.Remove(i, 1);
                            }
                        }
                    }

                    attempts++;

                    // Ensure the final phrase is within the min / max chars.
                } while (attempts < MaxAttemptsPerCount && (sb.Length < minChars || sb.Length > maxChars));
                if (attempts >= MaxAttemptsPerCount)
                {
                    sb.Clear();
                    sb.Append("A passphrase could not be found matching your minimum and maximum length requirements");
                }


                // Yield the phrase and reset state.
                var result = sb.ToString();
                yield return(result);

                sb.Clear();
                attempts = 0;
            }
            sw.Stop();

            PostSelectionAction("Passphrase", phraseCount, sw.Elapsed, random);
        }
예제 #14
0
        public YammerCommandFetcher(IRandomNumberGenerator randomNumberGenerator, 
                                    IYammerMessagePoster poster, 
                                    IQuoteRetriever quoteRetriever, 
                                    IComplimentFetcher complimentFetcher,
                                    IDictionaryService dictionaryService)
        {
            _randomNumberGenerator = randomNumberGenerator;
            _poster = poster;
            _quoteRetriever = quoteRetriever;
            _complimentFetcher = complimentFetcher;
            _dictionaryService = dictionaryService;
            _allCommands = new Dictionary<string, Func<Message, Message>>
                                  {
                                      {
                                          "randomquote", (message) =>
                                                             {
                                                                 string quote = null;
                                                                 try
                                                                 {
                                                                     quote = _quoteRetriever.GetNextQuote();
                                                                 }
                                                                 finally
                                                                 {
                                                                     if (quote == null)
                                                                         quote = "I don't have any more quotes...";
                                                                 }
                                                                 return _poster.PostReply(quote, message.ID);
                                                             }
                                      },
                                      {
                                          "tellmetofuckoff", (message) =>
                                                                 {
                                                                     return _poster.PostReply("F**k off", message.ID);
                                                                 }
                                      },
                                      {
                                          "help", (message) =>
                                                      {
                                                          return _poster.PostReply(
                                                              "@@RandomQuote gives a random quote, @@TellMeToFuckOff tells you to f**k off, @@CatFacts will send you a random cat fact",
                                                              message.ID);
                                                      }
                                      },
                                      {
                                          "catfacts", (message) =>
                                                          {
                                                              var responses = new Dictionary<int, string>
                                                                                  {
                                                                                      {0, "Cats have 9 lives"},
                                                                                      {1, "Cats are cute"},
                                                                                      {2, "Cats just don't give a f**k"}
                                                                                  };
                                                              var selectedResponse =
                                                                  responses[_randomNumberGenerator.GetRandomInt32(0, 3)];
                                                              return _poster.PostReply(selectedResponse, message.ID);
                                                          }
                                      },
                                      {
                                          "whispersweetnothingstome", (message) =>
                                                          {
                                                              return _poster.PostReply(_complimentFetcher.GetRandomComplimentPhrase(), message.ID);
                                                          }
                                      },
                                      {
                                          "sexify", (message) =>
                                                          {
                                                              var cmd = new Command(message.Body.Plain);
                                                              var wordDefinitions = cmd.Argument.Split(' ')
                                                                                       .Select(word => WordProcessor.NormalizeWord(word))
                                                                                       .Aggregate(new Dictionary<string,IEnumerable<string>>(),(accum, word) =>
                                                                                                   {
                                                                                                       if (!accum.Keys.Contains(word))
                                                                                                           accum.Add(word, _dictionaryService.GetDefinitions(word));
                                                                                                       return accum;
                                                                                                   });

                                                              return _poster.PostReply(WordProcessor.Sexify(cmd.Argument, wordDefinitions), message.ID);
                                                          }
                                      },
                                  };
        }
        private IEnumerable <string> SelectPasswords(IRandomNumberGenerator random, int length, int count, bool onlyFromBasicMultilingualPlane, bool includeEastAsianCharacters)
        {
            length = Math.Min(length, MaxLength);
            count  = Math.Min(count, MaxCount);
            if (count <= 0 || length <= 0)
            {
                yield break;
            }
            var allowedCategories = includeEastAsianCharacters ? AsianCategories : DefaultCategories;

            var sw = System.Diagnostics.Stopwatch.StartNew();
            int numberOfCharacters = 0, attempts = 0;
            var mask = onlyFromBasicMultilingualPlane ? 0x0000ffff : 0x001fffff;
            var sb   = new StringBuilder();

            for (int i = 0; i < count; i++)
            {
                numberOfCharacters = 0;
                attempts           = 0;
                sb.Clear();

                while (numberOfCharacters < length)
                {
                    // Get random int32 and create a code point from it.
                    // PERF: can reduce number of bytes required here based on the mask.
                    var codePoint = random.GetRandomInt32();
                    codePoint = codePoint & mask;       // Mask off the top bits, which aren't used.
                    attempts++;

                    // Break if too many attempts.
                    if (attempts > MaxAttemptsPerCodePoint)
                    {
                        continue;
                    }

                    // Surrogate code points are invalid.
                    if (this.InvalidSurrogateCodePoints(codePoint))
                    {
                        continue;
                    }
                    // Ensure the code point is not outside the maximum range.
                    if (this.InvalidMaxCodePoints(codePoint))
                    {
                        continue;
                    }

                    // the Int32 to up to 2 Char structs (in a string).
                    var s        = Char.ConvertFromUtf32(codePoint);
                    var category = Char.GetUnicodeCategory(s, 0);
                    if (!allowedCategories.Contains(category))
                    {
                        // Not allowed category.
                        continue;
                    }
                    sb.Append(s);
                    numberOfCharacters++;
                }

                var result = sb.ToString();
                yield return(result);

                attempts = 0;
            }
            sw.Stop();


            var bytesRequested = (int)((random as Terninger.Random.CypherBasedPrngGenerator)?.BytesRequested).GetValueOrDefault();

            RandomService.LogPasswordStat("Unicode", count, sw.Elapsed, bytesRequested, IPAddressHelpers.GetHostOrCacheIp(Request).AddressFamily, HttpContext.GetApiKeyId());
            if (!IpThrottlerService.HasAnyUsage(IPAddressHelpers.GetHostOrCacheIp(this.HttpContext.Request)))
            {
                RandomService.AddWebRequestEntropy(this.Request);
            }
            IpThrottlerService.IncrementUsage(IPAddressHelpers.GetHostOrCacheIp(this.HttpContext.Request), count);
        }