private static void TestGeneration(ReadablePassphraseGenerator generator, IEnumerable <PhraseStrength> strengths, int iterations)
 {
     Console.Write("Testing {0:N0} string phrases of strength {1}...", iterations, String.Join(",", strengths.Select(x => x.ToString())));
     for (int i = 0; i < iterations; i++)
     {
         generator.Generate(strengths);
     }
     Console.WriteLine(" OK.");
 }
 private static void GenerateDelimiterSamples(PhraseStrength strength, ReadablePassphraseGenerator generator, int count, string delimiter)
 {
     Console.WriteLine();
     Console.WriteLine("Delimited Samples ('{0}'):", delimiter);
     for (int i = 0; i < count; i++)
     {
         Console.WriteLine(generator.Generate(strength, wordDelimiter: delimiter));
     }
 }
 private static void TestGeneration(ReadablePassphraseGenerator generator, PhraseStrength strength, int iterations)
 {
     Console.Write("Testing {0:N0} string phrases of strength {1}...", iterations, strength);
     for (int i = 0; i < iterations; i++)
     {
         generator.Generate(strength);
     }
     Console.WriteLine(" OK.");
 }
 private static void GenerateSamples(PhraseStrength strength, ReadablePassphraseGenerator generator, int count)
 {
     Console.WriteLine();
     Console.WriteLine("Samples:");
     for (int i = 0; i < count; i++)
     {
         Console.WriteLine(generator.Generate(strength));
     }
 }
 private static void GenerateMutatedSamples(PhraseStrength strength, ReadablePassphraseGenerator generator, int count, IEnumerable <IMutator> mutators)
 {
     Console.WriteLine();
     Console.WriteLine("Mutated Samples:");
     for (int i = 0; i < count; i++)
     {
         var passphrase = generator.Generate(strength, mutators: mutators);
         Console.WriteLine(passphrase);
     }
 }
        private static void GenerateCustomSamples(IEnumerable <MurrayGrant.ReadablePassphrase.PhraseDescription.Clause> clause, ReadablePassphraseGenerator generator, int count)
        {
            Console.WriteLine();
            Console.WriteLine("Custom samples:");
            var combinations = generator.CalculateCombinations(clause);

            Console.WriteLine("Combinations: {0:E3} ({1:N2} bits)", combinations.ToString(), combinations.EntropyBitsToString());
            for (int i = 0; i < count; i++)
            {
                Console.WriteLine(generator.Generate(clause));
            }
        }
Esempio n. 7
0
        private static void TestGithubIssue3(ReadablePassphraseGenerator generator)
        {
            // No trailing whitespace causes ArgumentOutOfRangeException in ConstantMutator
            // Caused with combination of numeric mutator at end of phrase, then constant mutator at end of phrase
            // https://github.com/ligos/readablepassphrasegenerator/issues/3
            var numericMutator = new NumericMutator()
            {
                When = NumericStyles.EndOfPhrase
            };
            var constantMutator = new ConstantMutator()
            {
                When = ConstantStyles.EndOfPhrase
            };
            var mutatorArray = new IMutator[] { numericMutator, constantMutator };
            var phrase       = generator.Generate(wordDelimiter: "__", mutators: mutatorArray);

            Console.WriteLine(phrase);
            if (!phrase.EndsWith(constantMutator.ValueToAdd))
            {
                throw new Exception("Should not be any trailing whitespace; final character should be the '.' from ConstantMutator");
            }

            phrase = generator.Generate(wordDelimiter: "", mutators: mutatorArray);
            Console.WriteLine(phrase);
            if (!phrase.EndsWith(constantMutator.ValueToAdd))
            {
                throw new Exception("Should not be any trailing whitespace; final character should be the '.' from ConstantMutator");
            }

            var sb = new StringBuilder("some passphrase without trailing whitespace");

            numericMutator.Mutate(sb, GetRandomness());
            constantMutator.Mutate(sb, GetRandomness());
            Console.WriteLine(sb.ToString());

            sb = new StringBuilder("some passphrase with extra trailing whitespace   ");
            numericMutator.Mutate(sb, GetRandomness());
            constantMutator.Mutate(sb, GetRandomness());
            Console.WriteLine(sb.ToString());
        }
        private static void BenchmarkGeneration(ReadablePassphraseGenerator generator, PhraseStrength strength, int iterations)
        {
            Console.WriteLine();
            Console.WriteLine("Benchmark of {0:N0} phrases of strength {1}...", iterations, strength);
            var sw = System.Diagnostics.Stopwatch.StartNew();

            for (int i = 0; i < iterations; i++)
            {
                generator.Generate(strength);
            }
            sw.Stop();
            Console.WriteLine("  in {0:N3}ms", sw.Elapsed.TotalMilliseconds);
        }
        private static void TestTextualParsing(ReadablePassphraseGenerator generator, PhraseStrength strength)
        {
            Console.WriteLine("Testing parsing of textual phrase strength {0}...", strength);
            var description = Clause.CreatePhraseDescription(strength, generator.Randomness);
            var sb          = new StringBuilder();

            foreach (var c in description)
            {
                c.ToStringBuilder(sb);
            }
            var textualDescription = sb.ToString();

            Console.Write("    Generation OK.");
            var customStrength = Clause.CreateCollectionFromTextString(textualDescription);

            Console.Write(" Parsing OK.");
            generator.Generate(customStrength);
            Console.WriteLine(" Passphrase OK.");
        }
