diff --git a/CHANGELOG.md b/CHANGELOG.md index 0181e40..991b5c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,19 @@ See the [v2 → v3 migration guide](docs/migration-v2-to-v3.md). - **Dependency injection:** `AddPasswordGenerator(...)` with code and `appSettings.json` binding (resolution order: code-configure > appSettings > default). - **Presets:** `ForOwasp`, `ForNist`, `ForOtp`, `ForApiKey`, `ForEnvironmentName`, `ForPassphrase`. +- **Passphrases use the EFF Large Wordlist** (7,776 words, ~12.9 bits/word), replacing the small + built-in list — a 6-word phrase is now ~77 bits. The list is © EFF under CC BY 3.0; see + [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md). +- **Entropy-targeted passphrases:** `ForPassphraseWithEntropy(targetBits)` derives the word count + to meet a target, and `ForPassphrase(..., minimumEntropyBits)` enforces an entropy floor. +- **Symbol injection:** `ForPassphrase(..., includeSymbol: true)` attaches a random symbol to one + randomly chosen word, so passphrases satisfy "needs a number and a symbol" rules while staying + memorable. Entropy estimation now accounts for both the trailing number and the symbol. +- **`ForMemorable()` preset:** capitalized words sized to at least 80 bits of entropy. +- **Passphrases via dependency injection:** set `PasswordOptions.Passphrase` (a `PassphraseOptions`) + in code or bind a `Passphrase` section from configuration to resolve a passphrase + `IPasswordGenerator`. +- `EstimateEntropyBits()` is now part of the `IPasswordGenerator` interface. - **Custom pools:** `WithCharacters(string)`, `WithAllAscii()`. - **Quality controls:** `ExcludeAmbiguous()`, `RequireAtLeast(CharacterClass, count)`. - **Entropy estimation:** `IEntropyEstimator` / `PoolEntropyEstimator` and `EstimateEntropyBits()`. diff --git a/PasswordGenerator.Tests/PassphraseTests.cs b/PasswordGenerator.Tests/PassphraseTests.cs new file mode 100644 index 0000000..5465ce3 --- /dev/null +++ b/PasswordGenerator.Tests/PassphraseTests.cs @@ -0,0 +1,216 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; + +namespace PasswordGenerator.Tests +{ + public class PassphraseTests + { + // A deterministic random source that cycles a fixed sequence, so generation is reproducible. + private class FixedRandomSource : IRandomSource + { + private readonly int[] _values; + private int _index; + + public FixedRandomSource(params int[] values) => _values = values; + + public int NextInt(int maxExclusive) + { + var value = _values[_index % _values.Length] % maxExclusive; + _index++; + return value; + } + } + + [Test] + public void WordCountForEntropy_DerivesEnoughWordsToMeetTarget() + { + // 7,776-word list => ~12.925 bits/word; with the trailing number 6 words clears 80 bits, + // without it 7 are needed. + Assert.That(PassphraseGenerator.WordCountForEntropy(80, includeNumber: true), Is.EqualTo(6)); + Assert.That(PassphraseGenerator.WordCountForEntropy(80, includeNumber: false), Is.EqualTo(7)); + } + + [Test] + public void WordCountForEntropy_NeverReturnsLessThanOne() + { + Assert.That(PassphraseGenerator.WordCountForEntropy(0), Is.EqualTo(1)); + Assert.That(PassphraseGenerator.WordCountForEntropy(-50), Is.EqualTo(1)); + } + + [Test] + public void ForPassphraseWithEntropy_MeetsOrExceedsTarget() + { + var generator = Password.ForPassphraseWithEntropy(80); + Assert.That(generator.EstimateEntropyBits(), Is.GreaterThanOrEqualTo(80)); + } + + [Test] + public void ForPassphraseWithEntropy_ProducesDerivedWordCount() + { + var generator = Password.ForPassphraseWithEntropy(80, separator: '.', includeNumber: true); + var parts = generator.Next().Split('.'); + Assert.That(parts.Length, Is.EqualTo(7)); // 6 words + trailing number + } + + [Test] + public void EntropyFloor_RejectsWeakConfiguration() + { + Assert.Throws(() => Password.ForPassphrase(words: 2, minimumEntropyBits: 80)); + } + + [Test] + public void EntropyFloor_AllowsStrongConfiguration() + { + Assert.DoesNotThrow(() => Password.ForPassphrase(words: 8, minimumEntropyBits: 80)); + } + + [Test] + public void EntropyFloor_ZeroMeansNoEnforcement() + { + Assert.DoesNotThrow(() => Password.ForPassphrase(words: 1, minimumEntropyBits: 0)); + } + + [Test] + public void EstimateEntropyBits_IsAvailableThroughInterface() + { + IPasswordGenerator generator = Password.ForPassphrase(6); + Assert.That(generator.EstimateEntropyBits(), Is.GreaterThan(0)); + } + + private static readonly char[] SymbolChars = "!@#$%&*?".ToCharArray(); + + [Test] + public void IncludeSymbol_InjectsASymbol() + { + var generator = Password.ForPassphrase(4, separator: '.', includeNumber: false, + includeSymbol: true); + var phrase = generator.Next(); + Assert.That(phrase.IndexOfAny(SymbolChars), Is.GreaterThanOrEqualTo(0), phrase); + } + + [Test] + public void NumberAndSymbol_SatisfyCompositionRules() + { + var generator = Password.ForPassphrase(4, separator: '.', includeNumber: true, + includeSymbol: true); + var phrase = generator.Next(); + Assert.That(phrase.Any(char.IsDigit), Is.True, phrase); + Assert.That(phrase.IndexOfAny(SymbolChars), Is.GreaterThanOrEqualTo(0), phrase); + } + + [Test] + public void IncludeSymbol_IsOffByDefault() + { + var generator = Password.ForPassphrase(4, separator: '.', includeNumber: false); + var phrase = generator.Next(); + Assert.That(phrase.IndexOfAny(SymbolChars), Is.EqualTo(-1), phrase); + } + + [Test] + public void IncludeSymbol_AddsEntropy() + { + var withoutSymbol = Password.ForPassphrase(6, includeSymbol: false).EstimateEntropyBits(); + var withSymbol = Password.ForPassphrase(6, includeSymbol: true).EstimateEntropyBits(); + Assert.That(withSymbol, Is.GreaterThan(withoutSymbol)); + } + + [Test] + public void ForMemorable_IsCapitalizedAndStrong() + { + var generator = Password.ForMemorable(); + Assert.That(generator.EstimateEntropyBits(), Is.GreaterThanOrEqualTo(80)); + var phrase = generator.Next(); + Assert.That(char.IsUpper(phrase[0]), Is.True, phrase); + } + + [Test] + public void Di_CodeConfiguresPassphrase() + { + var services = new ServiceCollection(); + services.AddPasswordGenerator(o => + o.Passphrase = new PassphraseOptions { WordCount = 6, Separator = '.' }); + + using var provider = services.BuildServiceProvider(); + var generator = provider.GetRequiredService(); + + var parts = generator.Next().Split('.'); + Assert.That(parts.Length, Is.EqualTo(7)); // 6 words + trailing number (on by default) + } + + [Test] + public void Next_SelectsWordsByRandomIndex() + { + var rng = new FixedRandomSource(0, 1, 2, 3); + var generator = new PassphraseGenerator(4, '.', capitalize: false, includeNumber: false, + includeSymbol: false, minimumEntropyBits: 0, randomSource: rng); + + var expected = string.Join('.', + WordList.Words[0], WordList.Words[1], WordList.Words[2], WordList.Words[3]); + Assert.That(generator.Next(), Is.EqualTo(expected)); + } + + [Test] + public void Next_CapitalizesEachWordsFirstLetter() + { + var rng = new FixedRandomSource(0); + var generator = new PassphraseGenerator(1, '.', capitalize: true, includeNumber: false, + includeSymbol: false, minimumEntropyBits: 0, randomSource: rng); + + var word = WordList.Words[0]; + var expected = char.ToUpperInvariant(word[0]) + word.Substring(1); + Assert.That(generator.Next(), Is.EqualTo(expected)); + } + + [Test] + public void Next_PlacesSymbolOnTheChosenWord() + { + // Draw order: symbol-word index, symbol char index, then one index per word. + var rng = new FixedRandomSource(0, 0, 0, 1); + var generator = new PassphraseGenerator(2, '.', capitalize: false, includeNumber: false, + includeSymbol: true, minimumEntropyBits: 0, randomSource: rng); + + // Symbol index 0 maps to '!' (first of "!@#$%&*?"). + var expected = WordList.Words[0] + "!" + "." + WordList.Words[1]; + Assert.That(generator.Next(), Is.EqualTo(expected)); + } + + [Test] + public void Next_SamplesBroadlyAcrossTheWordList() + { + var generator = new PassphraseGenerator(1, '.', capitalize: false, includeNumber: false); + + var seen = new HashSet(); + for (var i = 0; i < 2000; i++) seen.Add(generator.Next()); + + // With 7,776 words and 2,000 draws the distinct count is ~1,700; >500 confirms broad, + // non-degenerate sampling without being flaky. + Assert.That(seen.Count, Is.GreaterThan(500)); + } + + [Test] + public void Di_BindsPassphraseFromConfiguration() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + ["Passphrase:WordCount"] = "5", + ["Passphrase:Separator"] = ".", + ["Passphrase:IncludeNumber"] = "false" + }) + .Build(); + + var services = new ServiceCollection(); + services.AddPasswordGenerator(configuration); + + using var provider = services.BuildServiceProvider(); + var generator = provider.GetRequiredService(); + + var parts = generator.Next().Split('.'); + Assert.That(parts.Length, Is.EqualTo(5)); // 5 words, no trailing number + } + } +} diff --git a/PasswordGenerator.Tests/Phase4Tests.cs b/PasswordGenerator.Tests/Phase4Tests.cs index 96bc280..579f0db 100644 --- a/PasswordGenerator.Tests/Phase4Tests.cs +++ b/PasswordGenerator.Tests/Phase4Tests.cs @@ -129,13 +129,16 @@ public void ForEnvironmentName_IsLowercaseDigitsWithoutAmbiguous() [Test] public void ForPassphrase_ProducesRequestedWordsPlusNumber() { - var generator = Password.ForPassphrase(4, '-', capitalize: false, includeNumber: true); + // Use '.' as the separator: a handful of EFF words are themselves hyphenated + // (e.g. "t-shirt"), so splitting on '-' would over-split the phrase. + var generator = Password.ForPassphrase(4, '.', capitalize: false, includeNumber: true); var phrase = generator.Next(); - var parts = phrase.Split('-'); + var parts = phrase.Split('.'); Assert.That(parts.Length, Is.EqualTo(5)); // 4 words + trailing number Assert.That(int.TryParse(parts[4], out _), Is.True, phrase); - Assert.That(parts.Take(4).All(p => p.All(char.IsLetter)), Is.True, phrase); + Assert.That(parts.Take(4).All(p => p.Length > 0 && p.All(c => char.IsLetter(c) || c == '-')), + Is.True, phrase); } // ----- DI / appSettings precedence ----- diff --git a/PasswordGenerator.Tests/WordListTests.cs b/PasswordGenerator.Tests/WordListTests.cs new file mode 100644 index 0000000..e7fa0c4 --- /dev/null +++ b/PasswordGenerator.Tests/WordListTests.cs @@ -0,0 +1,47 @@ +using System; +using System.Linq; +using NUnit.Framework; + +namespace PasswordGenerator.Tests +{ + public class WordListTests + { + // The EFF Large Wordlist is exactly 7,776 words; the entropy claims in + // PassphraseGenerator depend on this count, so guard it explicitly. + [Test] + public void WordList_HasExactlyEffLargeCount() + { + Assert.That(WordList.Words.Length, Is.EqualTo(7776)); + } + + [Test] + public void WordList_HasNoDuplicates() + { + var distinct = WordList.Words.Distinct(StringComparer.Ordinal).Count(); + Assert.That(distinct, Is.EqualTo(WordList.Words.Length)); + } + + [Test] + public void WordList_WordsAreLowercaseLettersOrHyphen() + { + // The EFF list contains four legitimately hyphenated entries + // (drop-down, felt-tip, t-shirt, yo-yo); everything else is a-z. + foreach (var word in WordList.Words) + Assert.That(word.All(c => (c >= 'a' && c <= 'z') || c == '-'), Is.True, word); + } + + [Test] + public void WordList_WordLengthsAreWithinEffBounds() + { + foreach (var word in WordList.Words) + Assert.That(word.Length, Is.InRange(3, 9), word); + } + + [Test] + public void WordList_PerWordEntropyIsAboutTwelveNineBits() + { + var bitsPerWord = Math.Log(WordList.Words.Length, 2); + Assert.That(bitsPerWord, Is.EqualTo(12.925).Within(0.001)); + } + } +} diff --git a/PasswordGenerator/IPasswordGenerator.cs b/PasswordGenerator/IPasswordGenerator.cs index e3651c9..69c17a5 100644 --- a/PasswordGenerator/IPasswordGenerator.cs +++ b/PasswordGenerator/IPasswordGenerator.cs @@ -35,5 +35,8 @@ public interface IPasswordGenerator /// Generates passwords, observing . ValueTask> GenerateAsync(int count, CancellationToken cancellationToken = default); + + /// Estimates the strength, in bits, of the output produced by this generator. + double EstimateEntropyBits(); } } diff --git a/PasswordGenerator/PassphraseGenerator.cs b/PasswordGenerator/PassphraseGenerator.cs index 00549e1..2f16631 100644 --- a/PasswordGenerator/PassphraseGenerator.cs +++ b/PasswordGenerator/PassphraseGenerator.cs @@ -18,16 +18,30 @@ public class PassphraseGenerator : IPasswordGenerator, IDisposable /// Creates a passphrase generator. /// The number of words in each passphrase; must be at least one. - /// The character placed between words (and before the trailing number). + /// + /// The character placed between words (and before the trailing number). Note that a few EFF + /// words contain a hyphen (e.g. "t-shirt"), so if you need to split the output back into words + /// choose a separator that does not occur in any word, such as '.' or a space. + /// /// Whether to capitalize the first letter of each word. /// Whether to append a random two-digit number. + /// + /// Whether to attach a random symbol to one randomly chosen word, so the phrase satisfies + /// "must contain a symbol" composition rules while staying memorable. + /// + /// + /// An optional entropy floor. When greater than zero, the configuration is rejected if its + /// estimated entropy is below this many bits, so callers cannot silently produce weak phrases. + /// /// /// An optional random source. When supplied, the caller owns it; otherwise a /// is created and owned by this instance. /// /// is less than one. + /// The estimated entropy is below . public PassphraseGenerator(int wordCount = 4, char separator = '-', bool capitalize = false, - bool includeNumber = true, IRandomSource? randomSource = null) + bool includeNumber = true, bool includeSymbol = false, double minimumEntropyBits = 0, + IRandomSource? randomSource = null) { if (wordCount < 1) throw new ArgumentOutOfRangeException(nameof(wordCount), "A passphrase needs at least one word."); @@ -36,8 +50,17 @@ public PassphraseGenerator(int wordCount = 4, char separator = '-', bool capital Separator = separator; Capitalize = capitalize; IncludeNumber = includeNumber; + IncludeSymbol = includeSymbol; + MinimumEntropyBits = minimumEntropyBits; _random = randomSource ?? new CryptoRandomSource(); _ownsRandom = randomSource == null; + + if (minimumEntropyBits > 0 && EstimateEntropyBits() < minimumEntropyBits) + throw new ArgumentException( + $"This passphrase yields about {EstimateEntropyBits():F1} bits of entropy, below the " + + $"required minimum of {minimumEntropyBits:F1} bits. Use more words " + + $"(at least {WordCountForEntropy(minimumEntropyBits, includeNumber)}).", + nameof(minimumEntropyBits)); } /// The number of words in each passphrase. @@ -52,6 +75,15 @@ public PassphraseGenerator(int wordCount = 4, char separator = '-', bool capital /// Whether a random two-digit number is appended. public bool IncludeNumber { get; } + /// Whether a random symbol is attached to one randomly chosen word. + public bool IncludeSymbol { get; } + + /// The entropy floor enforced at construction, in bits; zero means no floor. + public double MinimumEntropyBits { get; } + + /// The symbols eligible for injection when is set. + private const string Symbols = "!@#$%&*?"; + /// The number of passphrases produced by the parameterless overload. public int DefaultBatchCount { get; set; } = 1; @@ -60,6 +92,16 @@ public string Next() { var sb = new StringBuilder(); + // Pick which word gets the symbol (and which symbol) up front, so placement varies + // and the choice is unpredictable rather than always trailing. + var symbolWordIndex = -1; + var symbol = '\0'; + if (IncludeSymbol) + { + symbolWordIndex = _random.NextInt(WordCount); + symbol = Symbols[_random.NextInt(Symbols.Length)]; + } + for (var i = 0; i < WordCount; i++) { if (i > 0) sb.Append(Separator); @@ -74,6 +116,8 @@ public string Next() { sb.Append(word); } + + if (i == symbolWordIndex) sb.Append(symbol); } if (IncludeNumber) @@ -145,14 +189,34 @@ public ValueTask> GenerateAsync(int count, CancellationTok return new ValueTask>(passphrases); } - /// Estimates passphrase entropy in bits from the word-list size, word count, and trailing number. + /// + /// Estimates passphrase entropy in bits from the word-list size and word count, plus the + /// trailing number (90 possible values, 10-99) and the injected symbol (its value and which + /// word it lands on) when those are enabled. + /// public double EstimateEntropyBits() { var bits = WordCount * Math.Log(WordList.Words.Length, 2); if (IncludeNumber) bits += Math.Log(90, 2); + if (IncludeSymbol) bits += Math.Log(Symbols.Length, 2) + Math.Log(WordCount, 2); return bits; } + /// + /// Returns the smallest word count whose estimated entropy is at least + /// , accounting for the trailing number when requested. + /// + /// The desired minimum entropy in bits. + /// Whether a trailing two-digit number will also be included. + public static int WordCountForEntropy(double targetBits, bool includeNumber = true) + { + var remaining = targetBits - (includeNumber ? Math.Log(90, 2) : 0); + if (remaining <= 0) return 1; + + var bitsPerWord = Math.Log(WordList.Words.Length, 2); + return Math.Max(1, (int)Math.Ceiling(remaining / bitsPerWord)); + } + /// Disposes the random source when this instance owns it (i.e. it was not supplied by the caller). public void Dispose() { diff --git a/PasswordGenerator/PassphraseOptions.cs b/PasswordGenerator/PassphraseOptions.cs new file mode 100644 index 0000000..c5cf6f5 --- /dev/null +++ b/PasswordGenerator/PassphraseOptions.cs @@ -0,0 +1,28 @@ +namespace PasswordGenerator +{ + /// + /// Configuration for passphrase generation, used when registering via dependency injection or + /// binding from configuration (e.g. the "Passphrase" section of appSettings.json). When this is + /// set on , the registered generator produces passphrases. + /// + public class PassphraseOptions + { + /// The number of words in each passphrase. Defaults to 4. + public int WordCount { get; set; } = 4; + + /// The character placed between words. Defaults to '-'. + public char Separator { get; set; } = '-'; + + /// Whether the first letter of each word is capitalized. + public bool Capitalize { get; set; } + + /// Whether a random two-digit number is appended. Defaults to . + public bool IncludeNumber { get; set; } = true; + + /// Whether a random symbol is attached to one randomly chosen word. + public bool IncludeSymbol { get; set; } + + /// An optional entropy floor in bits; zero (the default) means no floor. + public double MinimumEntropyBits { get; set; } + } +} diff --git a/PasswordGenerator/Password.cs b/PasswordGenerator/Password.cs index 8cc48f5..d01f022 100644 --- a/PasswordGenerator/Password.cs +++ b/PasswordGenerator/Password.cs @@ -456,11 +456,47 @@ public static IPassword ForEnvironmentName(int length = 12) .LengthRequired(length); } - /// Diceware-style passphrase built from a built-in word list. + /// Diceware-style passphrase built from the EFF Large Wordlist. + /// The number of words in the passphrase. + /// The character placed between words. + /// Whether to capitalize the first letter of each word. + /// Whether to append a random two-digit number. + /// Whether to attach a random symbol to one randomly chosen word. + /// + /// An optional entropy floor; when greater than zero the configuration is rejected if it + /// falls below this many bits. + /// public static IPasswordGenerator ForPassphrase(int words = 4, char separator = '-', - bool capitalize = false, bool includeNumber = true) + bool capitalize = false, bool includeNumber = true, bool includeSymbol = false, + double minimumEntropyBits = 0) { - return new PassphraseGenerator(words, separator, capitalize, includeNumber); + return new PassphraseGenerator(words, separator, capitalize, includeNumber, includeSymbol, + minimumEntropyBits); + } + + /// + /// Diceware-style passphrase with at least bits of entropy. + /// The word count is derived from the word-list size, and the same value is enforced as a floor. + /// + /// The minimum entropy in bits (defaults to 80, a strong target). + /// The character placed between words. + /// Whether to capitalize the first letter of each word. + /// Whether to append a random two-digit number. + /// Whether to attach a random symbol to one randomly chosen word. + public static IPasswordGenerator ForPassphraseWithEntropy(double targetBits = 80, char separator = '-', + bool capitalize = false, bool includeNumber = true, bool includeSymbol = false) + { + var words = PassphraseGenerator.WordCountForEntropy(targetBits, includeNumber); + return new PassphraseGenerator(words, separator, capitalize, includeNumber, includeSymbol, targetBits); + } + + /// + /// A memorable, high-strength passphrase preset: capitalized words with a trailing number, + /// sized to at least 80 bits of entropy. + /// + public static IPasswordGenerator ForMemorable() + { + return ForPassphraseWithEntropy(80, separator: '-', capitalize: true, includeNumber: true); } } } diff --git a/PasswordGenerator/PasswordGenerator.csproj b/PasswordGenerator/PasswordGenerator.csproj index a4c08df..903a0f3 100644 --- a/PasswordGenerator/PasswordGenerator.csproj +++ b/PasswordGenerator/PasswordGenerator.csproj @@ -41,6 +41,10 @@ + + + + diff --git a/PasswordGenerator/PasswordGeneratorServiceCollectionExtensions.cs b/PasswordGenerator/PasswordGeneratorServiceCollectionExtensions.cs index fa3e13e..ac67552 100644 --- a/PasswordGenerator/PasswordGeneratorServiceCollectionExtensions.cs +++ b/PasswordGenerator/PasswordGeneratorServiceCollectionExtensions.cs @@ -42,8 +42,20 @@ private static IServiceCollection AddCore(IServiceCollection services, PasswordO return services; } - private static Password CreateGenerator(PasswordOptions options, IRandomSource randomSource) + private static IPasswordGenerator CreateGenerator(PasswordOptions options, IRandomSource randomSource) { + if (options.Passphrase != null) + { + var p = options.Passphrase; + // The random source is a DI singleton owned by the container, so it is passed in and + // must not be disposed by the generator. + return new PassphraseGenerator(p.WordCount, p.Separator, p.Capitalize, p.IncludeNumber, + p.IncludeSymbol, p.MinimumEntropyBits, randomSource) + { + DefaultBatchCount = options.DefaultBatchCount + }; + } + // Build with the non-special classes first, then layer special characters on (default or // custom) so the combined character set is assembled correctly. var settings = new PasswordSettings(options.IncludeLowercase, options.IncludeUppercase, diff --git a/PasswordGenerator/PasswordOptions.cs b/PasswordGenerator/PasswordOptions.cs index a025bbe..499205b 100644 --- a/PasswordGenerator/PasswordOptions.cs +++ b/PasswordGenerator/PasswordOptions.cs @@ -29,5 +29,11 @@ public class PasswordOptions /// The number of passwords produced by the parameterless Generate() overload. public int DefaultBatchCount { get; set; } = 1; + + /// + /// When set, the registered generator produces passphrases (from the EFF Large Wordlist) + /// instead of character passwords, and the character-pool options above are ignored. + /// + public PassphraseOptions? Passphrase { get; set; } } } diff --git a/PasswordGenerator/WordList.cs b/PasswordGenerator/WordList.cs index 1d03b3f..51ef08f 100644 --- a/PasswordGenerator/WordList.cs +++ b/PasswordGenerator/WordList.cs @@ -1,53 +1,1019 @@ +// ----------------------------------------------------------------------------- +// EFF Large Wordlist +// +// The word data in this file is the "EFF Large Wordlist" created by the +// Electronic Frontier Foundation (Joseph Bonneau) and published at: +// https://www.eff.org/dice +// https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt +// +// The word list is licensed by the EFF under the Creative Commons +// Attribution 3.0 United States license (CC BY 3.0 US): +// https://creativecommons.org/licenses/by/3.0/us/ +// +// Modifications: the original tab-separated "dice-numberword" rows have +// been reformatted into the C# string array below. The words themselves are +// unchanged. See THIRD-PARTY-NOTICES.md for full attribution. +// +// The rest of this project is licensed under the MIT License (see License.md). +// ----------------------------------------------------------------------------- + namespace PasswordGenerator { /// - /// A small built-in list of common, readable words used by . - /// This is intentionally compact (not a full diceware list); each word contributes - /// log2(.Length) bits of entropy. + /// The EFF Large Wordlist (7,776 words) used by . + /// Each word contributes log2(7776) ~= 12.925 bits of entropy when chosen uniformly + /// at random. The list is curated by the EFF for memorability and to avoid confusable + /// or offensive words. See the header of this file and THIRD-PARTY-NOTICES.md for the + /// CC BY 3.0 attribution. /// internal static class WordList { public static readonly string[] Words = { - "able", "acid", "acorn", "actor", "agile", "alarm", "album", "alert", "alley", "amber", - "amend", "angle", "ankle", "apple", "april", "arena", "armor", "arrow", "aside", "asset", - "atlas", "audio", "aunt", "avoid", "awake", "award", "bacon", "badge", "baker", "banjo", - "barge", "basil", "basin", "beach", "beard", "beast", "begin", "berry", "birch", "bison", - "blade", "blaze", "blend", "blink", "block", "bloom", "board", "boost", "booth", "brace", - "brain", "brand", "brave", "bread", "brick", "brief", "broad", "brook", "brush", "buddy", - "bunch", "cabin", "cable", "cacao", "camel", "candy", "canoe", "cargo", "carol", "carve", - "catch", "cedar", "chalk", "charm", "chase", "cheek", "chess", "chief", "chili", "chime", - "civic", "claim", "clamp", "clay", "clean", "clear", "cliff", "climb", "clock", "cloud", - "clove", "coast", "cobra", "cocoa", "comet", "coral", "couch", "cover", "crane", "crate", - "crisp", "crown", "crumb", "curve", "daisy", "dance", "delta", "diner", "ditch", "diver", - "dodge", "donor", "draft", "drama", "dream", "dress", "drift", "drink", "drive", "eagle", - "early", "earth", "ember", "emery", "enjoy", "equal", "ethos", "every", "fable", "fancy", - "feast", "fiber", "field", "final", "flame", "flank", "flash", "fleet", "flint", "float", - "flock", "flora", "flute", "focus", "forge", "frame", "frost", "fruit", "gauge", "ghost", - "giant", "glade", "glass", "glide", "globe", "glory", "grace", "grain", "grand", "grape", - "grasp", "grass", "green", "grove", "guide", "habit", "happy", "harbor", "haven", "hazel", - "heart", "hedge", "honey", "horse", "hotel", "house", "human", "humor", "ideal", "image", - "index", "inlet", "ivory", "jelly", "jewel", "jolly", "joust", "judge", "juice", "karma", - "kayak", "ketch", "kitten", "knack", "knife", "koala", "label", "lance", "laser", "latch", - "layer", "leaf", "ledge", "lemon", "lever", "light", "lilac", "linen", "llama", "lodge", - "lotus", "lunar", "lyric", "magic", "maize", "mango", "maple", "march", "marsh", "match", - "medal", "melon", "mercy", "metro", "manor", "mocha", "model", "money", "month", "motor", - "mound", "mount", "mouse", "music", "noble", "north", "novel", "ocean", "olive", "onion", - "opera", "orbit", "otter", "owl", "paint", "panda", "paper", "party", "pasta", "patch", - "peach", "pearl", "pedal", "perch", "piano", "pilot", "pixel", "pizza", "plank", "plant", - "plaza", "plume", "polar", "porch", "prism", "prize", "proud", "pulse", "punch", "quail", - "quartz", "queen", "quest", "quiet", "quill", "quilt", "radar", "rapid", "raven", "reach", - "realm", "rebel", "relay", "rhino", "ridge", "river", "roast", "robin", "rocky", "rover", - "royal", "ruby", "salad", "salsa", "sandy", "scarf", "scout", "shade", "shard", "shark", - "sheep", "shelf", "shell", "shine", "shore", "siren", "skate", "skiff", "slate", "sleek", - "slope", "smile", "smoke", "snail", "solar", "sonic", "spade", "spark", "spice", "spine", - "spire", "spoon", "sport", "spray", "spruce", "stack", "stage", "stalk", "stamp", "stark", - "steam", "steel", "stork", "storm", "story", "stove", "straw", "strip", "sugar", "swift", - "table", "tango", "teal", "thorn", "tidal", "tiger", "toast", "topaz", "torch", "totem", - "tower", "trail", "treat", "trend", "tribe", "trout", "tulip", "tundra", "ultra", "umber", - "unity", "urban", "valley", "value", "vapor", "vault", "venus", "vigor", "villa", "vinyl", - "viola", "vivid", "vocal", "wafer", "wagon", "waltz", "water", "wheat", "whale", "wharf", - "wheel", "whisk", "willow", "windy", "woven", "yacht", "yearn", "yield", "zebra", "zesty" + "abacus", "abdomen", "abdominal", "abide", "abiding", "ability", "ablaze", "able", + "abnormal", "abrasion", "abrasive", "abreast", "abridge", "abroad", "abruptly", "absence", + "absentee", "absently", "absinthe", "absolute", "absolve", "abstain", "abstract", "absurd", + "accent", "acclaim", "acclimate", "accompany", "account", "accuracy", "accurate", + "accustom", "acetone", "achiness", "aching", "acid", "acorn", "acquaint", "acquire", + "acre", "acrobat", "acronym", "acting", "action", "activate", "activator", "active", + "activism", "activist", "activity", "actress", "acts", "acutely", "acuteness", "aeration", + "aerobics", "aerosol", "aerospace", "afar", "affair", "affected", "affecting", "affection", + "affidavit", "affiliate", "affirm", "affix", "afflicted", "affluent", "afford", "affront", + "aflame", "afloat", "aflutter", "afoot", "afraid", "afterglow", "afterlife", "aftermath", + "aftermost", "afternoon", "aged", "ageless", "agency", "agenda", "agent", "aggregate", + "aghast", "agile", "agility", "aging", "agnostic", "agonize", "agonizing", "agony", + "agreeable", "agreeably", "agreed", "agreeing", "agreement", "aground", "ahead", "ahoy", + "aide", "aids", "aim", "ajar", "alabaster", "alarm", "albatross", "album", "alfalfa", + "algebra", "algorithm", "alias", "alibi", "alienable", "alienate", "aliens", "alike", + "alive", "alkaline", "alkalize", "almanac", "almighty", "almost", "aloe", "aloft", "aloha", + "alone", "alongside", "aloof", "alphabet", "alright", "although", "altitude", "alto", + "aluminum", "alumni", "always", "amaretto", "amaze", "amazingly", "amber", "ambiance", + "ambiguity", "ambiguous", "ambition", "ambitious", "ambulance", "ambush", "amendable", + "amendment", "amends", "amenity", "amiable", "amicably", "amid", "amigo", "amino", "amiss", + "ammonia", "ammonium", "amnesty", "amniotic", "among", "amount", "amperage", "ample", + "amplifier", "amplify", "amply", "amuck", "amulet", "amusable", "amused", "amusement", + "amuser", "amusing", "anaconda", "anaerobic", "anagram", "anatomist", "anatomy", "anchor", + "anchovy", "ancient", "android", "anemia", "anemic", "aneurism", "anew", "angelfish", + "angelic", "anger", "angled", "angler", "angles", "angling", "angrily", "angriness", + "anguished", "angular", "animal", "animate", "animating", "animation", "animator", "anime", + "animosity", "ankle", "annex", "annotate", "announcer", "annoying", "annually", "annuity", + "anointer", "another", "answering", "antacid", "antarctic", "anteater", "antelope", + "antennae", "anthem", "anthill", "anthology", "antibody", "antics", "antidote", "antihero", + "antiquely", "antiques", "antiquity", "antirust", "antitoxic", "antitrust", "antiviral", + "antivirus", "antler", "antonym", "antsy", "anvil", "anybody", "anyhow", "anymore", + "anyone", "anyplace", "anything", "anytime", "anyway", "anywhere", "aorta", "apache", + "apostle", "appealing", "appear", "appease", "appeasing", "appendage", "appendix", + "appetite", "appetizer", "applaud", "applause", "apple", "appliance", "applicant", + "applied", "apply", "appointee", "appraisal", "appraiser", "apprehend", "approach", + "approval", "approve", "apricot", "april", "apron", "aptitude", "aptly", "aqua", + "aqueduct", "arbitrary", "arbitrate", "ardently", "area", "arena", "arguable", "arguably", + "argue", "arise", "armadillo", "armband", "armchair", "armed", "armful", "armhole", + "arming", "armless", "armoire", "armored", "armory", "armrest", "army", "aroma", "arose", + "around", "arousal", "arrange", "array", "arrest", "arrival", "arrive", "arrogance", + "arrogant", "arson", "art", "ascend", "ascension", "ascent", "ascertain", "ashamed", + "ashen", "ashes", "ashy", "aside", "askew", "asleep", "asparagus", "aspect", "aspirate", + "aspire", "aspirin", "astonish", "astound", "astride", "astrology", "astronaut", + "astronomy", "astute", "atlantic", "atlas", "atom", "atonable", "atop", "atrium", + "atrocious", "atrophy", "attach", "attain", "attempt", "attendant", "attendee", + "attention", "attentive", "attest", "attic", "attire", "attitude", "attractor", + "attribute", "atypical", "auction", "audacious", "audacity", "audible", "audibly", + "audience", "audio", "audition", "augmented", "august", "authentic", "author", "autism", + "autistic", "autograph", "automaker", "automated", "automatic", "autopilot", "available", + "avalanche", "avatar", "avenge", "avenging", "avenue", "average", "aversion", "avert", + "aviation", "aviator", "avid", "avoid", "await", "awaken", "award", "aware", "awhile", + "awkward", "awning", "awoke", "awry", "axis", "babble", "babbling", "babied", "baboon", + "backache", "backboard", "backboned", "backdrop", "backed", "backer", "backfield", + "backfire", "backhand", "backing", "backlands", "backlash", "backless", "backlight", + "backlit", "backlog", "backpack", "backpedal", "backrest", "backroom", "backshift", + "backside", "backslid", "backspace", "backspin", "backstab", "backstage", "backtalk", + "backtrack", "backup", "backward", "backwash", "backwater", "backyard", "bacon", + "bacteria", "bacterium", "badass", "badge", "badland", "badly", "badness", "baffle", + "baffling", "bagel", "bagful", "baggage", "bagged", "baggie", "bagginess", "bagging", + "baggy", "bagpipe", "baguette", "baked", "bakery", "bakeshop", "baking", "balance", + "balancing", "balcony", "balmy", "balsamic", "bamboo", "banana", "banish", "banister", + "banjo", "bankable", "bankbook", "banked", "banker", "banking", "banknote", "bankroll", + "banner", "bannister", "banshee", "banter", "barbecue", "barbed", "barbell", "barber", + "barcode", "barge", "bargraph", "barista", "baritone", "barley", "barmaid", "barman", + "barn", "barometer", "barrack", "barracuda", "barrel", "barrette", "barricade", "barrier", + "barstool", "bartender", "barterer", "bash", "basically", "basics", "basil", "basin", + "basis", "basket", "batboy", "batch", "bath", "baton", "bats", "battalion", "battered", + "battering", "battery", "batting", "battle", "bauble", "bazooka", "blabber", "bladder", + "blade", "blah", "blame", "blaming", "blanching", "blandness", "blank", "blaspheme", + "blasphemy", "blast", "blatancy", "blatantly", "blazer", "blazing", "bleach", "bleak", + "bleep", "blemish", "blend", "bless", "blighted", "blimp", "bling", "blinked", "blinker", + "blinking", "blinks", "blip", "blissful", "blitz", "blizzard", "bloated", "bloating", + "blob", "blog", "bloomers", "blooming", "blooper", "blot", "blouse", "blubber", "bluff", + "bluish", "blunderer", "blunt", "blurb", "blurred", "blurry", "blurt", "blush", "blustery", + "boaster", "boastful", "boasting", "boat", "bobbed", "bobbing", "bobble", "bobcat", + "bobsled", "bobtail", "bodacious", "body", "bogged", "boggle", "bogus", "boil", "bok", + "bolster", "bolt", "bonanza", "bonded", "bonding", "bondless", "boned", "bonehead", + "boneless", "bonelike", "boney", "bonfire", "bonnet", "bonsai", "bonus", "bony", + "boogeyman", "boogieman", "book", "boondocks", "booted", "booth", "bootie", "booting", + "bootlace", "bootleg", "boots", "boozy", "borax", "boring", "borough", "borrower", + "borrowing", "boss", "botanical", "botanist", "botany", "botch", "both", "bottle", + "bottling", "bottom", "bounce", "bouncing", "bouncy", "bounding", "boundless", "bountiful", + "bovine", "boxcar", "boxer", "boxing", "boxlike", "boxy", "breach", "breath", "breeches", + "breeching", "breeder", "breeding", "breeze", "breezy", "brethren", "brewery", "brewing", + "briar", "bribe", "brick", "bride", "bridged", "brigade", "bright", "brilliant", "brim", + "bring", "brink", "brisket", "briskly", "briskness", "bristle", "brittle", "broadband", + "broadcast", "broaden", "broadly", "broadness", "broadside", "broadways", "broiler", + "broiling", "broken", "broker", "bronchial", "bronco", "bronze", "bronzing", "brook", + "broom", "brought", "browbeat", "brownnose", "browse", "browsing", "bruising", "brunch", + "brunette", "brunt", "brush", "brussels", "brute", "brutishly", "bubble", "bubbling", + "bubbly", "buccaneer", "bucked", "bucket", "buckle", "buckshot", "buckskin", "bucktooth", + "buckwheat", "buddhism", "buddhist", "budding", "buddy", "budget", "buffalo", "buffed", + "buffer", "buffing", "buffoon", "buggy", "bulb", "bulge", "bulginess", "bulgur", "bulk", + "bulldog", "bulldozer", "bullfight", "bullfrog", "bullhorn", "bullion", "bullish", + "bullpen", "bullring", "bullseye", "bullwhip", "bully", "bunch", "bundle", "bungee", + "bunion", "bunkbed", "bunkhouse", "bunkmate", "bunny", "bunt", "busboy", "bush", "busily", + "busload", "bust", "busybody", "buzz", "cabana", "cabbage", "cabbie", "cabdriver", "cable", + "caboose", "cache", "cackle", "cacti", "cactus", "caddie", "caddy", "cadet", "cadillac", + "cadmium", "cage", "cahoots", "cake", "calamari", "calamity", "calcium", "calculate", + "calculus", "caliber", "calibrate", "calm", "caloric", "calorie", "calzone", "camcorder", + "cameo", "camera", "camisole", "camper", "campfire", "camping", "campsite", "campus", + "canal", "canary", "cancel", "candied", "candle", "candy", "cane", "canine", "canister", + "cannabis", "canned", "canning", "cannon", "cannot", "canola", "canon", "canopener", + "canopy", "canteen", "canyon", "capable", "capably", "capacity", "cape", "capillary", + "capital", "capitol", "capped", "capricorn", "capsize", "capsule", "caption", "captivate", + "captive", "captivity", "capture", "caramel", "carat", "caravan", "carbon", "cardboard", + "carded", "cardiac", "cardigan", "cardinal", "cardstock", "carefully", "caregiver", + "careless", "caress", "caretaker", "cargo", "caring", "carless", "carload", "carmaker", + "carnage", "carnation", "carnival", "carnivore", "carol", "carpenter", "carpentry", + "carpool", "carport", "carried", "carrot", "carrousel", "carry", "cartel", "cartload", + "carton", "cartoon", "cartridge", "cartwheel", "carve", "carving", "carwash", "cascade", + "case", "cash", "casing", "casino", "casket", "cassette", "casually", "casualty", + "catacomb", "catalog", "catalyst", "catalyze", "catapult", "cataract", "catatonic", + "catcall", "catchable", "catcher", "catching", "catchy", "caterer", "catering", "catfight", + "catfish", "cathedral", "cathouse", "catlike", "catnap", "catnip", "catsup", "cattail", + "cattishly", "cattle", "catty", "catwalk", "caucasian", "caucus", "causal", "causation", + "cause", "causing", "cauterize", "caution", "cautious", "cavalier", "cavalry", "caviar", + "cavity", "cedar", "celery", "celestial", "celibacy", "celibate", "celtic", "cement", + "census", "ceramics", "ceremony", "certainly", "certainty", "certified", "certify", + "cesarean", "cesspool", "chafe", "chaffing", "chain", "chair", "chalice", "challenge", + "chamber", "chamomile", "champion", "chance", "change", "channel", "chant", "chaos", + "chaperone", "chaplain", "chapped", "chaps", "chapter", "character", "charbroil", + "charcoal", "charger", "charging", "chariot", "charity", "charm", "charred", "charter", + "charting", "chase", "chasing", "chaste", "chastise", "chastity", "chatroom", "chatter", + "chatting", "chatty", "cheating", "cheddar", "cheek", "cheer", "cheese", "cheesy", "chef", + "chemicals", "chemist", "chemo", "cherisher", "cherub", "chess", "chest", "chevron", + "chevy", "chewable", "chewer", "chewing", "chewy", "chief", "chihuahua", "childcare", + "childhood", "childish", "childless", "childlike", "chili", "chill", "chimp", "chip", + "chirping", "chirpy", "chitchat", "chivalry", "chive", "chloride", "chlorine", "choice", + "chokehold", "choking", "chomp", "chooser", "choosing", "choosy", "chop", "chosen", + "chowder", "chowtime", "chrome", "chubby", "chuck", "chug", "chummy", "chump", "chunk", + "churn", "chute", "cider", "cilantro", "cinch", "cinema", "cinnamon", "circle", "circling", + "circular", "circulate", "circus", "citable", "citadel", "citation", "citizen", "citric", + "citrus", "city", "civic", "civil", "clad", "claim", "clambake", "clammy", "clamor", + "clamp", "clamshell", "clang", "clanking", "clapped", "clapper", "clapping", "clarify", + "clarinet", "clarity", "clash", "clasp", "class", "clatter", "clause", "clavicle", "claw", + "clay", "clean", "clear", "cleat", "cleaver", "cleft", "clench", "clergyman", "clerical", + "clerk", "clever", "clicker", "client", "climate", "climatic", "cling", "clinic", + "clinking", "clip", "clique", "cloak", "clobber", "clock", "clone", "cloning", "closable", + "closure", "clothes", "clothing", "cloud", "clover", "clubbed", "clubbing", "clubhouse", + "clump", "clumsily", "clumsy", "clunky", "clustered", "clutch", "clutter", "coach", + "coagulant", "coastal", "coaster", "coasting", "coastland", "coastline", "coat", + "coauthor", "cobalt", "cobbler", "cobweb", "cocoa", "coconut", "cod", "coeditor", "coerce", + "coexist", "coffee", "cofounder", "cognition", "cognitive", "cogwheel", "coherence", + "coherent", "cohesive", "coil", "coke", "cola", "cold", "coleslaw", "coliseum", "collage", + "collapse", "collar", "collected", "collector", "collide", "collie", "collision", + "colonial", "colonist", "colonize", "colony", "colossal", "colt", "coma", "come", + "comfort", "comfy", "comic", "coming", "comma", "commence", "commend", "comment", + "commerce", "commode", "commodity", "commodore", "common", "commotion", "commute", + "commuting", "compacted", "compacter", "compactly", "compactor", "companion", "company", + "compare", "compel", "compile", "comply", "component", "composed", "composer", "composite", + "compost", "composure", "compound", "compress", "comprised", "computer", "computing", + "comrade", "concave", "conceal", "conceded", "concept", "concerned", "concert", "conch", + "concierge", "concise", "conclude", "concrete", "concur", "condense", "condiment", + "condition", "condone", "conducive", "conductor", "conduit", "cone", "confess", "confetti", + "confidant", "confident", "confider", "confiding", "configure", "confined", "confining", + "confirm", "conflict", "conform", "confound", "confront", "confused", "confusing", + "confusion", "congenial", "congested", "congrats", "congress", "conical", "conjoined", + "conjure", "conjuror", "connected", "connector", "consensus", "consent", "console", + "consoling", "consonant", "constable", "constant", "constrain", "constrict", "construct", + "consult", "consumer", "consuming", "contact", "container", "contempt", "contend", + "contented", "contently", "contents", "contest", "context", "contort", "contour", + "contrite", "control", "contusion", "convene", "convent", "copartner", "cope", "copied", + "copier", "copilot", "coping", "copious", "copper", "copy", "coral", "cork", "cornball", + "cornbread", "corncob", "cornea", "corned", "corner", "cornfield", "cornflake", "cornhusk", + "cornmeal", "cornstalk", "corny", "coronary", "coroner", "corporal", "corporate", "corral", + "correct", "corridor", "corrode", "corroding", "corrosive", "corsage", "corset", "cortex", + "cosigner", "cosmetics", "cosmic", "cosmos", "cosponsor", "cost", "cottage", "cotton", + "couch", "cough", "could", "countable", "countdown", "counting", "countless", "country", + "county", "courier", "covenant", "cover", "coveted", "coveting", "coyness", "cozily", + "coziness", "cozy", "crabbing", "crabgrass", "crablike", "crabmeat", "cradle", "cradling", + "crafter", "craftily", "craftsman", "craftwork", "crafty", "cramp", "cranberry", "crane", + "cranial", "cranium", "crank", "crate", "crave", "craving", "crawfish", "crawlers", + "crawling", "crayfish", "crayon", "crazed", "crazily", "craziness", "crazy", "creamed", + "creamer", "creamlike", "crease", "creasing", "creatable", "create", "creation", + "creative", "creature", "credible", "credibly", "credit", "creed", "creme", "creole", + "crepe", "crept", "crescent", "crested", "cresting", "crestless", "crevice", "crewless", + "crewman", "crewmate", "crib", "cricket", "cried", "crier", "crimp", "crimson", "cringe", + "cringing", "crinkle", "crinkly", "crisped", "crisping", "crisply", "crispness", "crispy", + "criteria", "critter", "croak", "crock", "crook", "croon", "crop", "cross", "crouch", + "crouton", "crowbar", "crowd", "crown", "crucial", "crudely", "crudeness", "cruelly", + "cruelness", "cruelty", "crumb", "crummiest", "crummy", "crumpet", "crumpled", "cruncher", + "crunching", "crunchy", "crusader", "crushable", "crushed", "crusher", "crushing", "crust", + "crux", "crying", "cryptic", "crystal", "cubbyhole", "cube", "cubical", "cubicle", + "cucumber", "cuddle", "cuddly", "cufflink", "culinary", "culminate", "culpable", "culprit", + "cultivate", "cultural", "culture", "cupbearer", "cupcake", "cupid", "cupped", "cupping", + "curable", "curator", "curdle", "cure", "curfew", "curing", "curled", "curler", + "curliness", "curling", "curly", "curry", "curse", "cursive", "cursor", "curtain", + "curtly", "curtsy", "curvature", "curve", "curvy", "cushy", "cusp", "cussed", "custard", + "custodian", "custody", "customary", "customer", "customize", "customs", "cut", "cycle", + "cyclic", "cycling", "cyclist", "cylinder", "cymbal", "cytoplasm", "cytoplast", "dab", + "dad", "daffodil", "dagger", "daily", "daintily", "dainty", "dairy", "daisy", "dallying", + "dance", "dancing", "dandelion", "dander", "dandruff", "dandy", "danger", "dangle", + "dangling", "daredevil", "dares", "daringly", "darkened", "darkening", "darkish", + "darkness", "darkroom", "darling", "darn", "dart", "darwinism", "dash", "dastardly", + "data", "datebook", "dating", "daughter", "daunting", "dawdler", "dawn", "daybed", + "daybreak", "daycare", "daydream", "daylight", "daylong", "dayroom", "daytime", "dazzler", + "dazzling", "deacon", "deafening", "deafness", "dealer", "dealing", "dealmaker", "dealt", + "dean", "debatable", "debate", "debating", "debit", "debrief", "debtless", "debtor", + "debug", "debunk", "decade", "decaf", "decal", "decathlon", "decay", "deceased", "deceit", + "deceiver", "deceiving", "december", "decency", "decent", "deception", "deceptive", + "decibel", "decidable", "decimal", "decimeter", "decipher", "deck", "declared", "decline", + "decode", "decompose", "decorated", "decorator", "decoy", "decrease", "decree", "dedicate", + "dedicator", "deduce", "deduct", "deed", "deem", "deepen", "deeply", "deepness", "deface", + "defacing", "defame", "default", "defeat", "defection", "defective", "defendant", + "defender", "defense", "defensive", "deferral", "deferred", "defiance", "defiant", + "defile", "defiling", "define", "definite", "deflate", "deflation", "deflator", + "deflected", "deflector", "defog", "deforest", "defraud", "defrost", "deftly", "defuse", + "defy", "degraded", "degrading", "degrease", "degree", "dehydrate", "deity", "dejected", + "delay", "delegate", "delegator", "delete", "deletion", "delicacy", "delicate", + "delicious", "delighted", "delirious", "delirium", "deliverer", "delivery", "delouse", + "delta", "deluge", "delusion", "deluxe", "demanding", "demeaning", "demeanor", "demise", + "democracy", "democrat", "demote", "demotion", "demystify", "denatured", "deniable", + "denial", "denim", "denote", "dense", "density", "dental", "dentist", "denture", "deny", + "deodorant", "deodorize", "departed", "departure", "depict", "deplete", "depletion", + "deplored", "deploy", "deport", "depose", "depraved", "depravity", "deprecate", "depress", + "deprive", "depth", "deputize", "deputy", "derail", "deranged", "derby", "derived", + "desecrate", "deserve", "deserving", "designate", "designed", "designer", "designing", + "deskbound", "desktop", "deskwork", "desolate", "despair", "despise", "despite", "destiny", + "destitute", "destruct", "detached", "detail", "detection", "detective", "detector", + "detention", "detergent", "detest", "detonate", "detonator", "detoxify", "detract", + "deuce", "devalue", "deviancy", "deviant", "deviate", "deviation", "deviator", "device", + "devious", "devotedly", "devotee", "devotion", "devourer", "devouring", "devoutly", + "dexterity", "dexterous", "diabetes", "diabetic", "diabolic", "diagnoses", "diagnosis", + "diagram", "dial", "diameter", "diaper", "diaphragm", "diary", "dice", "dicing", "dictate", + "dictation", "dictator", "difficult", "diffused", "diffuser", "diffusion", "diffusive", + "dig", "dilation", "diligence", "diligent", "dill", "dilute", "dime", "diminish", "dimly", + "dimmed", "dimmer", "dimness", "dimple", "diner", "dingbat", "dinghy", "dinginess", + "dingo", "dingy", "dining", "dinner", "diocese", "dioxide", "diploma", "dipped", "dipper", + "dipping", "directed", "direction", "directive", "directly", "directory", "direness", + "dirtiness", "disabled", "disagree", "disallow", "disarm", "disarray", "disaster", + "disband", "disbelief", "disburse", "discard", "discern", "discharge", "disclose", + "discolor", "discount", "discourse", "discover", "discuss", "disdain", "disengage", + "disfigure", "disgrace", "dish", "disinfect", "disjoin", "disk", "dislike", "disliking", + "dislocate", "dislodge", "disloyal", "dismantle", "dismay", "dismiss", "dismount", + "disobey", "disorder", "disown", "disparate", "disparity", "dispatch", "dispense", + "dispersal", "dispersed", "disperser", "displace", "display", "displease", "disposal", + "dispose", "disprove", "dispute", "disregard", "disrupt", "dissuade", "distance", + "distant", "distaste", "distill", "distinct", "distort", "distract", "distress", + "district", "distrust", "ditch", "ditto", "ditzy", "dividable", "divided", "dividend", + "dividers", "dividing", "divinely", "diving", "divinity", "divisible", "divisibly", + "division", "divisive", "divorcee", "dizziness", "dizzy", "doable", "docile", "dock", + "doctrine", "document", "dodge", "dodgy", "doily", "doing", "dole", "dollar", "dollhouse", + "dollop", "dolly", "dolphin", "domain", "domelike", "domestic", "dominion", "dominoes", + "donated", "donation", "donator", "donor", "donut", "doodle", "doorbell", "doorframe", + "doorknob", "doorman", "doormat", "doornail", "doorpost", "doorstep", "doorstop", + "doorway", "doozy", "dork", "dormitory", "dorsal", "dosage", "dose", "dotted", "doubling", + "douche", "dove", "down", "dowry", "doze", "drab", "dragging", "dragonfly", "dragonish", + "dragster", "drainable", "drainage", "drained", "drainer", "drainpipe", "dramatic", + "dramatize", "drank", "drapery", "drastic", "draw", "dreaded", "dreadful", "dreadlock", + "dreamboat", "dreamily", "dreamland", "dreamless", "dreamlike", "dreamt", "dreamy", + "drearily", "dreary", "drench", "dress", "drew", "dribble", "dried", "drier", "drift", + "driller", "drilling", "drinkable", "drinking", "dripping", "drippy", "drivable", "driven", + "driver", "driveway", "driving", "drizzle", "drizzly", "drone", "drool", "droop", + "drop-down", "dropbox", "dropkick", "droplet", "dropout", "dropper", "drove", "drown", + "drowsily", "drudge", "drum", "dry", "dubbed", "dubiously", "duchess", "duckbill", + "ducking", "duckling", "ducktail", "ducky", "duct", "dude", "duffel", "dugout", "duh", + "duke", "duller", "dullness", "duly", "dumping", "dumpling", "dumpster", "duo", "dupe", + "duplex", "duplicate", "duplicity", "durable", "durably", "duration", "duress", "during", + "dusk", "dust", "dutiful", "duty", "duvet", "dwarf", "dweeb", "dwelled", "dweller", + "dwelling", "dwindle", "dwindling", "dynamic", "dynamite", "dynasty", "dyslexia", + "dyslexic", "each", "eagle", "earache", "eardrum", "earflap", "earful", "earlobe", "early", + "earmark", "earmuff", "earphone", "earpiece", "earplugs", "earring", "earshot", "earthen", + "earthlike", "earthling", "earthly", "earthworm", "earthy", "earwig", "easeful", "easel", + "easiest", "easily", "easiness", "easing", "eastbound", "eastcoast", "easter", "eastward", + "eatable", "eaten", "eatery", "eating", "eats", "ebay", "ebony", "ebook", "ecard", + "eccentric", "echo", "eclair", "eclipse", "ecologist", "ecology", "economic", "economist", + "economy", "ecosphere", "ecosystem", "edge", "edginess", "edging", "edgy", "edition", + "editor", "educated", "education", "educator", "eel", "effective", "effects", "efficient", + "effort", "eggbeater", "egging", "eggnog", "eggplant", "eggshell", "egomaniac", "egotism", + "egotistic", "either", "eject", "elaborate", "elastic", "elated", "elbow", "eldercare", + "elderly", "eldest", "electable", "election", "elective", "elephant", "elevate", + "elevating", "elevation", "elevator", "eleven", "elf", "eligible", "eligibly", "eliminate", + "elite", "elitism", "elixir", "elk", "ellipse", "elliptic", "elm", "elongated", "elope", + "eloquence", "eloquent", "elsewhere", "elude", "elusive", "elves", "email", "embargo", + "embark", "embassy", "embattled", "embellish", "ember", "embezzle", "emblaze", "emblem", + "embody", "embolism", "emboss", "embroider", "emcee", "emerald", "emergency", "emission", + "emit", "emote", "emoticon", "emotion", "empathic", "empathy", "emperor", "emphases", + "emphasis", "emphasize", "emphatic", "empirical", "employed", "employee", "employer", + "emporium", "empower", "emptier", "emptiness", "empty", "emu", "enable", "enactment", + "enamel", "enchanted", "enchilada", "encircle", "enclose", "enclosure", "encode", "encore", + "encounter", "encourage", "encroach", "encrust", "encrypt", "endanger", "endeared", + "endearing", "ended", "ending", "endless", "endnote", "endocrine", "endorphin", "endorse", + "endowment", "endpoint", "endurable", "endurance", "enduring", "energetic", "energize", + "energy", "enforced", "enforcer", "engaged", "engaging", "engine", "engorge", "engraved", + "engraver", "engraving", "engross", "engulf", "enhance", "enigmatic", "enjoyable", + "enjoyably", "enjoyer", "enjoying", "enjoyment", "enlarged", "enlarging", "enlighten", + "enlisted", "enquirer", "enrage", "enrich", "enroll", "enslave", "ensnare", "ensure", + "entail", "entangled", "entering", "entertain", "enticing", "entire", "entitle", "entity", + "entomb", "entourage", "entrap", "entree", "entrench", "entrust", "entryway", "entwine", + "enunciate", "envelope", "enviable", "enviably", "envious", "envision", "envoy", "envy", + "enzyme", "epic", "epidemic", "epidermal", "epidermis", "epidural", "epilepsy", + "epileptic", "epilogue", "epiphany", "episode", "equal", "equate", "equation", "equator", + "equinox", "equipment", "equity", "equivocal", "eradicate", "erasable", "erased", "eraser", + "erasure", "ergonomic", "errand", "errant", "erratic", "error", "erupt", "escalate", + "escalator", "escapable", "escapade", "escapist", "escargot", "eskimo", "esophagus", + "espionage", "espresso", "esquire", "essay", "essence", "essential", "establish", "estate", + "esteemed", "estimate", "estimator", "estranged", "estrogen", "etching", "eternal", + "eternity", "ethanol", "ether", "ethically", "ethics", "euphemism", "evacuate", "evacuee", + "evade", "evaluate", "evaluator", "evaporate", "evasion", "evasive", "even", "everglade", + "evergreen", "everybody", "everyday", "everyone", "evict", "evidence", "evident", "evil", + "evoke", "evolution", "evolve", "exact", "exalted", "example", "excavate", "excavator", + "exceeding", "exception", "excess", "exchange", "excitable", "exciting", "exclaim", + "exclude", "excluding", "exclusion", "exclusive", "excretion", "excretory", "excursion", + "excusable", "excusably", "excuse", "exemplary", "exemplify", "exemption", "exerciser", + "exert", "exes", "exfoliate", "exhale", "exhaust", "exhume", "exile", "existing", "exit", + "exodus", "exonerate", "exorcism", "exorcist", "expand", "expanse", "expansion", + "expansive", "expectant", "expedited", "expediter", "expel", "expend", "expenses", + "expensive", "expert", "expire", "expiring", "explain", "expletive", "explicit", "explode", + "exploit", "explore", "exploring", "exponent", "exporter", "exposable", "expose", + "exposure", "express", "expulsion", "exquisite", "extended", "extending", "extent", + "extenuate", "exterior", "external", "extinct", "extortion", "extradite", "extras", + "extrovert", "extrude", "extruding", "exuberant", "fable", "fabric", "fabulous", + "facebook", "facecloth", "facedown", "faceless", "facelift", "faceplate", "faceted", + "facial", "facility", "facing", "facsimile", "faction", "factoid", "factor", "factsheet", + "factual", "faculty", "fade", "fading", "failing", "falcon", "fall", "false", "falsify", + "fame", "familiar", "family", "famine", "famished", "fanatic", "fancied", "fanciness", + "fancy", "fanfare", "fang", "fanning", "fantasize", "fantastic", "fantasy", "fascism", + "fastball", "faster", "fasting", "fastness", "faucet", "favorable", "favorably", "favored", + "favoring", "favorite", "fax", "feast", "federal", "fedora", "feeble", "feed", "feel", + "feisty", "feline", "felt-tip", "feminine", "feminism", "feminist", "feminize", "femur", + "fence", "fencing", "fender", "ferment", "fernlike", "ferocious", "ferocity", "ferret", + "ferris", "ferry", "fervor", "fester", "festival", "festive", "festivity", "fetal", + "fetch", "fever", "fiber", "fiction", "fiddle", "fiddling", "fidelity", "fidgeting", + "fidgety", "fifteen", "fifth", "fiftieth", "fifty", "figment", "figure", "figurine", + "filing", "filled", "filler", "filling", "film", "filter", "filth", "filtrate", "finale", + "finalist", "finalize", "finally", "finance", "financial", "finch", "fineness", "finer", + "finicky", "finished", "finisher", "finishing", "finite", "finless", "finlike", "fiscally", + "fit", "five", "flaccid", "flagman", "flagpole", "flagship", "flagstick", "flagstone", + "flail", "flakily", "flaky", "flame", "flammable", "flanked", "flanking", "flannels", + "flap", "flaring", "flashback", "flashbulb", "flashcard", "flashily", "flashing", "flashy", + "flask", "flatbed", "flatfoot", "flatly", "flatness", "flatten", "flattered", "flatterer", + "flattery", "flattop", "flatware", "flatworm", "flavored", "flavorful", "flavoring", + "flaxseed", "fled", "fleshed", "fleshy", "flick", "flier", "flight", "flinch", "fling", + "flint", "flip", "flirt", "float", "flock", "flogging", "flop", "floral", "florist", + "floss", "flounder", "flyable", "flyaway", "flyer", "flying", "flyover", "flypaper", + "foam", "foe", "fog", "foil", "folic", "folk", "follicle", "follow", "fondling", "fondly", + "fondness", "fondue", "font", "food", "fool", "footage", "football", "footbath", + "footboard", "footer", "footgear", "foothill", "foothold", "footing", "footless", + "footman", "footnote", "footpad", "footpath", "footprint", "footrest", "footsie", + "footsore", "footwear", "footwork", "fossil", "foster", "founder", "founding", "fountain", + "fox", "foyer", "fraction", "fracture", "fragile", "fragility", "fragment", "fragrance", + "fragrant", "frail", "frame", "framing", "frantic", "fraternal", "frayed", "fraying", + "frays", "freckled", "freckles", "freebase", "freebee", "freebie", "freedom", "freefall", + "freehand", "freeing", "freeload", "freely", "freemason", "freeness", "freestyle", + "freeware", "freeway", "freewill", "freezable", "freezing", "freight", "french", + "frenzied", "frenzy", "frequency", "frequent", "fresh", "fretful", "fretted", "friction", + "friday", "fridge", "fried", "friend", "frighten", "frightful", "frigidity", "frigidly", + "frill", "fringe", "frisbee", "frisk", "fritter", "frivolous", "frolic", "from", "front", + "frostbite", "frosted", "frostily", "frosting", "frostlike", "frosty", "froth", "frown", + "frozen", "fructose", "frugality", "frugally", "fruit", "frustrate", "frying", "gab", + "gaffe", "gag", "gainfully", "gaining", "gains", "gala", "gallantly", "galleria", + "gallery", "galley", "gallon", "gallows", "gallstone", "galore", "galvanize", "gambling", + "game", "gaming", "gamma", "gander", "gangly", "gangrene", "gangway", "gap", "garage", + "garbage", "garden", "gargle", "garland", "garlic", "garment", "garnet", "garnish", + "garter", "gas", "gatherer", "gathering", "gating", "gauging", "gauntlet", "gauze", "gave", + "gawk", "gazing", "gear", "gecko", "geek", "geiger", "gem", "gender", "generic", + "generous", "genetics", "genre", "gentile", "gentleman", "gently", "gents", "geography", + "geologic", "geologist", "geology", "geometric", "geometry", "geranium", "gerbil", + "geriatric", "germicide", "germinate", "germless", "germproof", "gestate", "gestation", + "gesture", "getaway", "getting", "getup", "giant", "gibberish", "giblet", "giddily", + "giddiness", "giddy", "gift", "gigabyte", "gigahertz", "gigantic", "giggle", "giggling", + "giggly", "gigolo", "gilled", "gills", "gimmick", "girdle", "giveaway", "given", "giver", + "giving", "gizmo", "gizzard", "glacial", "glacier", "glade", "gladiator", "gladly", + "glamorous", "glamour", "glance", "glancing", "glandular", "glare", "glaring", "glass", + "glaucoma", "glazing", "gleaming", "gleeful", "glider", "gliding", "glimmer", "glimpse", + "glisten", "glitch", "glitter", "glitzy", "gloater", "gloating", "gloomily", "gloomy", + "glorified", "glorifier", "glorify", "glorious", "glory", "gloss", "glove", "glowing", + "glowworm", "glucose", "glue", "gluten", "glutinous", "glutton", "gnarly", "gnat", "goal", + "goatskin", "goes", "goggles", "going", "goldfish", "goldmine", "goldsmith", "golf", + "goliath", "gonad", "gondola", "gone", "gong", "good", "gooey", "goofball", "goofiness", + "goofy", "google", "goon", "gopher", "gore", "gorged", "gorgeous", "gory", "gosling", + "gossip", "gothic", "gotten", "gout", "gown", "grab", "graceful", "graceless", "gracious", + "gradation", "graded", "grader", "gradient", "grading", "gradually", "graduate", + "graffiti", "grafted", "grafting", "grain", "granddad", "grandkid", "grandly", "grandma", + "grandpa", "grandson", "granite", "granny", "granola", "grant", "granular", "grape", + "graph", "grapple", "grappling", "grasp", "grass", "gratified", "gratify", "grating", + "gratitude", "gratuity", "gravel", "graveness", "graves", "graveyard", "gravitate", + "gravity", "gravy", "gray", "grazing", "greasily", "greedily", "greedless", "greedy", + "green", "greeter", "greeting", "grew", "greyhound", "grid", "grief", "grievance", + "grieving", "grievous", "grill", "grimace", "grimacing", "grime", "griminess", "grimy", + "grinch", "grinning", "grip", "gristle", "grit", "groggily", "groggy", "groin", "groom", + "groove", "grooving", "groovy", "grope", "ground", "grouped", "grout", "grove", "grower", + "growing", "growl", "grub", "grudge", "grudging", "grueling", "gruffly", "grumble", + "grumbling", "grumbly", "grumpily", "grunge", "grunt", "guacamole", "guidable", "guidance", + "guide", "guiding", "guileless", "guise", "gulf", "gullible", "gully", "gulp", "gumball", + "gumdrop", "gumminess", "gumming", "gummy", "gurgle", "gurgling", "guru", "gush", "gusto", + "gusty", "gutless", "guts", "gutter", "guy", "guzzler", "gyration", "habitable", + "habitant", "habitat", "habitual", "hacked", "hacker", "hacking", "hacksaw", "had", + "haggler", "haiku", "half", "halogen", "halt", "halved", "halves", "hamburger", "hamlet", + "hammock", "hamper", "hamster", "hamstring", "handbag", "handball", "handbook", + "handbrake", "handcart", "handclap", "handclasp", "handcraft", "handcuff", "handed", + "handful", "handgrip", "handgun", "handheld", "handiness", "handiwork", "handlebar", + "handled", "handler", "handling", "handmade", "handoff", "handpick", "handprint", + "handrail", "handsaw", "handset", "handsfree", "handshake", "handstand", "handwash", + "handwork", "handwoven", "handwrite", "handyman", "hangnail", "hangout", "hangover", + "hangup", "hankering", "hankie", "hanky", "haphazard", "happening", "happier", "happiest", + "happily", "happiness", "happy", "harbor", "hardcopy", "hardcore", "hardcover", "harddisk", + "hardened", "hardener", "hardening", "hardhat", "hardhead", "hardiness", "hardly", + "hardness", "hardship", "hardware", "hardwired", "hardwood", "hardy", "harmful", + "harmless", "harmonica", "harmonics", "harmonize", "harmony", "harness", "harpist", + "harsh", "harvest", "hash", "hassle", "haste", "hastily", "hastiness", "hasty", "hatbox", + "hatchback", "hatchery", "hatchet", "hatching", "hatchling", "hate", "hatless", "hatred", + "haunt", "haven", "hazard", "hazelnut", "hazily", "haziness", "hazing", "hazy", "headache", + "headband", "headboard", "headcount", "headdress", "headed", "header", "headfirst", + "headgear", "heading", "headlamp", "headless", "headlock", "headphone", "headpiece", + "headrest", "headroom", "headscarf", "headset", "headsman", "headstand", "headstone", + "headway", "headwear", "heap", "heat", "heave", "heavily", "heaviness", "heaving", "hedge", + "hedging", "heftiness", "hefty", "helium", "helmet", "helper", "helpful", "helping", + "helpless", "helpline", "hemlock", "hemstitch", "hence", "henchman", "henna", "herald", + "herbal", "herbicide", "herbs", "heritage", "hermit", "heroics", "heroism", "herring", + "herself", "hertz", "hesitancy", "hesitant", "hesitate", "hexagon", "hexagram", "hubcap", + "huddle", "huddling", "huff", "hug", "hula", "hulk", "hull", "human", "humble", "humbling", + "humbly", "humid", "humiliate", "humility", "humming", "hummus", "humongous", "humorist", + "humorless", "humorous", "humpback", "humped", "humvee", "hunchback", "hundredth", + "hunger", "hungrily", "hungry", "hunk", "hunter", "hunting", "huntress", "huntsman", + "hurdle", "hurled", "hurler", "hurling", "hurray", "hurricane", "hurried", "hurry", "hurt", + "husband", "hush", "husked", "huskiness", "hut", "hybrid", "hydrant", "hydrated", + "hydration", "hydrogen", "hydroxide", "hyperlink", "hypertext", "hyphen", "hypnoses", + "hypnosis", "hypnotic", "hypnotism", "hypnotist", "hypnotize", "hypocrisy", "hypocrite", + "ibuprofen", "ice", "iciness", "icing", "icky", "icon", "icy", "idealism", "idealist", + "idealize", "ideally", "idealness", "identical", "identify", "identity", "ideology", + "idiocy", "idiom", "idly", "igloo", "ignition", "ignore", "iguana", "illicitly", + "illusion", "illusive", "image", "imaginary", "imagines", "imaging", "imbecile", "imitate", + "imitation", "immature", "immerse", "immersion", "imminent", "immobile", "immodest", + "immorally", "immortal", "immovable", "immovably", "immunity", "immunize", "impaired", + "impale", "impart", "impatient", "impeach", "impeding", "impending", "imperfect", + "imperial", "impish", "implant", "implement", "implicate", "implicit", "implode", + "implosion", "implosive", "imply", "impolite", "important", "importer", "impose", + "imposing", "impotence", "impotency", "impotent", "impound", "imprecise", "imprint", + "imprison", "impromptu", "improper", "improve", "improving", "improvise", "imprudent", + "impulse", "impulsive", "impure", "impurity", "iodine", "iodize", "ion", "ipad", "iphone", + "ipod", "irate", "irk", "iron", "irregular", "irrigate", "irritable", "irritably", + "irritant", "irritate", "islamic", "islamist", "isolated", "isolating", "isolation", + "isotope", "issue", "issuing", "italicize", "italics", "item", "itinerary", "itunes", + "ivory", "ivy", "jab", "jackal", "jacket", "jackknife", "jackpot", "jailbird", "jailbreak", + "jailer", "jailhouse", "jalapeno", "jam", "janitor", "january", "jargon", "jarring", + "jasmine", "jaundice", "jaunt", "java", "jawed", "jawless", "jawline", "jaws", "jaybird", + "jaywalker", "jazz", "jeep", "jeeringly", "jellied", "jelly", "jersey", "jester", "jet", + "jiffy", "jigsaw", "jimmy", "jingle", "jingling", "jinx", "jitters", "jittery", "job", + "jockey", "jockstrap", "jogger", "jogging", "john", "joining", "jokester", "jokingly", + "jolliness", "jolly", "jolt", "jot", "jovial", "joyfully", "joylessly", "joyous", + "joyride", "joystick", "jubilance", "jubilant", "judge", "judgingly", "judicial", + "judiciary", "judo", "juggle", "juggling", "jugular", "juice", "juiciness", "juicy", + "jujitsu", "jukebox", "july", "jumble", "jumbo", "jump", "junction", "juncture", "june", + "junior", "juniper", "junkie", "junkman", "junkyard", "jurist", "juror", "jury", "justice", + "justifier", "justify", "justly", "justness", "juvenile", "kabob", "kangaroo", "karaoke", + "karate", "karma", "kebab", "keenly", "keenness", "keep", "keg", "kelp", "kennel", "kept", + "kerchief", "kerosene", "kettle", "kick", "kiln", "kilobyte", "kilogram", "kilometer", + "kilowatt", "kilt", "kimono", "kindle", "kindling", "kindly", "kindness", "kindred", + "kinetic", "kinfolk", "king", "kinship", "kinsman", "kinswoman", "kissable", "kisser", + "kissing", "kitchen", "kite", "kitten", "kitty", "kiwi", "kleenex", "knapsack", "knee", + "knelt", "knickers", "knoll", "koala", "kooky", "kosher", "krypton", "kudos", "kung", + "labored", "laborer", "laboring", "laborious", "labrador", "ladder", "ladies", "ladle", + "ladybug", "ladylike", "lagged", "lagging", "lagoon", "lair", "lake", "lance", "landed", + "landfall", "landfill", "landing", "landlady", "landless", "landline", "landlord", + "landmark", "landmass", "landmine", "landowner", "landscape", "landside", "landslide", + "language", "lankiness", "lanky", "lantern", "lapdog", "lapel", "lapped", "lapping", + "laptop", "lard", "large", "lark", "lash", "lasso", "last", "latch", "late", "lather", + "latitude", "latrine", "latter", "latticed", "launch", "launder", "laundry", "laurel", + "lavender", "lavish", "laxative", "lazily", "laziness", "lazy", "lecturer", "left", + "legacy", "legal", "legend", "legged", "leggings", "legible", "legibly", "legislate", + "lego", "legroom", "legume", "legwarmer", "legwork", "lemon", "lend", "length", "lens", + "lent", "leotard", "lesser", "letdown", "lethargic", "lethargy", "letter", "lettuce", + "level", "leverage", "levers", "levitate", "levitator", "liability", "liable", "liberty", + "librarian", "library", "licking", "licorice", "lid", "life", "lifter", "lifting", + "liftoff", "ligament", "likely", "likeness", "likewise", "liking", "lilac", "lilly", + "lily", "limb", "limeade", "limelight", "limes", "limit", "limping", "limpness", "line", + "lingo", "linguini", "linguist", "lining", "linked", "linoleum", "linseed", "lint", "lion", + "lip", "liquefy", "liqueur", "liquid", "lisp", "list", "litigate", "litigator", "litmus", + "litter", "little", "livable", "lived", "lively", "liver", "livestock", "lividly", + "living", "lizard", "lubricant", "lubricate", "lucid", "luckily", "luckiness", "luckless", + "lucrative", "ludicrous", "lugged", "lukewarm", "lullaby", "lumber", "luminance", + "luminous", "lumpiness", "lumping", "lumpish", "lunacy", "lunar", "lunchbox", "luncheon", + "lunchroom", "lunchtime", "lung", "lurch", "lure", "luridness", "lurk", "lushly", + "lushness", "luster", "lustfully", "lustily", "lustiness", "lustrous", "lusty", + "luxurious", "luxury", "lying", "lyrically", "lyricism", "lyricist", "lyrics", "macarena", + "macaroni", "macaw", "mace", "machine", "machinist", "magazine", "magenta", "maggot", + "magical", "magician", "magma", "magnesium", "magnetic", "magnetism", "magnetize", + "magnifier", "magnify", "magnitude", "magnolia", "mahogany", "maimed", "majestic", + "majesty", "majorette", "majority", "makeover", "maker", "makeshift", "making", + "malformed", "malt", "mama", "mammal", "mammary", "mammogram", "manager", "managing", + "manatee", "mandarin", "mandate", "mandatory", "mandolin", "manger", "mangle", "mango", + "mangy", "manhandle", "manhole", "manhood", "manhunt", "manicotti", "manicure", + "manifesto", "manila", "mankind", "manlike", "manliness", "manly", "manmade", "manned", + "mannish", "manor", "manpower", "mantis", "mantra", "manual", "many", "map", "marathon", + "marauding", "marbled", "marbles", "marbling", "march", "mardi", "margarine", "margarita", + "margin", "marigold", "marina", "marine", "marital", "maritime", "marlin", "marmalade", + "maroon", "married", "marrow", "marry", "marshland", "marshy", "marsupial", "marvelous", + "marxism", "mascot", "masculine", "mashed", "mashing", "massager", "masses", "massive", + "mastiff", "matador", "matchbook", "matchbox", "matcher", "matching", "matchless", + "material", "maternal", "maternity", "math", "mating", "matriarch", "matrimony", "matrix", + "matron", "matted", "matter", "maturely", "maturing", "maturity", "mauve", "maverick", + "maximize", "maximum", "maybe", "mayday", "mayflower", "moaner", "moaning", "mobile", + "mobility", "mobilize", "mobster", "mocha", "mocker", "mockup", "modified", "modify", + "modular", "modulator", "module", "moisten", "moistness", "moisture", "molar", "molasses", + "mold", "molecular", "molecule", "molehill", "mollusk", "mom", "monastery", "monday", + "monetary", "monetize", "moneybags", "moneyless", "moneywise", "mongoose", "mongrel", + "monitor", "monkhood", "monogamy", "monogram", "monologue", "monopoly", "monorail", + "monotone", "monotype", "monoxide", "monsieur", "monsoon", "monstrous", "monthly", + "monument", "moocher", "moodiness", "moody", "mooing", "moonbeam", "mooned", "moonlight", + "moonlike", "moonlit", "moonrise", "moonscape", "moonshine", "moonstone", "moonwalk", + "mop", "morale", "morality", "morally", "morbidity", "morbidly", "morphine", "morphing", + "morse", "mortality", "mortally", "mortician", "mortified", "mortify", "mortuary", + "mosaic", "mossy", "most", "mothball", "mothproof", "motion", "motivate", "motivator", + "motive", "motocross", "motor", "motto", "mountable", "mountain", "mounted", "mounting", + "mourner", "mournful", "mouse", "mousiness", "moustache", "mousy", "mouth", "movable", + "move", "movie", "moving", "mower", "mowing", "much", "muck", "mud", "mug", "mulberry", + "mulch", "mule", "mulled", "mullets", "multiple", "multiply", "multitask", "multitude", + "mumble", "mumbling", "mumbo", "mummified", "mummify", "mummy", "mumps", "munchkin", + "mundane", "municipal", "muppet", "mural", "murkiness", "murky", "murmuring", "muscular", + "museum", "mushily", "mushiness", "mushroom", "mushy", "music", "musket", "muskiness", + "musky", "mustang", "mustard", "muster", "mustiness", "musty", "mutable", "mutate", + "mutation", "mute", "mutilated", "mutilator", "mutiny", "mutt", "mutual", "muzzle", + "myself", "myspace", "mystified", "mystify", "myth", "nacho", "nag", "nail", "name", + "naming", "nanny", "nanometer", "nape", "napkin", "napped", "napping", "nappy", "narrow", + "nastily", "nastiness", "national", "native", "nativity", "natural", "nature", "naturist", + "nautical", "navigate", "navigator", "navy", "nearby", "nearest", "nearly", "nearness", + "neatly", "neatness", "nebula", "nebulizer", "nectar", "negate", "negation", "negative", + "neglector", "negligee", "negligent", "negotiate", "nemeses", "nemesis", "neon", "nephew", + "nerd", "nervous", "nervy", "nest", "net", "neurology", "neuron", "neurosis", "neurotic", + "neuter", "neutron", "never", "next", "nibble", "nickname", "nicotine", "niece", "nifty", + "nimble", "nimbly", "nineteen", "ninetieth", "ninja", "nintendo", "ninth", "nuclear", + "nuclei", "nucleus", "nugget", "nullify", "number", "numbing", "numbly", "numbness", + "numeral", "numerate", "numerator", "numeric", "numerous", "nuptials", "nursery", + "nursing", "nurture", "nutcase", "nutlike", "nutmeg", "nutrient", "nutshell", "nuttiness", + "nutty", "nuzzle", "nylon", "oaf", "oak", "oasis", "oat", "obedience", "obedient", + "obituary", "object", "obligate", "obliged", "oblivion", "oblivious", "oblong", + "obnoxious", "oboe", "obscure", "obscurity", "observant", "observer", "observing", + "obsessed", "obsession", "obsessive", "obsolete", "obstacle", "obstinate", "obstruct", + "obtain", "obtrusive", "obtuse", "obvious", "occultist", "occupancy", "occupant", + "occupier", "occupy", "ocean", "ocelot", "octagon", "octane", "october", "octopus", "ogle", + "oil", "oink", "ointment", "okay", "old", "olive", "olympics", "omega", "omen", "ominous", + "omission", "omit", "omnivore", "onboard", "oncoming", "ongoing", "onion", "online", + "onlooker", "only", "onscreen", "onset", "onshore", "onslaught", "onstage", "onto", + "onward", "onyx", "oops", "ooze", "oozy", "opacity", "opal", "open", "operable", "operate", + "operating", "operation", "operative", "operator", "opium", "opossum", "opponent", + "oppose", "opposing", "opposite", "oppressed", "oppressor", "opt", "opulently", "osmosis", + "other", "otter", "ouch", "ought", "ounce", "outage", "outback", "outbid", "outboard", + "outbound", "outbreak", "outburst", "outcast", "outclass", "outcome", "outdated", + "outdoors", "outer", "outfield", "outfit", "outflank", "outgoing", "outgrow", "outhouse", + "outing", "outlast", "outlet", "outline", "outlook", "outlying", "outmatch", "outmost", + "outnumber", "outplayed", "outpost", "outpour", "output", "outrage", "outrank", "outreach", + "outright", "outscore", "outsell", "outshine", "outshoot", "outsider", "outskirts", + "outsmart", "outsource", "outspoken", "outtakes", "outthink", "outward", "outweigh", + "outwit", "oval", "ovary", "oven", "overact", "overall", "overarch", "overbid", "overbill", + "overbite", "overblown", "overboard", "overbook", "overbuilt", "overcast", "overcoat", + "overcome", "overcook", "overcrowd", "overdraft", "overdrawn", "overdress", "overdrive", + "overdue", "overeager", "overeater", "overexert", "overfed", "overfeed", "overfill", + "overflow", "overfull", "overgrown", "overhand", "overhang", "overhaul", "overhead", + "overhear", "overheat", "overhung", "overjoyed", "overkill", "overlabor", "overlaid", + "overlap", "overlay", "overload", "overlook", "overlord", "overlying", "overnight", + "overpass", "overpay", "overplant", "overplay", "overpower", "overprice", "overrate", + "overreach", "overreact", "override", "overripe", "overrule", "overrun", "overshoot", + "overshot", "oversight", "oversized", "oversleep", "oversold", "overspend", "overstate", + "overstay", "overstep", "overstock", "overstuff", "oversweet", "overtake", "overthrow", + "overtime", "overtly", "overtone", "overture", "overturn", "overuse", "overvalue", + "overview", "overwrite", "owl", "oxford", "oxidant", "oxidation", "oxidize", "oxidizing", + "oxygen", "oxymoron", "oyster", "ozone", "paced", "pacemaker", "pacific", "pacifier", + "pacifism", "pacifist", "pacify", "padded", "padding", "paddle", "paddling", "padlock", + "pagan", "pager", "paging", "pajamas", "palace", "palatable", "palm", "palpable", + "palpitate", "paltry", "pampered", "pamperer", "pampers", "pamphlet", "panama", "pancake", + "pancreas", "panda", "pandemic", "pang", "panhandle", "panic", "panning", "panorama", + "panoramic", "panther", "pantomime", "pantry", "pants", "pantyhose", "paparazzi", "papaya", + "paper", "paprika", "papyrus", "parabola", "parachute", "parade", "paradox", "paragraph", + "parakeet", "paralegal", "paralyses", "paralysis", "paralyze", "paramedic", "parameter", + "paramount", "parasail", "parasite", "parasitic", "parcel", "parched", "parchment", + "pardon", "parish", "parka", "parking", "parkway", "parlor", "parmesan", "parole", + "parrot", "parsley", "parsnip", "partake", "parted", "parting", "partition", "partly", + "partner", "partridge", "party", "passable", "passably", "passage", "passcode", + "passenger", "passerby", "passing", "passion", "passive", "passivism", "passover", + "passport", "password", "pasta", "pasted", "pastel", "pastime", "pastor", "pastrami", + "pasture", "pasty", "patchwork", "patchy", "paternal", "paternity", "path", "patience", + "patient", "patio", "patriarch", "patriot", "patrol", "patronage", "patronize", "pauper", + "pavement", "paver", "pavestone", "pavilion", "paving", "pawing", "payable", "payback", + "paycheck", "payday", "payee", "payer", "paying", "payment", "payphone", "payroll", + "pebble", "pebbly", "pecan", "pectin", "peculiar", "peddling", "pediatric", "pedicure", + "pedigree", "pedometer", "pegboard", "pelican", "pellet", "pelt", "pelvis", "penalize", + "penalty", "pencil", "pendant", "pending", "penholder", "penknife", "pennant", "penniless", + "penny", "penpal", "pension", "pentagon", "pentagram", "pep", "perceive", "percent", + "perch", "percolate", "perennial", "perfected", "perfectly", "perfume", "periscope", + "perish", "perjurer", "perjury", "perkiness", "perky", "perm", "peroxide", "perpetual", + "perplexed", "persecute", "persevere", "persuaded", "persuader", "pesky", "peso", + "pessimism", "pessimist", "pester", "pesticide", "petal", "petite", "petition", "petri", + "petroleum", "petted", "petticoat", "pettiness", "petty", "petunia", "phantom", "phobia", + "phoenix", "phonebook", "phoney", "phonics", "phoniness", "phony", "phosphate", "photo", + "phrase", "phrasing", "placard", "placate", "placidly", "plank", "planner", "plant", + "plasma", "plaster", "plastic", "plated", "platform", "plating", "platinum", "platonic", + "platter", "platypus", "plausible", "plausibly", "playable", "playback", "player", + "playful", "playgroup", "playhouse", "playing", "playlist", "playmaker", "playmate", + "playoff", "playpen", "playroom", "playset", "plaything", "playtime", "plaza", "pleading", + "pleat", "pledge", "plentiful", "plenty", "plethora", "plexiglas", "pliable", "plod", + "plop", "plot", "plow", "ploy", "pluck", "plug", "plunder", "plunging", "plural", "plus", + "plutonium", "plywood", "poach", "pod", "poem", "poet", "pogo", "pointed", "pointer", + "pointing", "pointless", "pointy", "poise", "poison", "poker", "poking", "polar", "police", + "policy", "polio", "polish", "politely", "polka", "polo", "polyester", "polygon", + "polygraph", "polymer", "poncho", "pond", "pony", "popcorn", "pope", "poplar", "popper", + "poppy", "popsicle", "populace", "popular", "populate", "porcupine", "pork", "porous", + "porridge", "portable", "portal", "portfolio", "porthole", "portion", "portly", "portside", + "poser", "posh", "posing", "possible", "possibly", "possum", "postage", "postal", + "postbox", "postcard", "posted", "poster", "posting", "postnasal", "posture", "postwar", + "pouch", "pounce", "pouncing", "pound", "pouring", "pout", "powdered", "powdering", + "powdery", "power", "powwow", "pox", "praising", "prance", "prancing", "pranker", + "prankish", "prankster", "prayer", "praying", "preacher", "preaching", "preachy", + "preamble", "precinct", "precise", "precision", "precook", "precut", "predator", + "predefine", "predict", "preface", "prefix", "preflight", "preformed", "pregame", + "pregnancy", "pregnant", "preheated", "prelaunch", "prelaw", "prelude", "premiere", + "premises", "premium", "prenatal", "preoccupy", "preorder", "prepaid", "prepay", "preplan", + "preppy", "preschool", "prescribe", "preseason", "preset", "preshow", "president", + "presoak", "press", "presume", "presuming", "preteen", "pretended", "pretender", + "pretense", "pretext", "pretty", "pretzel", "prevail", "prevalent", "prevent", "preview", + "previous", "prewar", "prewashed", "prideful", "pried", "primal", "primarily", "primary", + "primate", "primer", "primp", "princess", "print", "prior", "prism", "prison", "prissy", + "pristine", "privacy", "private", "privatize", "prize", "proactive", "probable", + "probably", "probation", "probe", "probing", "probiotic", "problem", "procedure", + "process", "proclaim", "procreate", "procurer", "prodigal", "prodigy", "produce", + "product", "profane", "profanity", "professed", "professor", "profile", "profound", + "profusely", "progeny", "prognosis", "program", "progress", "projector", "prologue", + "prolonged", "promenade", "prominent", "promoter", "promotion", "prompter", "promptly", + "prone", "prong", "pronounce", "pronto", "proofing", "proofread", "proofs", "propeller", + "properly", "property", "proponent", "proposal", "propose", "props", "prorate", + "protector", "protegee", "proton", "prototype", "protozoan", "protract", "protrude", + "proud", "provable", "proved", "proven", "provided", "provider", "providing", "province", + "proving", "provoke", "provoking", "provolone", "prowess", "prowler", "prowling", + "proximity", "proxy", "prozac", "prude", "prudishly", "prune", "pruning", "pry", "psychic", + "public", "publisher", "pucker", "pueblo", "pug", "pull", "pulmonary", "pulp", "pulsate", + "pulse", "pulverize", "puma", "pumice", "pummel", "punch", "punctual", "punctuate", + "punctured", "pungent", "punisher", "punk", "pupil", "puppet", "puppy", "purchase", + "pureblood", "purebred", "purely", "pureness", "purgatory", "purge", "purging", "purifier", + "purify", "purist", "puritan", "purity", "purple", "purplish", "purposely", "purr", + "purse", "pursuable", "pursuant", "pursuit", "purveyor", "pushcart", "pushchair", "pusher", + "pushiness", "pushing", "pushover", "pushpin", "pushup", "pushy", "putdown", "putt", + "puzzle", "puzzling", "pyramid", "pyromania", "python", "quack", "quadrant", "quail", + "quaintly", "quake", "quaking", "qualified", "qualifier", "qualify", "quality", "qualm", + "quantum", "quarrel", "quarry", "quartered", "quarterly", "quarters", "quartet", "quench", + "query", "quicken", "quickly", "quickness", "quicksand", "quickstep", "quiet", "quill", + "quilt", "quintet", "quintuple", "quirk", "quit", "quiver", "quizzical", "quotable", + "quotation", "quote", "rabid", "race", "racing", "racism", "rack", "racoon", "radar", + "radial", "radiance", "radiantly", "radiated", "radiation", "radiator", "radio", "radish", + "raffle", "raft", "rage", "ragged", "raging", "ragweed", "raider", "railcar", "railing", + "railroad", "railway", "raisin", "rake", "raking", "rally", "ramble", "rambling", "ramp", + "ramrod", "ranch", "rancidity", "random", "ranged", "ranger", "ranging", "ranked", + "ranking", "ransack", "ranting", "rants", "rare", "rarity", "rascal", "rash", "rasping", + "ravage", "raven", "ravine", "raving", "ravioli", "ravishing", "reabsorb", "reach", + "reacquire", "reaction", "reactive", "reactor", "reaffirm", "ream", "reanalyze", + "reappear", "reapply", "reappoint", "reapprove", "rearrange", "rearview", "reason", + "reassign", "reassure", "reattach", "reawake", "rebalance", "rebate", "rebel", "rebirth", + "reboot", "reborn", "rebound", "rebuff", "rebuild", "rebuilt", "reburial", "rebuttal", + "recall", "recant", "recapture", "recast", "recede", "recent", "recess", "recharger", + "recipient", "recital", "recite", "reckless", "reclaim", "recliner", "reclining", + "recluse", "reclusive", "recognize", "recoil", "recollect", "recolor", "reconcile", + "reconfirm", "reconvene", "recopy", "record", "recount", "recoup", "recovery", "recreate", + "rectal", "rectangle", "rectified", "rectify", "recycled", "recycler", "recycling", + "reemerge", "reenact", "reenter", "reentry", "reexamine", "referable", "referee", + "reference", "refill", "refinance", "refined", "refinery", "refining", "refinish", + "reflected", "reflector", "reflex", "reflux", "refocus", "refold", "reforest", "reformat", + "reformed", "reformer", "reformist", "refract", "refrain", "refreeze", "refresh", + "refried", "refueling", "refund", "refurbish", "refurnish", "refusal", "refuse", + "refusing", "refutable", "refute", "regain", "regalia", "regally", "reggae", "regime", + "region", "register", "registrar", "registry", "regress", "regretful", "regroup", + "regular", "regulate", "regulator", "rehab", "reheat", "rehire", "rehydrate", "reimburse", + "reissue", "reiterate", "rejoice", "rejoicing", "rejoin", "rekindle", "relapse", + "relapsing", "relatable", "related", "relation", "relative", "relax", "relay", "relearn", + "release", "relenting", "reliable", "reliably", "reliance", "reliant", "relic", "relieve", + "relieving", "relight", "relish", "relive", "reload", "relocate", "relock", "reluctant", + "rely", "remake", "remark", "remarry", "rematch", "remedial", "remedy", "remember", + "reminder", "remindful", "remission", "remix", "remnant", "remodeler", "remold", "remorse", + "remote", "removable", "removal", "removed", "remover", "removing", "rename", "renderer", + "rendering", "rendition", "renegade", "renewable", "renewably", "renewal", "renewed", + "renounce", "renovate", "renovator", "rentable", "rental", "rented", "renter", "reoccupy", + "reoccur", "reopen", "reorder", "repackage", "repacking", "repaint", "repair", "repave", + "repaying", "repayment", "repeal", "repeated", "repeater", "repent", "rephrase", "replace", + "replay", "replica", "reply", "reporter", "repose", "repossess", "repost", "repressed", + "reprimand", "reprint", "reprise", "reproach", "reprocess", "reproduce", "reprogram", + "reps", "reptile", "reptilian", "repugnant", "repulsion", "repulsive", "repurpose", + "reputable", "reputably", "request", "require", "requisite", "reroute", "rerun", "resale", + "resample", "rescuer", "reseal", "research", "reselect", "reseller", "resemble", "resend", + "resent", "reset", "reshape", "reshoot", "reshuffle", "residence", "residency", "resident", + "residual", "residue", "resigned", "resilient", "resistant", "resisting", "resize", + "resolute", "resolved", "resonant", "resonate", "resort", "resource", "respect", + "resubmit", "result", "resume", "resupply", "resurface", "resurrect", "retail", "retainer", + "retaining", "retake", "retaliate", "retention", "rethink", "retinal", "retired", + "retiree", "retiring", "retold", "retool", "retorted", "retouch", "retrace", "retract", + "retrain", "retread", "retreat", "retrial", "retrieval", "retriever", "retry", "return", + "retying", "retype", "reunion", "reunite", "reusable", "reuse", "reveal", "reveler", + "revenge", "revenue", "reverb", "revered", "reverence", "reverend", "reversal", "reverse", + "reversing", "reversion", "revert", "revisable", "revise", "revision", "revisit", + "revivable", "revival", "reviver", "reviving", "revocable", "revoke", "revolt", "revolver", + "revolving", "reward", "rewash", "rewind", "rewire", "reword", "rework", "rewrap", + "rewrite", "rhyme", "ribbon", "ribcage", "rice", "riches", "richly", "richness", "rickety", + "ricotta", "riddance", "ridden", "ride", "riding", "rifling", "rift", "rigging", "rigid", + "rigor", "rimless", "rimmed", "rind", "rink", "rinse", "rinsing", "riot", "ripcord", + "ripeness", "ripening", "ripping", "ripple", "rippling", "riptide", "rise", "rising", + "risk", "risotto", "ritalin", "ritzy", "rival", "riverbank", "riverbed", "riverboat", + "riverside", "riveter", "riveting", "roamer", "roaming", "roast", "robbing", "robe", + "robin", "robotics", "robust", "rockband", "rocker", "rocket", "rockfish", "rockiness", + "rocking", "rocklike", "rockslide", "rockstar", "rocky", "rogue", "roman", "romp", "rope", + "roping", "roster", "rosy", "rotten", "rotting", "rotunda", "roulette", "rounding", + "roundish", "roundness", "roundup", "roundworm", "routine", "routing", "rover", "roving", + "royal", "rubbed", "rubber", "rubbing", "rubble", "rubdown", "ruby", "ruckus", "rudder", + "rug", "ruined", "rule", "rumble", "rumbling", "rummage", "rumor", "runaround", "rundown", + "runner", "running", "runny", "runt", "runway", "rupture", "rural", "ruse", "rush", "rust", + "rut", "sabbath", "sabotage", "sacrament", "sacred", "sacrifice", "sadden", "saddlebag", + "saddled", "saddling", "sadly", "sadness", "safari", "safeguard", "safehouse", "safely", + "safeness", "saffron", "saga", "sage", "sagging", "saggy", "said", "saint", "sake", + "salad", "salami", "salaried", "salary", "saline", "salon", "saloon", "salsa", "salt", + "salutary", "salute", "salvage", "salvaging", "salvation", "same", "sample", "sampling", + "sanction", "sanctity", "sanctuary", "sandal", "sandbag", "sandbank", "sandbar", + "sandblast", "sandbox", "sanded", "sandfish", "sanding", "sandlot", "sandpaper", "sandpit", + "sandstone", "sandstorm", "sandworm", "sandy", "sanitary", "sanitizer", "sank", "santa", + "sapling", "sappiness", "sappy", "sarcasm", "sarcastic", "sardine", "sash", "sasquatch", + "sassy", "satchel", "satiable", "satin", "satirical", "satisfied", "satisfy", "saturate", + "saturday", "sauciness", "saucy", "sauna", "savage", "savanna", "saved", "savings", + "savior", "savor", "saxophone", "say", "scabbed", "scabby", "scalded", "scalding", "scale", + "scaling", "scallion", "scallop", "scalping", "scam", "scandal", "scanner", "scanning", + "scant", "scapegoat", "scarce", "scarcity", "scarecrow", "scared", "scarf", "scarily", + "scariness", "scarring", "scary", "scavenger", "scenic", "schedule", "schematic", "scheme", + "scheming", "schilling", "schnapps", "scholar", "science", "scientist", "scion", "scoff", + "scolding", "scone", "scoop", "scooter", "scope", "scorch", "scorebook", "scorecard", + "scored", "scoreless", "scorer", "scoring", "scorn", "scorpion", "scotch", "scoundrel", + "scoured", "scouring", "scouting", "scouts", "scowling", "scrabble", "scraggly", + "scrambled", "scrambler", "scrap", "scratch", "scrawny", "screen", "scribble", "scribe", + "scribing", "scrimmage", "script", "scroll", "scrooge", "scrounger", "scrubbed", + "scrubber", "scruffy", "scrunch", "scrutiny", "scuba", "scuff", "sculptor", "sculpture", + "scurvy", "scuttle", "secluded", "secluding", "seclusion", "second", "secrecy", "secret", + "sectional", "sector", "secular", "securely", "security", "sedan", "sedate", "sedation", + "sedative", "sediment", "seduce", "seducing", "segment", "seismic", "seizing", "seldom", + "selected", "selection", "selective", "selector", "self", "seltzer", "semantic", + "semester", "semicolon", "semifinal", "seminar", "semisoft", "semisweet", "senate", + "senator", "send", "senior", "senorita", "sensation", "sensitive", "sensitize", + "sensually", "sensuous", "sepia", "september", "septic", "septum", "sequel", "sequence", + "sequester", "series", "sermon", "serotonin", "serpent", "serrated", "serve", "service", + "serving", "sesame", "sessions", "setback", "setting", "settle", "settling", "setup", + "sevenfold", "seventeen", "seventh", "seventy", "severity", "shabby", "shack", "shaded", + "shadily", "shadiness", "shading", "shadow", "shady", "shaft", "shakable", "shakily", + "shakiness", "shaking", "shaky", "shale", "shallot", "shallow", "shame", "shampoo", + "shamrock", "shank", "shanty", "shape", "shaping", "share", "sharpener", "sharper", + "sharpie", "sharply", "sharpness", "shawl", "sheath", "shed", "sheep", "sheet", "shelf", + "shell", "shelter", "shelve", "shelving", "sherry", "shield", "shifter", "shifting", + "shiftless", "shifty", "shimmer", "shimmy", "shindig", "shine", "shingle", "shininess", + "shining", "shiny", "ship", "shirt", "shivering", "shock", "shone", "shoplift", "shopper", + "shopping", "shoptalk", "shore", "shortage", "shortcake", "shortcut", "shorten", "shorter", + "shorthand", "shortlist", "shortly", "shortness", "shorts", "shortwave", "shorty", "shout", + "shove", "showbiz", "showcase", "showdown", "shower", "showgirl", "showing", "showman", + "shown", "showoff", "showpiece", "showplace", "showroom", "showy", "shrank", "shrapnel", + "shredder", "shredding", "shrewdly", "shriek", "shrill", "shrimp", "shrine", "shrink", + "shrivel", "shrouded", "shrubbery", "shrubs", "shrug", "shrunk", "shucking", "shudder", + "shuffle", "shuffling", "shun", "shush", "shut", "shy", "siamese", "siberian", "sibling", + "siding", "sierra", "siesta", "sift", "sighing", "silenced", "silencer", "silent", + "silica", "silicon", "silk", "silliness", "silly", "silo", "silt", "silver", "similarly", + "simile", "simmering", "simple", "simplify", "simply", "sincere", "sincerity", "singer", + "singing", "single", "singular", "sinister", "sinless", "sinner", "sinuous", "sip", + "siren", "sister", "sitcom", "sitter", "sitting", "situated", "situation", "sixfold", + "sixteen", "sixth", "sixties", "sixtieth", "sixtyfold", "sizable", "sizably", "size", + "sizing", "sizzle", "sizzling", "skater", "skating", "skedaddle", "skeletal", "skeleton", + "skeptic", "sketch", "skewed", "skewer", "skid", "skied", "skier", "skies", "skiing", + "skilled", "skillet", "skillful", "skimmed", "skimmer", "skimming", "skimpily", "skincare", + "skinhead", "skinless", "skinning", "skinny", "skintight", "skipper", "skipping", + "skirmish", "skirt", "skittle", "skydiver", "skylight", "skyline", "skype", "skyrocket", + "skyward", "slab", "slacked", "slacker", "slacking", "slackness", "slacks", "slain", + "slam", "slander", "slang", "slapping", "slapstick", "slashed", "slashing", "slate", + "slather", "slaw", "sled", "sleek", "sleep", "sleet", "sleeve", "slept", "sliceable", + "sliced", "slicer", "slicing", "slick", "slider", "slideshow", "sliding", "slighted", + "slighting", "slightly", "slimness", "slimy", "slinging", "slingshot", "slinky", "slip", + "slit", "sliver", "slobbery", "slogan", "sloped", "sloping", "sloppily", "sloppy", "slot", + "slouching", "slouchy", "sludge", "slug", "slum", "slurp", "slush", "sly", "small", + "smartly", "smartness", "smasher", "smashing", "smashup", "smell", "smelting", "smile", + "smilingly", "smirk", "smite", "smith", "smitten", "smock", "smog", "smoked", "smokeless", + "smokiness", "smoking", "smoky", "smolder", "smooth", "smother", "smudge", "smudgy", + "smuggler", "smuggling", "smugly", "smugness", "snack", "snagged", "snaking", "snap", + "snare", "snarl", "snazzy", "sneak", "sneer", "sneeze", "sneezing", "snide", "sniff", + "snippet", "snipping", "snitch", "snooper", "snooze", "snore", "snoring", "snorkel", + "snort", "snout", "snowbird", "snowboard", "snowbound", "snowcap", "snowdrift", "snowdrop", + "snowfall", "snowfield", "snowflake", "snowiness", "snowless", "snowman", "snowplow", + "snowshoe", "snowstorm", "snowsuit", "snowy", "snub", "snuff", "snuggle", "snugly", + "snugness", "speak", "spearfish", "spearhead", "spearman", "spearmint", "species", + "specimen", "specked", "speckled", "specks", "spectacle", "spectator", "spectrum", + "speculate", "speech", "speed", "spellbind", "speller", "spelling", "spendable", "spender", + "spending", "spent", "spew", "sphere", "spherical", "sphinx", "spider", "spied", "spiffy", + "spill", "spilt", "spinach", "spinal", "spindle", "spinner", "spinning", "spinout", + "spinster", "spiny", "spiral", "spirited", "spiritism", "spirits", "spiritual", "splashed", + "splashing", "splashy", "splatter", "spleen", "splendid", "splendor", "splice", "splicing", + "splinter", "splotchy", "splurge", "spoilage", "spoiled", "spoiler", "spoiling", "spoils", + "spoken", "spokesman", "sponge", "spongy", "sponsor", "spoof", "spookily", "spooky", + "spool", "spoon", "spore", "sporting", "sports", "sporty", "spotless", "spotlight", + "spotted", "spotter", "spotting", "spotty", "spousal", "spouse", "spout", "sprain", + "sprang", "sprawl", "spray", "spree", "sprig", "spring", "sprinkled", "sprinkler", + "sprint", "sprite", "sprout", "spruce", "sprung", "spry", "spud", "spur", "sputter", + "spyglass", "squabble", "squad", "squall", "squander", "squash", "squatted", "squatter", + "squatting", "squeak", "squealer", "squealing", "squeamish", "squeegee", "squeeze", + "squeezing", "squid", "squiggle", "squiggly", "squint", "squire", "squirt", "squishier", + "squishy", "stability", "stabilize", "stable", "stack", "stadium", "staff", "stage", + "staging", "stagnant", "stagnate", "stainable", "stained", "staining", "stainless", + "stalemate", "staleness", "stalling", "stallion", "stamina", "stammer", "stamp", "stand", + "stank", "staple", "stapling", "starboard", "starch", "stardom", "stardust", "starfish", + "stargazer", "staring", "stark", "starless", "starlet", "starlight", "starlit", "starring", + "starry", "starship", "starter", "starting", "startle", "startling", "startup", "starved", + "starving", "stash", "state", "static", "statistic", "statue", "stature", "status", + "statute", "statutory", "staunch", "stays", "steadfast", "steadier", "steadily", + "steadying", "steam", "steed", "steep", "steerable", "steering", "steersman", "stegosaur", + "stellar", "stem", "stench", "stencil", "step", "stereo", "sterile", "sterility", + "sterilize", "sterling", "sternness", "sternum", "stew", "stick", "stiffen", "stiffly", + "stiffness", "stifle", "stifling", "stillness", "stilt", "stimulant", "stimulate", + "stimuli", "stimulus", "stinger", "stingily", "stinging", "stingray", "stingy", "stinking", + "stinky", "stipend", "stipulate", "stir", "stitch", "stock", "stoic", "stoke", "stole", + "stomp", "stonewall", "stoneware", "stonework", "stoning", "stony", "stood", "stooge", + "stool", "stoop", "stoplight", "stoppable", "stoppage", "stopped", "stopper", "stopping", + "stopwatch", "storable", "storage", "storeroom", "storewide", "storm", "stout", "stove", + "stowaway", "stowing", "straddle", "straggler", "strained", "strainer", "straining", + "strangely", "stranger", "strangle", "strategic", "strategy", "stratus", "straw", "stray", + "streak", "stream", "street", "strength", "strenuous", "strep", "stress", "stretch", + "strewn", "stricken", "strict", "stride", "strife", "strike", "striking", "strive", + "striving", "strobe", "strode", "stroller", "strongbox", "strongly", "strongman", "struck", + "structure", "strudel", "struggle", "strum", "strung", "strut", "stubbed", "stubble", + "stubbly", "stubborn", "stucco", "stuck", "student", "studied", "studio", "study", + "stuffed", "stuffing", "stuffy", "stumble", "stumbling", "stump", "stung", "stunned", + "stunner", "stunning", "stunt", "stupor", "sturdily", "sturdy", "styling", "stylishly", + "stylist", "stylized", "stylus", "suave", "subarctic", "subatomic", "subdivide", "subdued", + "subduing", "subfloor", "subgroup", "subheader", "subject", "sublease", "sublet", + "sublevel", "sublime", "submarine", "submerge", "submersed", "submitter", "subpanel", + "subpar", "subplot", "subprime", "subscribe", "subscript", "subsector", "subside", + "subsiding", "subsidize", "subsidy", "subsoil", "subsonic", "substance", "subsystem", + "subtext", "subtitle", "subtly", "subtotal", "subtract", "subtype", "suburb", "subway", + "subwoofer", "subzero", "succulent", "such", "suction", "sudden", "sudoku", "suds", + "sufferer", "suffering", "suffice", "suffix", "suffocate", "suffrage", "sugar", "suggest", + "suing", "suitable", "suitably", "suitcase", "suitor", "sulfate", "sulfide", "sulfite", + "sulfur", "sulk", "sullen", "sulphate", "sulphuric", "sultry", "superbowl", "superglue", + "superhero", "superior", "superjet", "superman", "supermom", "supernova", "supervise", + "supper", "supplier", "supply", "support", "supremacy", "supreme", "surcharge", "surely", + "sureness", "surface", "surfacing", "surfboard", "surfer", "surgery", "surgical", + "surging", "surname", "surpass", "surplus", "surprise", "surreal", "surrender", + "surrogate", "surround", "survey", "survival", "survive", "surviving", "survivor", "sushi", + "suspect", "suspend", "suspense", "sustained", "sustainer", "swab", "swaddling", "swagger", + "swampland", "swan", "swapping", "swarm", "sway", "swear", "sweat", "sweep", "swell", + "swept", "swerve", "swifter", "swiftly", "swiftness", "swimmable", "swimmer", "swimming", + "swimsuit", "swimwear", "swinger", "swinging", "swipe", "swirl", "switch", "swivel", + "swizzle", "swooned", "swoop", "swoosh", "swore", "sworn", "swung", "sycamore", "sympathy", + "symphonic", "symphony", "symptom", "synapse", "syndrome", "synergy", "synopses", + "synopsis", "synthesis", "synthetic", "syrup", "system", "t-shirt", "tabasco", "tabby", + "tableful", "tables", "tablet", "tableware", "tabloid", "tackiness", "tacking", "tackle", + "tackling", "tacky", "taco", "tactful", "tactical", "tactics", "tactile", "tactless", + "tadpole", "taekwondo", "tag", "tainted", "take", "taking", "talcum", "talisman", "tall", + "talon", "tamale", "tameness", "tamer", "tamper", "tank", "tanned", "tannery", "tanning", + "tantrum", "tapeless", "tapered", "tapering", "tapestry", "tapioca", "tapping", "taps", + "tarantula", "target", "tarmac", "tarnish", "tarot", "tartar", "tartly", "tartness", + "task", "tassel", "taste", "tastiness", "tasting", "tasty", "tattered", "tattle", + "tattling", "tattoo", "taunt", "tavern", "thank", "that", "thaw", "theater", "theatrics", + "thee", "theft", "theme", "theology", "theorize", "thermal", "thermos", "thesaurus", + "these", "thesis", "thespian", "thicken", "thicket", "thickness", "thieving", "thievish", + "thigh", "thimble", "thing", "think", "thinly", "thinner", "thinness", "thinning", + "thirstily", "thirsting", "thirsty", "thirteen", "thirty", "thong", "thorn", "those", + "thousand", "thrash", "thread", "threaten", "threefold", "thrift", "thrill", "thrive", + "thriving", "throat", "throbbing", "throng", "throttle", "throwaway", "throwback", + "thrower", "throwing", "thud", "thumb", "thumping", "thursday", "thus", "thwarting", + "thyself", "tiara", "tibia", "tidal", "tidbit", "tidiness", "tidings", "tidy", "tiger", + "tighten", "tightly", "tightness", "tightrope", "tightwad", "tigress", "tile", "tiling", + "till", "tilt", "timid", "timing", "timothy", "tinderbox", "tinfoil", "tingle", "tingling", + "tingly", "tinker", "tinkling", "tinsel", "tinsmith", "tint", "tinwork", "tiny", "tipoff", + "tipped", "tipper", "tipping", "tiptoeing", "tiptop", "tiring", "tissue", "trace", + "tracing", "track", "traction", "tractor", "trade", "trading", "tradition", "traffic", + "tragedy", "trailing", "trailside", "train", "traitor", "trance", "tranquil", "transfer", + "transform", "translate", "transpire", "transport", "transpose", "trapdoor", "trapeze", + "trapezoid", "trapped", "trapper", "trapping", "traps", "trash", "travel", "traverse", + "travesty", "tray", "treachery", "treading", "treadmill", "treason", "treat", "treble", + "tree", "trekker", "tremble", "trembling", "tremor", "trench", "trend", "trespass", + "triage", "trial", "triangle", "tribesman", "tribunal", "tribune", "tributary", "tribute", + "triceps", "trickery", "trickily", "tricking", "trickle", "trickster", "tricky", + "tricolor", "tricycle", "trident", "tried", "trifle", "trifocals", "trillion", "trilogy", + "trimester", "trimmer", "trimming", "trimness", "trinity", "trio", "tripod", "tripping", + "triumph", "trivial", "trodden", "trolling", "trombone", "trophy", "tropical", "tropics", + "trouble", "troubling", "trough", "trousers", "trout", "trowel", "truce", "truck", + "truffle", "trump", "trunks", "trustable", "trustee", "trustful", "trusting", "trustless", + "truth", "try", "tubby", "tubeless", "tubular", "tucking", "tuesday", "tug", "tuition", + "tulip", "tumble", "tumbling", "tummy", "turban", "turbine", "turbofan", "turbojet", + "turbulent", "turf", "turkey", "turmoil", "turret", "turtle", "tusk", "tutor", "tutu", + "tux", "tweak", "tweed", "tweet", "tweezers", "twelve", "twentieth", "twenty", "twerp", + "twice", "twiddle", "twiddling", "twig", "twilight", "twine", "twins", "twirl", + "twistable", "twisted", "twister", "twisting", "twisty", "twitch", "twitter", "tycoon", + "tying", "tyke", "udder", "ultimate", "ultimatum", "ultra", "umbilical", "umbrella", + "umpire", "unabashed", "unable", "unadorned", "unadvised", "unafraid", "unaired", + "unaligned", "unaltered", "unarmored", "unashamed", "unaudited", "unawake", "unaware", + "unbaked", "unbalance", "unbeaten", "unbend", "unbent", "unbiased", "unbitten", + "unblended", "unblessed", "unblock", "unbolted", "unbounded", "unboxed", "unbraided", + "unbridle", "unbroken", "unbuckled", "unbundle", "unburned", "unbutton", "uncanny", + "uncapped", "uncaring", "uncertain", "unchain", "unchanged", "uncharted", "uncheck", + "uncivil", "unclad", "unclaimed", "unclamped", "unclasp", "uncle", "unclip", "uncloak", + "unclog", "unclothed", "uncoated", "uncoiled", "uncolored", "uncombed", "uncommon", + "uncooked", "uncork", "uncorrupt", "uncounted", "uncouple", "uncouth", "uncover", + "uncross", "uncrown", "uncrushed", "uncured", "uncurious", "uncurled", "uncut", + "undamaged", "undated", "undaunted", "undead", "undecided", "undefined", "underage", + "underarm", "undercoat", "undercook", "undercut", "underdog", "underdone", "underfed", + "underfeed", "underfoot", "undergo", "undergrad", "underhand", "underline", "underling", + "undermine", "undermost", "underpaid", "underpass", "underpay", "underrate", "undertake", + "undertone", "undertook", "undertow", "underuse", "underwear", "underwent", "underwire", + "undesired", "undiluted", "undivided", "undocked", "undoing", "undone", "undrafted", + "undress", "undrilled", "undusted", "undying", "unearned", "unearth", "unease", "uneasily", + "uneasy", "uneatable", "uneaten", "unedited", "unelected", "unending", "unengaged", + "unenvied", "unequal", "unethical", "uneven", "unexpired", "unexposed", "unfailing", + "unfair", "unfasten", "unfazed", "unfeeling", "unfiled", "unfilled", "unfitted", + "unfitting", "unfixable", "unfixed", "unflawed", "unfocused", "unfold", "unfounded", + "unframed", "unfreeze", "unfrosted", "unfrozen", "unfunded", "unglazed", "ungloved", + "unglue", "ungodly", "ungraded", "ungreased", "unguarded", "unguided", "unhappily", + "unhappy", "unharmed", "unhealthy", "unheard", "unhearing", "unheated", "unhelpful", + "unhidden", "unhinge", "unhitched", "unholy", "unhook", "unicorn", "unicycle", "unified", + "unifier", "uniformed", "uniformly", "unify", "unimpeded", "uninjured", "uninstall", + "uninsured", "uninvited", "union", "uniquely", "unisexual", "unison", "unissued", "unit", + "universal", "universe", "unjustly", "unkempt", "unkind", "unknotted", "unknowing", + "unknown", "unlaced", "unlatch", "unlawful", "unleaded", "unlearned", "unleash", "unless", + "unleveled", "unlighted", "unlikable", "unlimited", "unlined", "unlinked", "unlisted", + "unlit", "unlivable", "unloaded", "unloader", "unlocked", "unlocking", "unlovable", + "unloved", "unlovely", "unloving", "unluckily", "unlucky", "unmade", "unmanaged", + "unmanned", "unmapped", "unmarked", "unmasked", "unmasking", "unmatched", "unmindful", + "unmixable", "unmixed", "unmolded", "unmoral", "unmovable", "unmoved", "unmoving", + "unnamable", "unnamed", "unnatural", "unneeded", "unnerve", "unnerving", "unnoticed", + "unopened", "unopposed", "unpack", "unpadded", "unpaid", "unpainted", "unpaired", + "unpaved", "unpeeled", "unpicked", "unpiloted", "unpinned", "unplanned", "unplanted", + "unpleased", "unpledged", "unplowed", "unplug", "unpopular", "unproven", "unquote", + "unranked", "unrated", "unraveled", "unreached", "unread", "unreal", "unreeling", + "unrefined", "unrelated", "unrented", "unrest", "unretired", "unrevised", "unrigged", + "unripe", "unrivaled", "unroasted", "unrobed", "unroll", "unruffled", "unruly", "unrushed", + "unsaddle", "unsafe", "unsaid", "unsalted", "unsaved", "unsavory", "unscathed", + "unscented", "unscrew", "unsealed", "unseated", "unsecured", "unseeing", "unseemly", + "unseen", "unselect", "unselfish", "unsent", "unsettled", "unshackle", "unshaken", + "unshaved", "unshaven", "unsheathe", "unshipped", "unsightly", "unsigned", "unskilled", + "unsliced", "unsmooth", "unsnap", "unsocial", "unsoiled", "unsold", "unsolved", "unsorted", + "unspoiled", "unspoken", "unstable", "unstaffed", "unstamped", "unsteady", "unsterile", + "unstirred", "unstitch", "unstopped", "unstuck", "unstuffed", "unstylish", "unsubtle", + "unsubtly", "unsuited", "unsure", "unsworn", "untagged", "untainted", "untaken", "untamed", + "untangled", "untapped", "untaxed", "unthawed", "unthread", "untidy", "untie", "until", + "untimed", "untimely", "untitled", "untoasted", "untold", "untouched", "untracked", + "untrained", "untreated", "untried", "untrimmed", "untrue", "untruth", "unturned", + "untwist", "untying", "unusable", "unused", "unusual", "unvalued", "unvaried", "unvarying", + "unveiled", "unveiling", "unvented", "unviable", "unvisited", "unvocal", "unwanted", + "unwarlike", "unwary", "unwashed", "unwatched", "unweave", "unwed", "unwelcome", "unwell", + "unwieldy", "unwilling", "unwind", "unwired", "unwitting", "unwomanly", "unworldly", + "unworn", "unworried", "unworthy", "unwound", "unwoven", "unwrapped", "unwritten", "unzip", + "upbeat", "upchuck", "upcoming", "upcountry", "update", "upfront", "upgrade", "upheaval", + "upheld", "uphill", "uphold", "uplifted", "uplifting", "upload", "upon", "upper", + "upright", "uprising", "upriver", "uproar", "uproot", "upscale", "upside", "upstage", + "upstairs", "upstart", "upstate", "upstream", "upstroke", "upswing", "uptake", "uptight", + "uptown", "upturned", "upward", "upwind", "uranium", "urban", "urchin", "urethane", + "urgency", "urgent", "urging", "urologist", "urology", "usable", "usage", "useable", + "used", "uselessly", "user", "usher", "usual", "utensil", "utility", "utilize", "utmost", + "utopia", "utter", "vacancy", "vacant", "vacate", "vacation", "vagabond", "vagrancy", + "vagrantly", "vaguely", "vagueness", "valiant", "valid", "valium", "valley", "valuables", + "value", "vanilla", "vanish", "vanity", "vanquish", "vantage", "vaporizer", "variable", + "variably", "varied", "variety", "various", "varmint", "varnish", "varsity", "varying", + "vascular", "vaseline", "vastly", "vastness", "veal", "vegan", "veggie", "vehicular", + "velcro", "velocity", "velvet", "vendetta", "vending", "vendor", "veneering", "vengeful", + "venomous", "ventricle", "venture", "venue", "venus", "verbalize", "verbally", "verbose", + "verdict", "verify", "verse", "version", "versus", "vertebrae", "vertical", "vertigo", + "very", "vessel", "vest", "veteran", "veto", "vexingly", "viability", "viable", "vibes", + "vice", "vicinity", "victory", "video", "viewable", "viewer", "viewing", "viewless", + "viewpoint", "vigorous", "village", "villain", "vindicate", "vineyard", "vintage", + "violate", "violation", "violator", "violet", "violin", "viper", "viral", "virtual", + "virtuous", "virus", "visa", "viscosity", "viscous", "viselike", "visible", "visibly", + "vision", "visiting", "visitor", "visor", "vista", "vitality", "vitalize", "vitally", + "vitamins", "vivacious", "vividly", "vividness", "vixen", "vocalist", "vocalize", + "vocally", "vocation", "voice", "voicing", "void", "volatile", "volley", "voltage", + "volumes", "voter", "voting", "voucher", "vowed", "vowel", "voyage", "wackiness", "wad", + "wafer", "waffle", "waged", "wager", "wages", "waggle", "wagon", "wake", "waking", "walk", + "walmart", "walnut", "walrus", "waltz", "wand", "wannabe", "wanted", "wanting", "wasabi", + "washable", "washbasin", "washboard", "washbowl", "washcloth", "washday", "washed", + "washer", "washhouse", "washing", "washout", "washroom", "washstand", "washtub", "wasp", + "wasting", "watch", "water", "waviness", "waving", "wavy", "whacking", "whacky", "wham", + "wharf", "wheat", "whenever", "whiff", "whimsical", "whinny", "whiny", "whisking", + "whoever", "whole", "whomever", "whoopee", "whooping", "whoops", "why", "wick", "widely", + "widen", "widget", "widow", "width", "wieldable", "wielder", "wife", "wifi", "wikipedia", + "wildcard", "wildcat", "wilder", "wildfire", "wildfowl", "wildland", "wildlife", "wildly", + "wildness", "willed", "willfully", "willing", "willow", "willpower", "wilt", "wimp", + "wince", "wincing", "wind", "wing", "winking", "winner", "winnings", "winter", "wipe", + "wired", "wireless", "wiring", "wiry", "wisdom", "wise", "wish", "wisplike", "wispy", + "wistful", "wizard", "wobble", "wobbling", "wobbly", "wok", "wolf", "wolverine", + "womanhood", "womankind", "womanless", "womanlike", "womanly", "womb", "woof", "wooing", + "wool", "woozy", "word", "work", "worried", "worrier", "worrisome", "worry", "worsening", + "worshiper", "worst", "wound", "woven", "wow", "wrangle", "wrath", "wreath", "wreckage", + "wrecker", "wrecking", "wrench", "wriggle", "wriggly", "wrinkle", "wrinkly", "wrist", + "writing", "written", "wrongdoer", "wronged", "wrongful", "wrongly", "wrongness", + "wrought", "xbox", "xerox", "yahoo", "yam", "yanking", "yapping", "yard", "yarn", "yeah", + "yearbook", "yearling", "yearly", "yearning", "yeast", "yelling", "yelp", "yen", + "yesterday", "yiddish", "yield", "yin", "yippee", "yo-yo", "yodel", "yoga", "yogurt", + "yonder", "yoyo", "yummy", "zap", "zealous", "zebra", "zen", "zeppelin", "zero", + "zestfully", "zesty", "zigzagged", "zipfile", "zipping", "zippy", "zips", "zit", "zodiac", + "zombie", "zone", "zoning", "zookeeper", "zoologist", "zoology", "zoom", }; } } diff --git a/Readme.md b/Readme.md index e3fa558..f4cb17b 100644 --- a/Readme.md +++ b/Readme.md @@ -90,8 +90,18 @@ string otp = Password.ForOtp(6).Next(); // 6-digit one-time code string apiKey = Password.ForApiKey(32).Next(); // URL-safe token string envName = Password.ForEnvironmentName(12).Next();// readable id, no look-alike characters string phrase = Password.ForPassphrase(4).Next(); // e.g. "maple-river-quartz-bloom-42" +string strong = Password.ForPassphraseWithEntropy(80).Next(); // word count derived to clear 80 bits +string memorable = Password.ForMemorable().Next(); // capitalized, ~80+ bits, e.g. "Maple-River-Quartz-Bloom-Glade-Vivid-42" ``` +`ForPassphraseWithEntropy(targetBits)` derives the word count needed to reach the target and +enforces it as a floor. You can also pass `minimumEntropyBits` to `ForPassphrase(...)` to reject +configurations that are too weak. + +For sites that require a digit and a symbol, pass `includeSymbol: true`. A random symbol is attached +to one randomly chosen word (e.g. `maple-river#-quartz-bloom-42`), so the phrase passes composition +rules while staying memorable. + ## Quality controls ```csharp @@ -146,8 +156,25 @@ public class SignupService(IPasswordGenerator generator) } ``` +To register a passphrase generator instead, set the `Passphrase` options (or bind a `Passphrase` +section from configuration): + +```csharp +services.AddPasswordGenerator(o => + o.Passphrase = new PassphraseOptions { WordCount = 6, Capitalize = true }); +``` + ## Documentation - [v2 → v3 migration guide](docs/migration-v2-to-v3.md) - [Changelog](CHANGELOG.md) - [Design & architecture docs](docs/README.md) + +## License & attribution + +PasswordGenerator is licensed under the [MIT License](License.md). + +Passphrases are generated from the **EFF Large Wordlist** (7,776 words) by the +[Electronic Frontier Foundation](https://www.eff.org/dice), used under the +[Creative Commons Attribution 3.0 US](https://creativecommons.org/licenses/by/3.0/us/) +license. See [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md) for details. diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md new file mode 100644 index 0000000..0ed49f3 --- /dev/null +++ b/THIRD-PARTY-NOTICES.md @@ -0,0 +1,21 @@ +# Third-Party Notices + +This project (PasswordGenerator) is licensed under the MIT License (see +`License.md`). It also includes third-party data, listed below, that is +distributed under its own license. + +## EFF Large Wordlist + +`PasswordGenerator/WordList.cs` embeds the **EFF Large Wordlist** (7,776 words), +created by the **Electronic Frontier Foundation** (Joseph Bonneau) and published at: + +- https://www.eff.org/dice +- https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt + +**License:** Creative Commons Attribution 3.0 United States (CC BY 3.0 US) +https://creativecommons.org/licenses/by/3.0/us/ + +**Modifications:** The original tab-separated `dice-numberword` rows were +reformatted into a C# `string[]` array. The words themselves are unchanged. + +The EFF Large Wordlist is used here to generate diceware-style passphrases. diff --git a/docs/api-surface.md b/docs/api-surface.md index 7e3fffc..8a47a15 100644 --- a/docs/api-surface.md +++ b/docs/api-surface.md @@ -31,6 +31,7 @@ flowchart TD g3["NextAsync(ct) : ValueTask~string~"] g4["Generate() / Generate(count)"] g5["GenerateAsync() / GenerateAsync(count, ct)"] + g6["EstimateEntropyBits() : double"] end Entry --> Build --> Gen classDef good fill:#e6ffe6,stroke:#009900; @@ -58,11 +59,26 @@ flowchart LR ForOwasp --> O["all printable ASCII, no forced composition"] ForNist --> Nn["NIST 800-63B aligned length/charset"] ForOtp --> Ot["short numeric, e.g. 4-6 digits"] - ForPassphrase --> Pp["diceware word-list"] + ForPassphrase --> Pp["EFF Large Wordlist (7,776 words)"] + ForPassphraseWithEntropy --> Pe["word count derived from a target bits"] + ForMemorable --> Pm["capitalized words, ~80+ bits"] ForApiKey --> Ak["long, URL-safe charset"] ForEnvironmentName --> En["readable, memorable identifiers"] ``` +### Passphrases + +Passphrases are built from the **EFF Large Wordlist** (7,776 words, ~12.9 bits/word; CC BY 3.0, see +`THIRD-PARTY-NOTICES.md`). Beyond `ForPassphrase(words, ...)`: + +- `ForPassphraseWithEntropy(targetBits)` derives the word count needed to clear a target and enforces + it as a floor; `ForPassphrase(..., minimumEntropyBits)` enforces a floor for an explicit word count. +- `includeSymbol: true` attaches a random symbol to one randomly chosen word, satisfying + "needs a number and a symbol" composition rules while staying memorable. +- `EstimateEntropyBits()` (on `IPasswordGenerator`) reports the estimated strength. +- Via DI, set `PasswordOptions.Passphrase` (a `PassphraseOptions`) in code or bind a `Passphrase` + configuration section to resolve a passphrase `IPasswordGenerator`. + Presets are static factory methods on `Password` (sugar over the fluent builder); any subsequent fluent call still overrides them (resolution order is documented in `configuration-and-di.md`). diff --git a/docs/architecture.md b/docs/architecture.md index c594d81..27961e9 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -17,6 +17,7 @@ classDiagram +Generate(int count) IReadOnlyList +GenerateAsync(CancellationToken) Task +GenerateAsync(int count, CancellationToken) Task + +EstimateEntropyBits() double } class IPassword { <> @@ -36,15 +37,30 @@ classDiagram class Password { +static ForOwasp/ForNist/ForOtp() IPassword +static ForApiKey/ForEnvironmentName() IPassword - +static ForPassphrase() IPasswordGenerator + +static ForPassphrase()/ForPassphraseWithEntropy()/ForMemorable() IPasswordGenerator + +EstimateEntropyBits() double + } + class PassphraseGenerator { + +WordCount, Separator, Capitalize + +IncludeNumber, IncludeSymbol, MinimumEntropyBits + +static WordCountForEntropy(bits, includeNumber) int +EstimateEntropyBits() double } + class WordList { + <> + EFF Large Wordlist (7,776 words, CC BY 3.0) + } class PasswordOptions { +IncludeLowercase/Uppercase/Numeric/Special +SpecialCharacters, Length +ExcludeAmbiguous, DefaultBatchCount + +Passphrase : PassphraseOptions? +bind from IConfiguration } + class PassphraseOptions { + +WordCount, Separator, Capitalize + +IncludeNumber, IncludeSymbol, MinimumEntropyBits + } class IRandomSource { <> +int NextInt(int maxExclusive) @@ -61,7 +77,11 @@ classDiagram IPasswordGenerator <|.. Password IPasswordGenerator <|.. PassphraseGenerator Password --> IRandomSource : uses + PassphraseGenerator --> IRandomSource : uses + PassphraseGenerator --> WordList : samples PasswordOptions ..> Password : configures (DI) + PasswordOptions *-- PassphraseOptions + PassphraseOptions ..> PassphraseGenerator : configures (DI) IRandomSource <|.. CryptoRandomSource IEntropyEstimator <|.. PoolEntropyEstimator Password ..> PoolEntropyEstimator : EstimateEntropyBits @@ -71,7 +91,12 @@ Key points: - **`IRandomSource` abstraction** wraps the CSPRNG (unbiased `RandomNumberGenerator.GetInt32`). No `static`, injectable — a deterministic `IRandomSource` can be injected in unit tests — and the Guid-based `Shuffle` is gone in favour of Fisher–Yates. -- **`PasswordOptions`** is the DI config object, bindable from `IConfiguration`. +- **`PasswordOptions`** is the DI config object, bindable from `IConfiguration`. Setting its + `Passphrase` (a `PassphraseOptions`) makes the DI registration resolve a `PassphraseGenerator` + instead of a character `Password`. +- **Passphrases** (`PassphraseGenerator`) sample the internal `WordList` (the EFF Large Wordlist, + CC BY 3.0) and share the injectable `IRandomSource`, with entropy targeting/floor and optional + symbol injection. - **Presets** are static factory methods on `Password` that pre-fill the fluent builder. - The `[Obsolete]` v2 wrappers from earlier proposals are not present.