Esempio n. 10
0
        static void RunMain()
        {
            // Generate and print phrases.
            if (!quiet)
            {
                var ver = GetProgramVersion();
                var idx = ver.IndexOf('.', ver.IndexOf('.', ver.IndexOf('.') + 1) + 1);
                Console.WriteLine("Readable Passphrase Generator {0}", ver.Substring(0, idx));
            }
            if (!quiet && anyLength > 0)
            {
                Console.WriteLine("Generating {0:N0} non-grammatic phrase(s) of length '{1}'...", count, anyLength);
            }
            else if (!quiet && String.IsNullOrEmpty(customPhrasePath))
            {
                Console.WriteLine("Generating {0:N0} phrase(s) of strength '{1}'...", count, strength);
            }
            else if (!quiet && !String.IsNullOrEmpty(customPhrasePath))
            {
                Console.WriteLine("Generating {0:N0} phrase(s) based on phrase description in '{1}'...", count, System.IO.Path.GetFileName(customPhrasePath));
            }
            if (!quiet && (maxLength < Int32.MaxValue || minLength > 1))
            {
                Console.WriteLine("Must be between {0:N0} and {1} characters.", minLength, maxLength == Int32.MaxValue ? "∞" : maxLength.ToString("N0"));
            }

            var generator = new ReadablePassphraseGenerator();

            // Must load dictionary before trying to generate.
            var dictSw  = System.Diagnostics.Stopwatch.StartNew();
            var loaderT = GetDictionaryLoaderType();

            // If the internal dictionary loader is being used and no other arguments are specified, tell it to use the default dictionary.
            if (loaderT == typeof(ExplicitXmlDictionaryLoader) && String.IsNullOrEmpty(loaderArguments.Trim()))
            {
                loaderArguments = "useDefaultDictionary=true";
            }

            // And load our dictionary!
            using (var loader = Activator.CreateInstance(loaderT) as IDictionaryLoader)
            {
                if (loader == null)
                {
                    throw new Exception($"Unable to create instance of dictionary loader {loaderT.FullName}");
                }
                generator.LoadDictionary(loader, loaderArguments);
            }
            dictSw.Stop();

            // Summarise actions and combinations / entropy.
            if (!quiet)
            {
                Console.WriteLine("Dictionary contains {0:N0} words (loaded in {1:N2}ms)", generator.Dictionary.Count, dictSw.Elapsed.TotalMilliseconds);
                PhraseCombinations combinations;
                if (anyLength > 0)
                {
                    combinations = generator.CalculateCombinations(NonGrammaticalClause(anyLength));
                }
                else if (strength != PhraseStrength.Custom)
                {
                    combinations = generator.CalculateCombinations(strength);
                }
                else
                {
                    combinations = generator.CalculateCombinations(phraseDescription);
                }
                Console.WriteLine("Average combinations ~{0:E3} (~{1:N2} bits)", combinations.OptionalAverage, combinations.OptionalAverageAsEntropyBits);
                Console.WriteLine("Total combinations {0:E3} - {1:E3} ({2:N2} - {3:N2} bits)", combinations.Shortest, combinations.Longest, combinations.ShortestAsEntropyBits, combinations.LongestAsEntropyBits);

                var upperTypeText = upperStyle == AllUppercaseStyles.RunOfLetters ? " run"
                                  : upperStyle == AllUppercaseStyles.WholeWord ? " word"
                                  : "";
                var upperTypeText2 = upperStyle == AllUppercaseStyles.RunOfLetters ? "run"
                                   : upperStyle == AllUppercaseStyles.WholeWord ? "word"
                                   : "capital";
                if (applyStandardMutators)
                {
                    Console.WriteLine("Using standard mutators (2 numbers, 2 capitals, period at end)");
                }
                else if (applyAlternativeMutators)
                {
                    Console.WriteLine("Using alternate mutators (2 numbers, 1 whole capital word, period at end)");
                }
                else if (numericStyle != 0 && upperStyle != 0 && constantStyle != 0)
                {
                    Console.WriteLine($"Using upper case{upperTypeText}, numeric and constant mutators ({upperCount:N0} {upperTypeText2}(s), {numericCount:N0} number(s))");
                }
                else if (numericStyle != 0 && upperStyle != 0 && constantStyle == 0)
                {
                    Console.WriteLine($"Using upper case{upperTypeText} and numeric mutators ({upperCount:N0} {upperTypeText2}(s), {numericCount:N0} number(s))");
                }
                else if (numericStyle == 0 && upperStyle != 0 && constantStyle != 0)
                {
                    Console.WriteLine($"Using upper case{upperTypeText} and constant mutators ({upperCount:N0} {upperTypeText2}(s))");
                }
                else if (numericStyle == 0 && upperStyle != 0 && constantStyle == 0)
                {
                    Console.WriteLine($"Using upper case{upperTypeText} mutator only ({upperCount:N0} {upperTypeText2}(s))");
                }
                else if (numericStyle != 0 && upperStyle == 0 && constantStyle != 0)
                {
                    Console.WriteLine($"Using numeric and constant mutators ({numericCount:N0} number(s))");
                }
                else if (numericStyle != 0 && upperStyle == 0 && constantStyle == 0)
                {
                    Console.WriteLine($"Using numeric mutator only ({numericCount:N0} number(s))");
                }
                else if (numericStyle == 0 && upperStyle == 0 && constantStyle != 0)
                {
                    Console.WriteLine($"Using constant mutator only");
                }
                else
                {
                    Console.WriteLine("Using no mutators");
                }
                Console.WriteLine();
            }

            // Generate!
            var genSw       = System.Diagnostics.Stopwatch.StartNew();
            int generated   = 0;
            int attempts    = 0;
            int maxAttempts = count * MaxAttemptsPerCount;
            var mutators    = applyStandardMutators ? new IMutator[] { UppercaseMutator.Basic, NumericMutator.Basic, ConstantMutator.Basic }
                         : applyAlternativeMutators ? new IMutator[] { UppercaseWordMutator.Basic, NumericMutator.Basic, ConstantMutator.Basic }
                         : Enumerable.Empty <IMutator>();

            if (upperStyle > 0 && upperStyle <= AllUppercaseStyles.Anywhere)
            {
                mutators = mutators.Concat(new IMutator[] { new UppercaseMutator()
                                                            {
                                                                When = (UppercaseStyles)upperStyle, NumberOfCharactersToCapitalise = upperCount
                                                            } });
            }
            if (upperStyle == AllUppercaseStyles.RunOfLetters)
            {
                mutators = mutators.Concat(new IMutator[] { new UppercaseRunMutator()
                                                            {
                                                                NumberOfRuns = upperCount
                                                            } });
            }
            if (upperStyle == AllUppercaseStyles.WholeWord)
            {
                mutators = mutators.Concat(new IMutator[] { new UppercaseWordMutator()
                                                            {
                                                                NumberOfWordsToCapitalise = upperCount
                                                            } });
            }
            if (numericStyle != 0)
            {
                mutators = mutators.Concat(new IMutator[] { new NumericMutator()
                                                            {
                                                                When = numericStyle, NumberOfNumbersToAdd = numericCount
                                                            } });
            }
            if (constantStyle != 0)
            {
                mutators = mutators.Concat(new IMutator[] { new ConstantMutator()
                                                            {
                                                                When = constantStyle, ValueToAdd = constantValue
                                                            } });
            }
            while (generated < count)
            {
                // Generate phrase.
                // We always include spaces in the phrase because the mutators rely on whitespace.
                string phrase;
                attempts++;
                if (anyLength > 0)
                {
                    phrase = generator.Generate(NonGrammaticalClause(anyLength), " ", mutators);
                }
                else if (strength == PhraseStrength.Custom)
                {
                    phrase = generator.Generate(phraseDescription, " ", mutators);
                }
                else
                {
                    phrase = generator.Generate(strength, " ", mutators);
                }

                // After mutators are applied, it's safe to remove white space.
                if (wordSeparator != " ")
                {
                    phrase = phrase.Replace(" ", wordSeparator);
                }

                // Clamp the length.
                if (phrase.Length >= minLength && phrase.Length <= maxLength)
                {
                    Console.WriteLine(phrase);
                    generated++;
                }
                if (attempts >= maxAttempts)
                {
                    break;
                }
            }
            genSw.Stop();

            // Summarise result.
            if (!quiet)
            {
                Console.WriteLine();
                Console.WriteLine("Generated {0:N0} phrase(s) in {1:N2}ms.", generated, genSw.Elapsed.TotalMilliseconds);
                if (attempts >= maxAttempts)
                {
                    Console.WriteLine("But unable to generate requested {0:N0} phrase(s) after {1:N0} attempts." + Environment.NewLine + "Perhaps try changing the minimum or maximum phrase length.", count, attempts);
                }
            }
        }
        private static void WriteStatisticsFor(ReadablePassphraseGenerator generator, PhraseStrength strength, int count, string filename)
        {
            Console.Write("Writing statistics to '{0}'...", filename);

            var wordHistogram           = new Dictionary <int, int>();
            var charHistogram           = new Dictionary <int, int>();
            var keepassQualityHistogram = new Dictionary <uint, int>();
            var combinations            = generator.CalculateCombinations(strength);

            for (int i = 0; i < count; i++)
            {
                var phrase = generator.Generate(strength);

                if (!charHistogram.ContainsKey(phrase.Length))
                {
                    charHistogram.Add(phrase.Length, 0);
                }
                charHistogram[phrase.Length] = charHistogram[phrase.Length] + 1;

                var wordCount = phrase.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries).Length;
                if (!wordHistogram.ContainsKey(wordCount))
                {
                    wordHistogram.Add(wordCount, 0);
                }
                wordHistogram[wordCount] = wordHistogram[wordCount] + 1;

                var keePassQualityEst = KeePassLib.Cryptography.QualityEstimation.EstimatePasswordBits(phrase.ToCharArray());
                if (!keepassQualityHistogram.ContainsKey(keePassQualityEst))
                {
                    keepassQualityHistogram.Add(keePassQualityEst, 0);
                }
                keepassQualityHistogram[keePassQualityEst] = keepassQualityHistogram[keePassQualityEst] + 1;
            }

            using (var writer = new System.IO.StreamWriter(filename, false, Encoding.UTF8))
            {
                writer.WriteLine("Word histogram");
                for (int i = wordHistogram.Keys.Min(); i < wordHistogram.Keys.Max() + 1; i++)
                {
                    writer.WriteLine("{0},{1}", i, wordHistogram.ContainsKey(i) ? wordHistogram[i] : 0);
                }
                writer.WriteLine();

                writer.WriteLine("Character histogram");
                for (int i = charHistogram.Keys.Min(); i < charHistogram.Keys.Max() + 1; i++)
                {
                    writer.WriteLine("{0},{1}", i, charHistogram.ContainsKey(i) ? charHistogram[i] : 0);
                }
                writer.WriteLine();

                writer.WriteLine("KeePass Quality Estimate");
                for (uint i = keepassQualityHistogram.Keys.Min(); i < keepassQualityHistogram.Keys.Max() + 1; i++)
                {
                    writer.WriteLine("{0},{1}", i, keepassQualityHistogram.ContainsKey(i) ? keepassQualityHistogram[i] : 0);
                }
                writer.WriteLine();

                writer.WriteLine("Combination counts");
                writer.WriteLine("Min:,{0:E3},{1:N2}", combinations.Shortest, combinations.ShortestAsEntropyBits);
                writer.WriteLine("Max:,{0:E3},{1:N2}", combinations.Longest, combinations.LongestAsEntropyBits);
                writer.WriteLine("Avg:,{0:E3},{1:N2}", combinations.OptionalAverage, combinations.OptionalAverageAsEntropyBits);

                writer.WriteLine();
                writer.WriteLine("Samples:");
                for (int i = 0; i < 20; i++)
                {
                    writer.WriteLine(generator.Generate(strength));
                }
            }

            Console.WriteLine(" Done.");

            bool isFirst = !System.IO.File.Exists(AllStatsCharFilename);

            using (var writer = new System.IO.StreamWriter(AllStatsCharFilename, true, Encoding.UTF8))
            {
                if (isFirst)
                {
                    writer.WriteLine("Strength,Min,Max,Avg,Median,Samples");
                }
                writer.WriteLine("{0},{1},{2},{3},{4},{5}", strength.ToString(), charHistogram.Keys.Min(), charHistogram.Keys.Max(), GetAvg(charHistogram), GetMedian(charHistogram), count);
            }
        }