summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbaren@mit.edu>2015-03-14 19:47:09 -0400
committerGravatar Benjamin Barenblat <bbaren@mit.edu>2015-03-14 19:47:09 -0400
commitaadb9e2e90925a187877241e50110e4ce7ea80a1 (patch)
tree7cb115e040db2a73c10e5da3f0fe4c16c9f39f9b
Imported Upstream version 1.3upstream/1.3
-rw-r--r--ChangeLog36
-rw-r--r--Makefile.proto100
-rw-r--r--README27
-rw-r--r--cexcept.h243
-rw-r--r--diagnostics.h41
-rw-r--r--diceware8k.c8201
-rw-r--r--exceptions.h43
-rw-r--r--main.c222
-rw-r--r--pwgen.c313
-rw-r--r--pwgen.h130
-rw-r--r--secpwgen.1293
-rw-r--r--secure_memory.h57
-rw-r--r--secure_memory_unix.c135
-rw-r--r--secure_random.h69
-rw-r--r--secure_random_cryptlib.c84
-rw-r--r--secure_random_openssl.c108
-rw-r--r--skeylist.c263
17 files changed, 10365 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..ea40d18
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,36 @@
+Changes in 1.3
+* Added koremutake method for pronouncible password generation.
+* Moved to MIT license
+
+Changes in 1.2
+* Added cryptlib support
+
+* Added an option to compile with mlock() instead of mlockall().
+ - mlockall() caused problems on some Linux 2.6 distros because it would
+ succeed even for ordinary users. some library component would then
+ try to allocate too much memory which would exceed the process'
+ resource limits for locked memory. being unable to allocate memory has
+ resulted in a crash.
+
+* Minor code improvements:
+ - uses mprotect(PROT_NONE) on the last page of secure memory so that the
+ segmentation fault is guaranteed on buffer overflow
+ - minor cleanups
+
+* Updated manpage
+
+Changes in 1.1
+* Major security improvements:
+ - memory locking
+ - zeroing "secure" memory on exit
+ - disabling core dumps
+ - dropping root privileges after memory locking
+ - printing a warning if security can't be completely set up
+
+* The program does no buffer length checking. If you try to generate too long
+ passphrase, the program will CRASH because of buffer overrun. For that
+ event to happen the passphrase would have to be long about 3000 characters.
+
+* Major code cleanups.
+
+* Added the manual page.
diff --git a/Makefile.proto b/Makefile.proto
new file mode 100644
index 0000000..e932ed4
--- /dev/null
+++ b/Makefile.proto
@@ -0,0 +1,100 @@
+##############################################################################
+# USER CONFIGURATION
+# You MUST set all of the following variables for the compilation to succeed.
+##############################################################################
+
+##
+# paths to crypto library headers and archives. if they are not in the
+# standard system locations (this really depends on the OS you are using),
+# then UNCOMMENT the CRYPTO_INCLUDE_PATH and CRYPTO_LIBRARY_PATH and add the
+# appropriate paths immediately after -I, resp. -L.
+#
+# OpenSSL
+# -------
+# The include path is the directory containing the openssl include
+# directory (e.g. if OpenSSL is installed in /usr/local/ssl, its include
+# files are in /usr/local/ssl/include/openssl and you must set the
+# CRYPTO_INCLUDE_PATH to -I/usr/local/ssl/include).
+#
+# The library path for OpenSSL is the one containing libcrypto.so or
+# libcrypto.a (e.g. set CRYPTO_LIBRARY_PATH to -L/usr/local/ssl/lib)
+#
+# cryptlib
+# --------
+# The include directory is the one containing the cryptlib.h file.
+# The library path is the one containing libcl.so or libcl.a.
+##
+#CRYPTO_INCLUDE_PATH = -I/replace/this/with/real/path
+#CRYPTO_LIBRARY_PATH = -L/replace/this/with/real/path
+
+##
+# If using OpenSSL, uncomment the following 3 lines.
+##
+#CRYPTO_CFLAGS =
+#CRYPTO_OBJS = secure_random_openssl.o
+#CRYPTO_LIBS = -lcrypto
+
+##
+# If using cryptlib, uncomment the following 3 lines.
+##
+#CRYPTO_CFLAGS = -D_REENTRANT
+#CRYPTO_OBJS = secure_random_cryptlib.o
+#CRYPTO_LIBS = -lcl -lpthread
+
+##
+# Change PREFIX to install to different directories. The binary is installed
+# in $PREFIX/bin, and the man in $PREFIX/man/man1
+##
+PREFIX = /usr/local
+
+##
+# On some operating systems (most notably Linux 2.6 kernels) using mlockall
+# causes the program to fail with segmentation fault because it tries to
+# allocate memory beyond its current resource limits for locked memory. If
+# you experience crashes immediately at startup, uncomment the following line.
+##
+#
+#NO_MLOCKALL = -DDISABLE_MLOCKALL
+
+##
+# Sometimes you have only dynamic libraries available. In that case COMMENT
+# the following line.
+##
+LINK_STATIC = -static
+
+##############################################################################
+# NO USER MODIFIABLE PARTS AFTER THIS POINT
+##############################################################################
+CFLAGS = -Wall $(CRYPTO_INCLUDE_PATH) $(CRYPTO_CFLAGS) $(NO_MLOCKALL)
+LDFLAGS = $(CRYPTO_LIBRARY_PATH) $(LINK_STATIC) $(CRYPTO_LIBS) -lm
+
+.PHONY : all install-strip install clean
+
+OBJS = diceware8k.o main.o pwgen.o secure_memory_unix.o \
+ $(CRYPTO_OBJS) skeylist.o
+
+all: secpwgen
+
+secpwgen: $(OBJS)
+ $(CC) -o $@ $(OBJS) $(LDFLAGS)
+
+install-strip: secpwgen
+ strip secpwgen
+ $(MAKE) install
+
+install: secpwgen
+ cp -i secpwgen $(PREFIX)/bin
+ cp -i secpwgen.1 $(PREFIX)/man/man1
+
+clean:
+ rm -f *.o secpwgen
+
+diceware8k.o: diceware8k.c
+main.o: main.c secure_memory.h secure_random.h pwgen.h exceptions.h \
+ cexcept.h
+pwgen.o: pwgen.c secure_random.h pwgen.h exceptions.h cexcept.h
+secure_memory_unix.o: secure_memory_unix.c secure_random.h \
+ secure_memory.h exceptions.h cexcept.h
+secure_random_cryptlib.o: secure_random_cryptlib.c exceptions.h cexcept.h
+secure_random_openssl.o: secure_random_openssl.c exceptions.h cexcept.h
+skeylist.o: skeylist.c
diff --git a/README b/README
new file mode 100644
index 0000000..d27b7f5
--- /dev/null
+++ b/README
@@ -0,0 +1,27 @@
+PREREQUISITES
+=============
+You need OpenSSL at least 0.9.7 OR cryptlib 3.1 or later.
+
+HOW
+===
+Copy Makefile.proto to Makefile and edit it according to instructions found
+there.
+
+USAGE
+=====
+Read the secpwgen man page.
+
+NOTE ON VERSIONING
+==================
+Unlike many open-source packages, this program's versioning follows the
+normal DECIMAL NUMBER comparison rules: the following example shows the
+ordering of versions: 0.9 < 1.0 < 1.1 < 1.2 < 1.21 < 1.22xx < 1.3 (some
+time in the future) because the same relations hold for ordinary decimals.
+
+TODO
+====
+Add an option to specify path to EGD socket. This will enable the program to
+provide secure passwords even on crippled systems (with no /dev/{u,}random)
+provided EGD (entropy gathering daemon) is running.
+
+Call OpenSSL Win32 specific function to init the entropy pool.
diff --git a/cexcept.h b/cexcept.h
new file mode 100644
index 0000000..dbea51e
--- /dev/null
+++ b/cexcept.h
@@ -0,0 +1,243 @@
+/*===
+cexcept.h 2.0.0 (2001-Jul-12-Thu)
+Adam M. Costello <amc@cs.berkeley.edu>
+
+An interface for exception-handling in ANSI C (C89 and subsequent ISO
+standards), developed jointly with Cosmin Truta <cosmin@cs.toronto.edu>.
+
+ Copyright (c) 2001 Adam M. Costello and Cosmin Truta. Everyone
+ is hereby granted permission to do whatever they like with this
+ file, provided that if they modify it they take reasonable steps to
+ avoid confusing or misleading people about the authors, version,
+ and terms of use of the derived file. The copyright holders make
+ no guarantees regarding this file, and are not responsible for any
+ damage resulting from its use.
+
+Only user-defined exceptions are supported, not "real" exceptions like
+division by zero or memory segmentation violations.
+
+If this interface is used by multiple .c files, they shouldn't include
+this header file directly. Instead, create a wrapper header file that
+includes this header file and then invokes the define_exception_type
+macro (see below), and let your .c files include that header file.
+
+The interface consists of one type, one well-known name, and six macros.
+
+
+define_exception_type(type_name);
+
+ This macro is used like an external declaration. It specifies
+ the type of object that gets copied from the exception thrower to
+ the exception catcher. The type_name can be any type that can be
+ assigned to, that is, a non-constant arithmetic type, struct, union,
+ or pointer. Examples:
+
+ define_exception_type(int);
+
+ enum exception { out_of_memory, bad_arguments, disk_full };
+ define_exception_type(enum exception);
+
+ struct exception { int code; const char *msg; };
+ define_exception_type(struct exception);
+
+ Because throwing an exception causes the object to be copied (not
+ just once, but twice), programmers may wish to consider size when
+ choosing the exception type.
+
+
+struct exception_context;
+
+ This type may be used after the define_exception_type() macro has
+ been invoked. A struct exception_context must be known to both
+ the thrower and the catcher. It is expected that there be one
+ context for each thread that uses exceptions. It would certainly
+ be dangerous for multiple threads to access the same context.
+ One thread can use multiple contexts, but that is likely to be
+ confusing and not typically useful. The application can allocate
+ this structure in any way it pleases--automatic, static, or dynamic.
+ The application programmer should pretend not to know the structure
+ members, which are subject to change.
+
+
+struct exception_context *the_exception_context;
+
+ The Try/Catch and Throw statements (described below) implicitly
+ refer to a context, using the name the_exception_context. It is
+ the application's responsibility to make sure that this name yields
+ the address of a mutable (non-constant) struct exception_context
+ wherever those statements are used. Subject to that constraint, the
+ application may declare a variable of this name anywhere it likes
+ (inside a function, in a parameter list, or externally), and may
+ use whatever storage class specifiers (static, extern, etc) or type
+ qualifiers (const, volatile, etc) it likes. Examples:
+
+ static struct exception_context
+ * const the_exception_context = &foo;
+
+ { struct exception_context *the_exception_context = bar; ... }
+
+ int blah(struct exception_context *the_exception_context, ...);
+
+ extern struct exception_context the_exception_context[1];
+
+ The last example illustrates a trick that avoids creating a pointer
+ object separate from the structure object.
+
+ The name could even be a macro, for example:
+
+ struct exception_context ec_array[numthreads];
+ #define the_exception_context (ec_array + thread_id)
+
+ Be aware that the_exception_context is used several times by the
+ Try/Catch/Throw macros, so it shouldn't be expensive or have side
+ effects. The expansion must be a drop-in replacement for an
+ identifier, so it's safest to put parentheses around it.
+
+
+void init_exception_context(struct exception_context *ec);
+
+ For context structures allocated statically (by an external
+ definition or using the "static" keyword), the implicit
+ initialization to all zeros is sufficient, but contexts allocated
+ by other means must be initialized using this macro before they
+ are used by a Try/Catch statement. It does no harm to initialize
+ a context more than once (by using this macro on a statically
+ allocated context, or using this macro twice on the same context),
+ but a context must not be re-initialized after it has been used by a
+ Try/Catch statement.
+
+
+Try statement
+Catch (expression) statement
+
+ The Try/Catch/Throw macros are capitalized in order to avoid
+ confusion with the C++ keywords, which have subtly different
+ semantics.
+
+ A Try/Catch statement has a syntax similar to an if/else statement,
+ except that the parenthesized expression goes after the second
+ keyword rather than the first. As with if/else, there are two
+ clauses, each of which may be a simple statement ending with a
+ semicolon or a brace-enclosed compound statement. But whereas
+ the else clause is optional, the Catch clause is required. The
+ expression must be a modifiable lvalue (something capable of being
+ assigned to) of the same type (disregarding type qualifiers) that
+ was passed to define_exception_type().
+
+ If a Throw that uses the same exception context as the Try/Catch is
+ executed within the Try clause (typically within a function called
+ by the Try clause), and the exception is not caught by a nested
+ Try/Catch statement, then a copy of the exception will be assigned
+ to the expression, and control will jump to the Catch clause. If no
+ such Throw is executed, then the assignment is not performed, and
+ the Catch clause is not executed.
+
+ The expression is not evaluated unless and until the exception is
+ caught, which is significant if it has side effects, for example:
+
+ Try foo();
+ Catch (p[++i].e) { ... }
+
+ IMPORTANT: Jumping into or out of a Try clause (for example via
+ return, break, continue, goto, longjmp) is forbidden--the compiler
+ will not complain, but bad things will happen at run-time. Jumping
+ into or out of a Catch clause is okay, and so is jumping around
+ inside a Try clause. In many cases where one is tempted to return
+ from a Try clause, it will suffice to use Throw, and then return
+ from the Catch clause. Another option is to set a flag variable and
+ use goto to jump to the end of the Try clause, then check the flag
+ after the Try/Catch statement.
+
+ IMPORTANT: The values of any non-volatile automatic variables
+ changed within the Try clause are undefined after an exception is
+ caught. Therefore, variables modified inside the Try block whose
+ values are needed later outside the Try block must either use static
+ storage or be declared with the "volatile" type qualifier.
+
+
+Throw expression;
+
+ A Throw statement is very much like a return statement, except that
+ the expression is required. Whereas return jumps back to the place
+ where the current function was called, Throw jumps back to the Catch
+ clause of the innermost enclosing Try clause. The expression must
+ be compatible with the type passed to define_exception_type(). The
+ exception must be caught, otherwise the program may crash.
+
+ Slight limitation: If the expression is a comma-expression it must
+ be enclosed in parentheses.
+
+
+Try statement
+Catch_anonymous statement
+
+ When the value of the exception is not needed, a Try/Catch statement
+ can use Catch_anonymous instead of Catch (expression).
+
+
+Everything below this point is for the benefit of the compiler. The
+application programmer should pretend not to know any of it, because it
+is subject to change.
+
+===*/
+
+
+#ifndef CEXCEPT_H
+#define CEXCEPT_H
+
+
+#include <setjmp.h>
+
+#define define_exception_type(etype) \
+struct exception_context { \
+ jmp_buf *penv; \
+ int caught; \
+ volatile struct { etype etmp; } v; \
+}
+
+/* etmp must be volatile because the application might use automatic */
+/* storage for the_exception_context, and etmp is modified between */
+/* the calls to setjmp() and longjmp(). A wrapper struct is used to */
+/* avoid warnings about a duplicate volatile qualifier in case etype */
+/* already includes it. */
+
+#define init_exception_context(ec) ((void)((ec)->penv = 0))
+
+#define Try \
+ { \
+ jmp_buf *exception__prev, exception__env; \
+ exception__prev = the_exception_context->penv; \
+ the_exception_context->penv = &exception__env; \
+ if (setjmp(exception__env) == 0) { \
+ if (&exception__prev)
+
+#define exception__catch(action) \
+ else { } \
+ the_exception_context->caught = 0; \
+ } \
+ else { \
+ the_exception_context->caught = 1; \
+ } \
+ the_exception_context->penv = exception__prev; \
+ } \
+ if (!the_exception_context->caught || action) { } \
+ else
+
+#define Catch(e) exception__catch(((e) = the_exception_context->v.etmp, 0))
+#define Catch_anonymous exception__catch(0)
+
+/* Try ends with if(), and Catch begins and ends with else. This */
+/* ensures that the Try/Catch syntax is really the same as the */
+/* if/else syntax. */
+/* */
+/* We use &exception__prev instead of 1 to appease compilers that */
+/* warn about constant expressions inside if(). Most compilers */
+/* should still recognize that &exception__prev is never zero and */
+/* avoid generating test code. */
+
+#define Throw \
+ for (;; longjmp(*the_exception_context->penv, 1)) \
+ the_exception_context->v.etmp =
+
+
+#endif /* CEXCEPT_H */
diff --git a/diagnostics.h b/diagnostics.h
new file mode 100644
index 0000000..8b5d820
--- /dev/null
+++ b/diagnostics.h
@@ -0,0 +1,41 @@
+/*
+ diagnostics.h - standard error codes and messages
+ (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef DIAGNOSTICS_H__
+#define DIAGNOSTICS_H__
+
+#define I01 "destroying secure memory"
+#define W01 "using insecure memory"
+#define E01 "N must be an integer > 0"
+#define F01 "out of memory"
+#define F02 "system call failed"
+#define F03 "unhandled exception"
+#define F04 "can't drop privileges"
+
+#define IWDIAG(x, ...) fprintf(stderr, "%s: %s:\n", #x, x, __VA_ARGS__)
+#define EFDIAG(x, ...) do { \
+ fprintf(stderr, "%s: %s\n", #x, __VA_ARGS__);\
+ exit(EXIT_FAILURE);\
+}
+
+#endif /* DIAGNOSTICS_H__ */
diff --git a/diceware8k.c b/diceware8k.c
new file mode 100644
index 0000000..6cefa03
--- /dev/null
+++ b/diceware8k.c
@@ -0,0 +1,8201 @@
+/* Diceware 8k Word List in C
+ Arnold G. Reinhold
+ 2000-10-23 */
+
+static const char * Dicewds8k[] =
+{"a",
+"a&p",
+"a's",
+"a2",
+"a3",
+"a4",
+"a5",
+"a6",
+"a7",
+"a8",
+"a9",
+"aa",
+"aaa",
+"aaaa",
+"aaron",
+"ab",
+"aba",
+"ababa",
+"aback",
+"abase",
+"abash",
+"abate",
+"abbas",
+"abbe",
+"abbey",
+"abbot",
+"abbott",
+"abc",
+"abe",
+"abed",
+"abel",
+"abet",
+"abide",
+"abject",
+"ablaze",
+"able",
+"abner",
+"abo",
+"abode",
+"abort",
+"about",
+"above",
+"abrade",
+"abram",
+"absorb",
+"abuse",
+"abut",
+"abyss",
+"ac",
+"acadia",
+"accra",
+"accrue",
+"ace",
+"acetic",
+"ache",
+"acid",
+"acidic",
+"acm",
+"acme",
+"acorn",
+"acre",
+"acrid",
+"act",
+"acton",
+"actor",
+"acts",
+"acuity",
+"acute",
+"ad",
+"ada",
+"adage",
+"adagio",
+"adair",
+"adam",
+"adams",
+"adapt",
+"add",
+"added",
+"addict",
+"addis",
+"addle",
+"adele",
+"aden",
+"adept",
+"adieu",
+"adjust",
+"adler",
+"admit",
+"admix",
+"ado",
+"adobe",
+"adonis",
+"adopt",
+"adore",
+"adorn",
+"adult",
+"advent",
+"advert",
+"advise",
+"ae",
+"aegis",
+"aeneid",
+"af",
+"afar",
+"affair",
+"affine",
+"affix",
+"afire",
+"afoot",
+"afraid",
+"africa",
+"afro",
+"aft",
+"ag",
+"again",
+"agate",
+"agave",
+"age",
+"agee",
+"agenda",
+"agent",
+"agile",
+"aging",
+"agnes",
+"agnew",
+"ago",
+"agone",
+"agony",
+"agree",
+"ague",
+"agway",
+"ah",
+"ahead",
+"ahem",
+"ahoy",
+"ai",
+"aid",
+"aida",
+"aide",
+"aides",
+"aiken",
+"ail",
+"aile",
+"aim",
+"ain't",
+"ainu",
+"air",
+"aires",
+"airman",
+"airway",
+"airy",
+"aisle",
+"aj",
+"ajar",
+"ajax",
+"ak",
+"akers",
+"akin",
+"akron",
+"al",
+"ala",
+"alai",
+"alamo",
+"alan",
+"alarm",
+"alaska",
+"alb",
+"alba",
+"album",
+"alcoa",
+"alden",
+"alder",
+"ale",
+"alec",
+"aleck",
+"aleph",
+"alert",
+"alex",
+"alexei",
+"alga",
+"algae",
+"algal",
+"alger",
+"algol",
+"ali",
+"alia",
+"alias",
+"alibi",
+"alice",
+"alien",
+"alight",
+"align",
+"alike",
+"alive",
+"all",
+"allah",
+"allan",
+"allay",
+"allen",
+"alley",
+"allied",
+"allis",
+"allot",
+"allow",
+"alloy",
+"allure",
+"ally",
+"allyl",
+"allyn",
+"alma",
+"almost",
+"aloe",
+"aloft",
+"aloha",
+"alone",
+"along",
+"aloof",
+"aloud",
+"alp",
+"alpha",
+"alps",
+"also",
+"alsop",
+"altair",
+"altar",
+"alter",
+"alto",
+"alton",
+"alum",
+"alumni",
+"alva",
+"alvin",
+"alway",
+"am",
+"ama",
+"amass",
+"amaze",
+"amber",
+"amble",
+"ambush",
+"amen",
+"amend",
+"ames",
+"ami",
+"amid",
+"amide",
+"amigo",
+"amino",
+"amiss",
+"amity",
+"amman",
+"ammo",
+"amoco",
+"amok",
+"among",
+"amort",
+"amos",
+"amp",
+"ampere",
+"ampex",
+"ample",
+"amply",
+"amra",
+"amulet",
+"amuse",
+"amy",
+"an",
+"ana",
+"and",
+"andes",
+"andre",
+"andrew",
+"andy",
+"anent",
+"anew",
+"angel",
+"angelo",
+"anger",
+"angie",
+"angle",
+"anglo",
+"angola",
+"angry",
+"angst",
+"angus",
+"ani",
+"anion",
+"anise",
+"anita",
+"ankle",
+"ann",
+"anna",
+"annal",
+"anne",
+"annex",
+"annie",
+"annoy",
+"annul",
+"annuli",
+"annum",
+"anode",
+"ansi",
+"answer",
+"ant",
+"ante",
+"anti",
+"antic",
+"anton",
+"anus",
+"anvil",
+"any",
+"anyhow",
+"anyway",
+"ao",
+"aok",
+"aorta",
+"ap",
+"apart",
+"apathy",
+"ape",
+"apex",
+"aphid",
+"aplomb",
+"appeal",
+"append",
+"apple",
+"apply",
+"april",
+"apron",
+"apse",
+"apt",
+"aq",
+"aqua",
+"ar",
+"arab",
+"araby",
+"arc",
+"arcana",
+"arch",
+"archer",
+"arden",
+"ardent",
+"are",
+"area",
+"arena",
+"ares",
+"argive",
+"argo",
+"argon",
+"argot",
+"argue",
+"argus",
+"arhat",
+"arid",
+"aries",
+"arise",
+"ark",
+"arlen",
+"arlene",
+"arm",
+"armco",
+"army",
+"arnold",
+"aroma",
+"arose",
+"arpa",
+"array",
+"arrear",
+"arrow",
+"arson",
+"art",
+"artery",
+"arthur",
+"artie",
+"arty",
+"aruba",
+"arum",
+"aryl",
+"as",
+"ascend",
+"ash",
+"ashen",
+"asher",
+"ashley",
+"ashy",
+"asia",
+"aside",
+"ask",
+"askew",
+"asleep",
+"aspen",
+"aspire",
+"ass",
+"assai",
+"assam",
+"assay",
+"asset",
+"assort",
+"assure",
+"aster",
+"astm",
+"astor",
+"astral",
+"at",
+"at&t",
+"ate",
+"athens",
+"atlas",
+"atom",
+"atomic",
+"atone",
+"atop",
+"attic",
+"attire",
+"au",
+"aubrey",
+"audio",
+"audit",
+"aug",
+"auger",
+"augur",
+"august",
+"auk",
+"aunt",
+"aura",
+"aural",
+"auric",
+"austin",
+"auto",
+"autumn",
+"av",
+"avail",
+"ave",
+"aver",
+"avert",
+"avery",
+"aviate",
+"avid",
+"avis",
+"aviv",
+"avoid",
+"avon",
+"avow",
+"aw",
+"await",
+"awake",
+"award",
+"aware",
+"awash",
+"away",
+"awe",
+"awful",
+"awl",
+"awn",
+"awoke",
+"awry",
+"ax",
+"axe",
+"axes",
+"axial",
+"axiom",
+"axis",
+"axle",
+"axon",
+"ay",
+"aye",
+"ayers",
+"az",
+"aztec",
+"azure",
+"b",
+"b's",
+"b2",
+"b3",
+"b4",
+"b5",
+"b6",
+"b7",
+"b8",
+"b9",
+"ba",
+"babe",
+"babel",
+"baby",
+"bach",
+"back",
+"backup",
+"bacon",
+"bad",
+"bade",
+"baden",
+"badge",
+"baffle",
+"bag",
+"baggy",
+"bah",
+"bahama",
+"bail",
+"baird",
+"bait",
+"bake",
+"baku",
+"bald",
+"baldy",
+"bale",
+"bali",
+"balk",
+"balkan",
+"balky",
+"ball",
+"balled",
+"ballot",
+"balm",
+"balmy",
+"balsa",
+"bam",
+"bambi",
+"ban",
+"banal",
+"band",
+"bandit",
+"bandy",
+"bane",
+"bang",
+"banish",
+"banjo",
+"bank",
+"banks",
+"bantu",
+"bar",
+"barb",
+"bard",
+"bare",
+"barfly",
+"barge",
+"bark",
+"barley",
+"barn",
+"barnes",
+"baron",
+"barony",
+"barr",
+"barre",
+"barry",
+"barter",
+"barth",
+"barton",
+"basal",
+"base",
+"basel",
+"bash",
+"basic",
+"basil",
+"basin",
+"basis",
+"bask",
+"bass",
+"bassi",
+"basso",
+"baste",
+"bat",
+"batch",
+"bate",
+"bater",
+"bates",
+"bath",
+"bathe",
+"batik",
+"baton",
+"bator",
+"batt",
+"bauble",
+"baud",
+"bauer",
+"bawd",
+"bawdy",
+"bawl",
+"baxter",
+"bay",
+"bayda",
+"bayed",
+"bayou",
+"bazaar",
+"bb",
+"bbb",
+"bbbb",
+"bc",
+"bcd",
+"bd",
+"be",
+"beach",
+"bead",
+"beady",
+"beak",
+"beam",
+"bean",
+"bear",
+"beard",
+"beast",
+"beat",
+"beau",
+"beauty",
+"beaux",
+"bebop",
+"becalm",
+"beck",
+"becker",
+"becky",
+"bed",
+"bedim",
+"bee",
+"beebe",
+"beech",
+"beef",
+"beefy",
+"been",
+"beep",
+"beer",
+"beet",
+"befall",
+"befit",
+"befog",
+"beg",
+"began",
+"beget",
+"beggar",
+"begin",
+"begun",
+"behind",
+"beige",
+"being",
+"beirut",
+"bel",
+"bela",
+"belch",
+"belfry",
+"belie",
+"bell",
+"bella",
+"belle",
+"belly",
+"below",
+"belt",
+"bema",
+"beman",
+"bemoan",
+"ben",
+"bench",
+"bend",
+"bender",
+"benny",
+"bent",
+"benz",
+"berea",
+"bereft",
+"beret",
+"berg",
+"berlin",
+"bern",
+"berne",
+"bernet",
+"berra",
+"berry",
+"bert",
+"berth",
+"beryl",
+"beset",
+"bess",
+"bessel",
+"best",
+"bestir",
+"bet",
+"beta",
+"betel",
+"beth",
+"bethel",
+"betsy",
+"bette",
+"betty",
+"bevel",
+"bevy",
+"beware",
+"bey",
+"bezel",
+"bf",
+"bg",
+"bh",
+"bhoy",
+"bi",
+"bias",
+"bib",
+"bibb",
+"bible",
+"bicep",
+"biceps",
+"bid",
+"biddy",
+"bide",
+"bien",
+"big",
+"biggs",
+"bigot",
+"bile",
+"bilge",
+"bilk",
+"bill",
+"billow",
+"billy",
+"bin",
+"binary",
+"bind",
+"bing",
+"binge",
+"bingle",
+"bini",
+"biota",
+"birch",
+"bird",
+"birdie",
+"birth",
+"bison",
+"bisque",
+"bit",
+"bitch",
+"bite",
+"bitt",
+"bitten",
+"biz",
+"bizet",
+"bj",
+"bk",
+"bl",
+"blab",
+"black",
+"blade",
+"blair",
+"blake",
+"blame",
+"blanc",
+"bland",
+"blank",
+"blare",
+"blast",
+"blat",
+"blatz",
+"blaze",
+"bleak",
+"bleat",
+"bled",
+"bleed",
+"blend",
+"bless",
+"blest",
+"blew",
+"blimp",
+"blind",
+"blink",
+"blinn",
+"blip",
+"bliss",
+"blithe",
+"blitz",
+"bloat",
+"blob",
+"bloc",
+"bloch",
+"block",
+"bloke",
+"blond",
+"blonde",
+"blood",
+"bloom",
+"bloop",
+"blot",
+"blotch",
+"blow",
+"blown",
+"blue",
+"bluet",
+"bluff",
+"blum",
+"blunt",
+"blur",
+"blurt",
+"blush",
+"blvd",
+"blythe",
+"bm",
+"bmw",
+"bn",
+"bo",
+"boa",
+"boar",
+"board",
+"boast",
+"boat",
+"bob",
+"bobbin",
+"bobby",
+"bobcat",
+"boca",
+"bock",
+"bode",
+"body",
+"bog",
+"bogey",
+"boggy",
+"bogus",
+"bogy",
+"bohr",
+"boil",
+"bois",
+"boise",
+"bold",
+"bole",
+"bolo",
+"bolt",
+"bomb",
+"bombay",
+"bon",
+"bona",
+"bond",
+"bone",
+"bong",
+"bongo",
+"bonn",
+"bonus",
+"bony",
+"bonze",
+"boo",
+"booby",
+"boogie",
+"book",
+"booky",
+"boom",
+"boon",
+"boone",
+"boor",
+"boost",
+"boot",
+"booth",
+"booty",
+"booze",
+"bop",
+"borax",
+"border",
+"bore",
+"borg",
+"boric",
+"boris",
+"born",
+"borne",
+"borneo",
+"boron",
+"bosch",
+"bose",
+"bosom",
+"boson",
+"boss",
+"boston",
+"botch",
+"both",
+"bottle",
+"bough",
+"bouncy",
+"bound",
+"bourn",
+"bout",
+"bovine",
+"bow",
+"bowel",
+"bowen",
+"bowie",
+"bowl",
+"box",
+"boxy",
+"boy",
+"boyar",
+"boyce",
+"boyd",
+"boyle",
+"bp",
+"bq",
+"br",
+"brace",
+"bract",
+"brad",
+"brady",
+"brae",
+"brag",
+"bragg",
+"braid",
+"brain",
+"brainy",
+"brake",
+"bran",
+"brand",
+"brandt",
+"brant",
+"brash",
+"brass",
+"brassy",
+"braun",
+"brave",
+"bravo",
+"brawl",
+"bray",
+"bread",
+"break",
+"bream",
+"breath",
+"bred",
+"breed",
+"breeze",
+"bremen",
+"brent",
+"brest",
+"brett",
+"breve",
+"brew",
+"brian",
+"briar",
+"bribe",
+"brice",
+"brick",
+"bride",
+"brief",
+"brig",
+"briggs",
+"brim",
+"brine",
+"bring",
+"brink",
+"briny",
+"brisk",
+"broad",
+"brock",
+"broil",
+"broke",
+"broken",
+"bronx",
+"brood",
+"brook",
+"brooke",
+"broom",
+"broth",
+"brow",
+"brown",
+"browse",
+"bruce",
+"bruit",
+"brunch",
+"bruno",
+"brunt",
+"brush",
+"brute",
+"bryan",
+"bryant",
+"bryce",
+"bryn",
+"bs",
+"bstj",
+"bt",
+"btl",
+"bu",
+"bub",
+"buck",
+"bud",
+"budd",
+"buddy",
+"budge",
+"buena",
+"buenos",
+"buff",
+"bug",
+"buggy",
+"bugle",
+"buick",
+"build",
+"built",
+"bulb",
+"bulge",
+"bulk",
+"bulky",
+"bull",
+"bully",
+"bum",
+"bump",
+"bun",
+"bunch",
+"bundy",
+"bunk",
+"bunny",
+"bunt",
+"bunyan",
+"buoy",
+"burch",
+"bureau",
+"buret",
+"burg",
+"buried",
+"burke",
+"burl",
+"burly",
+"burma",
+"burn",
+"burnt",
+"burp",
+"burr",
+"burro",
+"burst",
+"burt",
+"burton",
+"burtt",
+"bury",
+"bus",
+"busch",
+"bush",
+"bushel",
+"bushy",
+"buss",
+"bust",
+"busy",
+"but",
+"butane",
+"butch",
+"buteo",
+"butt",
+"butte",
+"butyl",
+"buxom",
+"buy",
+"buyer",
+"buzz",
+"buzzy",
+"bv",
+"bw",
+"bx",
+"by",
+"bye",
+"byers",
+"bylaw",
+"byline",
+"byrd",
+"byrne",
+"byron",
+"byte",
+"byway",
+"byword",
+"bz",
+"c",
+"c's",
+"c2",
+"c3",
+"c4",
+"c5",
+"c6",
+"c7",
+"c8",
+"c9",
+"ca",
+"cab",
+"cabal",
+"cabin",
+"cable",
+"cabot",
+"cacao",
+"cache",
+"cacm",
+"cacti",
+"caddy",
+"cadent",
+"cadet",
+"cadre",
+"cady",
+"cafe",
+"cage",
+"cagey",
+"cahill",
+"caiman",
+"cain",
+"caine",
+"cairn",
+"cairo",
+"cake",
+"cal",
+"calder",
+"caleb",
+"calf",
+"call",
+"calla",
+"callus",
+"calm",
+"calve",
+"cam",
+"camber",
+"came",
+"camel",
+"cameo",
+"camp",
+"can",
+"can't",
+"canal",
+"canary",
+"cancer",
+"candle",
+"candy",
+"cane",
+"canis",
+"canna",
+"cannot",
+"canny",
+"canoe",
+"canon",
+"canopy",
+"cant",
+"canto",
+"canton",
+"cap",
+"cape",
+"caper",
+"capo",
+"car",
+"carbon",
+"card",
+"care",
+"caress",
+"caret",
+"carey",
+"cargo",
+"carib",
+"carl",
+"carla",
+"carlo",
+"carne",
+"carob",
+"carol",
+"carp",
+"carpet",
+"carr",
+"carrie",
+"carry",
+"carson",
+"cart",
+"carte",
+"caruso",
+"carve",
+"case",
+"casey",
+"cash",
+"cashew",
+"cask",
+"casket",
+"cast",
+"caste",
+"cat",
+"catch",
+"cater",
+"cathy",
+"catkin",
+"catsup",
+"cauchy",
+"caulk",
+"cause",
+"cave",
+"cavern",
+"cavil",
+"cavort",
+"caw",
+"cayuga",
+"cb",
+"cbs",
+"cc",
+"ccc",
+"cccc",
+"cd",
+"cdc",
+"ce",
+"cease",
+"cecil",
+"cedar",
+"cede",
+"ceil",
+"celia",
+"cell",
+"census",
+"cent",
+"ceres",
+"cern",
+"cetera",
+"cetus",
+"cf",
+"cg",
+"ch",
+"chad",
+"chafe",
+"chaff",
+"chai",
+"chain",
+"chair",
+"chalk",
+"champ",
+"chance",
+"chang",
+"chant",
+"chao",
+"chaos",
+"chap",
+"chapel",
+"char",
+"chard",
+"charm",
+"chart",
+"chase",
+"chasm",
+"chaste",
+"chat",
+"chaw",
+"cheap",
+"cheat",
+"check",
+"cheek",
+"cheeky",
+"cheer",
+"chef",
+"chen",
+"chert",
+"cherub",
+"chess",
+"chest",
+"chevy",
+"chew",
+"chi",
+"chic",
+"chick",
+"chide",
+"chief",
+"child",
+"chile",
+"chili",
+"chill",
+"chilly",
+"chime",
+"chin",
+"china",
+"chine",
+"chink",
+"chip",
+"chirp",
+"chisel",
+"chit",
+"chive",
+"chock",
+"choir",
+"choke",
+"chomp",
+"chop",
+"chopin",
+"choral",
+"chord",
+"chore",
+"chose",
+"chosen",
+"chou",
+"chow",
+"chris",
+"chub",
+"chuck",
+"chuff",
+"chug",
+"chum",
+"chump",
+"chunk",
+"churn",
+"chute",
+"ci",
+"cia",
+"cicada",
+"cider",
+"cigar",
+"cilia",
+"cinch",
+"cindy",
+"cipher",
+"circa",
+"circe",
+"cite",
+"citrus",
+"city",
+"civet",
+"civic",
+"civil",
+"cj",
+"ck",
+"cl",
+"clad",
+"claim",
+"clam",
+"clammy",
+"clamp",
+"clan",
+"clang",
+"clank",
+"clap",
+"clara",
+"clare",
+"clark",
+"clarke",
+"clash",
+"clasp",
+"class",
+"claus",
+"clause",
+"claw",
+"clay",
+"clean",
+"clear",
+"cleat",
+"cleft",
+"clerk",
+"cliche",
+"click",
+"cliff",
+"climb",
+"clime",
+"cling",
+"clink",
+"clint",
+"clio",
+"clip",
+"clive",
+"cloak",
+"clock",
+"clod",
+"clog",
+"clomp",
+"clone",
+"close",
+"closet",
+"clot",
+"cloth",
+"cloud",
+"clout",
+"clove",
+"clown",
+"cloy",
+"club",
+"cluck",
+"clue",
+"cluj",
+"clump",
+"clumsy",
+"clung",
+"clyde",
+"cm",
+"cn",
+"co",
+"coach",
+"coal",
+"coast",
+"coat",
+"coax",
+"cobb",
+"cobble",
+"cobol",
+"cobra",
+"coca",
+"cock",
+"cockle",
+"cocky",
+"coco",
+"cocoa",
+"cod",
+"coda",
+"coddle",
+"code",
+"codon",
+"cody",
+"coed",
+"cog",
+"cogent",
+"cohen",
+"cohn",
+"coil",
+"coin",
+"coke",
+"col",
+"cola",
+"colby",
+"cold",
+"cole",
+"colon",
+"colony",
+"colt",
+"colza",
+"coma",
+"comb",
+"combat",
+"come",
+"comet",
+"cometh",
+"comic",
+"comma",
+"con",
+"conch",
+"cone",
+"coney",
+"congo",
+"conic",
+"conn",
+"conner",
+"conway",
+"cony",
+"coo",
+"cook",
+"cooke",
+"cooky",
+"cool",
+"cooley",
+"coon",
+"coop",
+"coors",
+"coot",
+"cop",
+"cope",
+"copra",
+"copy",
+"coral",
+"corbel",
+"cord",
+"core",
+"corey",
+"cork",
+"corn",
+"corny",
+"corp",
+"corps",
+"corvus",
+"cos",
+"cosec",
+"coset",
+"cosh",
+"cost",
+"costa",
+"cosy",
+"cot",
+"cotta",
+"cotty",
+"couch",
+"cough",
+"could",
+"count",
+"coup",
+"coupe",
+"court",
+"cousin",
+"cove",
+"coven",
+"cover",
+"covet",
+"cow",
+"cowan",
+"cowl",
+"cowman",
+"cowry",
+"cox",
+"coy",
+"coyote",
+"coypu",
+"cozen",
+"cozy",
+"cp",
+"cpa",
+"cq",
+"cr",
+"crab",
+"crack",
+"craft",
+"crag",
+"craig",
+"cram",
+"cramp",
+"crane",
+"crank",
+"crap",
+"crash",
+"crass",
+"crate",
+"crater",
+"crave",
+"craw",
+"crawl",
+"craze",
+"crazy",
+"creak",
+"cream",
+"credit",
+"credo",
+"creed",
+"creek",
+"creep",
+"creole",
+"creon",
+"crepe",
+"crept",
+"cress",
+"crest",
+"crete",
+"crew",
+"crib",
+"cried",
+"crime",
+"crimp",
+"crisp",
+"criss",
+"croak",
+"crock",
+"crocus",
+"croft",
+"croix",
+"crone",
+"crony",
+"crook",
+"croon",
+"crop",
+"cross",
+"crow",
+"crowd",
+"crown",
+"crt",
+"crud",
+"crude",
+"cruel",
+"crumb",
+"crump",
+"crush",
+"crust",
+"crux",
+"cruz",
+"cry",
+"crypt",
+"cs",
+"ct",
+"cu",
+"cub",
+"cuba",
+"cube",
+"cubic",
+"cud",
+"cuddle",
+"cue",
+"cuff",
+"cull",
+"culpa",
+"cult",
+"cumin",
+"cuny",
+"cup",
+"cupful",
+"cupid",
+"cur",
+"curb",
+"curd",
+"cure",
+"curfew",
+"curia",
+"curie",
+"curio",
+"curl",
+"curry",
+"curse",
+"curt",
+"curve",
+"cusp",
+"cut",
+"cute",
+"cutlet",
+"cv",
+"cw",
+"cx",
+"cy",
+"cycad",
+"cycle",
+"cynic",
+"cyril",
+"cyrus",
+"cyst",
+"cz",
+"czar",
+"czech",
+"d",
+"d'art",
+"d's",
+"d2",
+"d3",
+"d4",
+"d5",
+"d6",
+"d7",
+"d8",
+"d9",
+"da",
+"dab",
+"dacca",
+"dactyl",
+"dad",
+"dada",
+"daddy",
+"dade",
+"daffy",
+"dahl",
+"dahlia",
+"dairy",
+"dais",
+"daisy",
+"dakar",
+"dale",
+"daley",
+"dally",
+"daly",
+"dam",
+"dame",
+"damn",
+"damon",
+"damp",
+"damsel",
+"dan",
+"dana",
+"dance",
+"dandy",
+"dane",
+"dang",
+"dank",
+"danny",
+"dante",
+"dar",
+"dare",
+"dark",
+"darken",
+"darn",
+"darry",
+"dart",
+"dash",
+"data",
+"date",
+"dater",
+"datum",
+"daub",
+"daunt",
+"dave",
+"david",
+"davis",
+"davit",
+"davy",
+"dawn",
+"dawson",
+"day",
+"daze",
+"db",
+"dc",
+"dd",
+"ddd",
+"dddd",
+"de",
+"deacon",
+"dead",
+"deaf",
+"deal",
+"dealt",
+"dean",
+"deane",
+"dear",
+"death",
+"debar",
+"debby",
+"debit",
+"debra",
+"debris",
+"debt",
+"debug",
+"debut",
+"dec",
+"decal",
+"decay",
+"decca",
+"deck",
+"decker",
+"decor",
+"decree",
+"decry",
+"dee",
+"deed",
+"deem",
+"deep",
+"deer",
+"deere",
+"def",
+"defer",
+"deform",
+"deft",
+"defy",
+"degas",
+"degum",
+"deify",
+"deign",
+"deity",
+"deja",
+"del",
+"delay",
+"delft",
+"delhi",
+"delia",
+"dell",
+"della",
+"delta",
+"delve",
+"demark",
+"demit",
+"demon",
+"demur",
+"den",
+"deneb",
+"denial",
+"denny",
+"dense",
+"dent",
+"denton",
+"deny",
+"depot",
+"depth",
+"depute",
+"derby",
+"derek",
+"des",
+"desist",
+"desk",
+"detach",
+"deter",
+"deuce",
+"deus",
+"devil",
+"devoid",
+"devon",
+"dew",
+"dewar",
+"dewey",
+"dewy",
+"dey",
+"df",
+"dg",
+"dh",
+"dhabi",
+"di",
+"dial",
+"diana",
+"diane",
+"diary",
+"dibble",
+"dice",
+"dick",
+"dicta",
+"did",
+"dido",
+"die",
+"died",
+"diego",
+"diem",
+"diesel",
+"diet",
+"diety",
+"dietz",
+"dig",
+"digit",
+"dilate",
+"dill",
+"dim",
+"dime",
+"din",
+"dinah",
+"dine",
+"ding",
+"dingo",
+"dingy",
+"dint",
+"diode",
+"dip",
+"dirac",
+"dire",
+"dirge",
+"dirt",
+"dirty",
+"dis",
+"disc",
+"dish",
+"disk",
+"disney",
+"ditch",
+"ditto",
+"ditty",
+"diva",
+"divan",
+"dive",
+"dixie",
+"dixon",
+"dizzy",
+"dj",
+"dk",
+"dl",
+"dm",
+"dn",
+"dna",
+"do",
+"dobbs",
+"dobson",
+"dock",
+"docket",
+"dod",
+"dodd",
+"dodge",
+"dodo",
+"doe",
+"doff",
+"dog",
+"doge",
+"dogma",
+"dolan",
+"dolce",
+"dole",
+"doll",
+"dolly",
+"dolt",
+"dome",
+"don",
+"don't",
+"done",
+"doneck",
+"donna",
+"donor",
+"doom",
+"door",
+"dope",
+"dora",
+"doria",
+"doric",
+"doris",
+"dose",
+"dot",
+"dote",
+"double",
+"doubt",
+"douce",
+"doug",
+"dough",
+"dour",
+"douse",
+"dove",
+"dow",
+"dowel",
+"down",
+"downs",
+"dowry",
+"doyle",
+"doze",
+"dozen",
+"dp",
+"dq",
+"dr",
+"drab",
+"draco",
+"draft",
+"drag",
+"drain",
+"drake",
+"dram",
+"drama",
+"drank",
+"drape",
+"draw",
+"drawl",
+"drawn",
+"dread",
+"dream",
+"dreamy",
+"dreg",
+"dress",
+"dressy",
+"drew",
+"drib",
+"dried",
+"drier",
+"drift",
+"drill",
+"drink",
+"drip",
+"drive",
+"droll",
+"drone",
+"drool",
+"droop",
+"drop",
+"dross",
+"drove",
+"drown",
+"drub",
+"drug",
+"druid",
+"drum",
+"drunk",
+"drury",
+"dry",
+"dryad",
+"ds",
+"dt",
+"du",
+"dual",
+"duane",
+"dub",
+"dubhe",
+"dublin",
+"ducat",
+"duck",
+"duct",
+"dud",
+"due",
+"duel",
+"duet",
+"duff",
+"duffy",
+"dug",
+"dugan",
+"duke",
+"dull",
+"dully",
+"dulse",
+"duly",
+"duma",
+"dumb",
+"dummy",
+"dump",
+"dumpy",
+"dun",
+"dunce",
+"dune",
+"dung",
+"dunham",
+"dunk",
+"dunlop",
+"dunn",
+"dupe",
+"durer",
+"dusk",
+"dusky",
+"dust",
+"dusty",
+"dutch",
+"duty",
+"dv",
+"dw",
+"dwarf",
+"dwell",
+"dwelt",
+"dwight",
+"dwyer",
+"dx",
+"dy",
+"dyad",
+"dye",
+"dyer",
+"dying",
+"dyke",
+"dylan",
+"dyne",
+"dz",
+"e",
+"e'er",
+"e's",
+"e2",
+"e3",
+"e4",
+"e5",
+"e6",
+"e7",
+"e8",
+"e9",
+"ea",
+"each",
+"eagan",
+"eager",
+"eagle",
+"ear",
+"earl",
+"earn",
+"earth",
+"ease",
+"easel",
+"east",
+"easy",
+"eat",
+"eaten",
+"eater",
+"eaton",
+"eave",
+"eb",
+"ebb",
+"eben",
+"ebony",
+"ec",
+"echo",
+"eclat",
+"ecole",
+"ed",
+"eddie",
+"eddy",
+"eden",
+"edgar",
+"edge",
+"edgy",
+"edict",
+"edify",
+"edit",
+"edith",
+"editor",
+"edna",
+"edt",
+"edwin",
+"ee",
+"eee",
+"eeee",
+"eel",
+"eeoc",
+"eerie",
+"ef",
+"efface",
+"effie",
+"efg",
+"eft",
+"eg",
+"egan",
+"egg",
+"ego",
+"egress",
+"egret",
+"egypt",
+"eh",
+"ei",
+"eider",
+"eight",
+"eire",
+"ej",
+"eject",
+"ek",
+"eke",
+"el",
+"elan",
+"elate",
+"elba",
+"elbow",
+"elder",
+"eldon",
+"elect",
+"elegy",
+"elena",
+"eleven",
+"elfin",
+"elgin",
+"eli",
+"elide",
+"eliot",
+"elite",
+"elk",
+"ell",
+"ella",
+"ellen",
+"ellis",
+"elm",
+"elmer",
+"elope",
+"else",
+"elsie",
+"elton",
+"elude",
+"elute",
+"elves",
+"ely",
+"em",
+"embalm",
+"embark",
+"embed",
+"ember",
+"emcee",
+"emery",
+"emil",
+"emile",
+"emily",
+"emit",
+"emma",
+"emory",
+"empty",
+"en",
+"enact",
+"enamel",
+"end",
+"endow",
+"enemy",
+"eng",
+"engel",
+"engle",
+"engulf",
+"enid",
+"enjoy",
+"enmity",
+"enoch",
+"enol",
+"enos",
+"enrico",
+"ensue",
+"enter",
+"entrap",
+"entry",
+"envoy",
+"envy",
+"eo",
+"ep",
+"epa",
+"epic",
+"epoch",
+"epoxy",
+"epsom",
+"eq",
+"equal",
+"equip",
+"er",
+"era",
+"erase",
+"erato",
+"erda",
+"ere",
+"erect",
+"erg",
+"eric",
+"erich",
+"erie",
+"erik",
+"ernest",
+"ernie",
+"ernst",
+"erode",
+"eros",
+"err",
+"errand",
+"errol",
+"error",
+"erupt",
+"ervin",
+"erwin",
+"es",
+"essay",
+"essen",
+"essex",
+"est",
+"ester",
+"estes",
+"estop",
+"et",
+"eta",
+"etc",
+"etch",
+"ethan",
+"ethel",
+"ether",
+"ethic",
+"ethos",
+"ethyl",
+"etude",
+"eu",
+"eucre",
+"euler",
+"eureka",
+"ev",
+"eva",
+"evade",
+"evans",
+"eve",
+"even",
+"event",
+"every",
+"evict",
+"evil",
+"evoke",
+"evolve",
+"ew",
+"ewe",
+"ewing",
+"ex",
+"exact",
+"exalt",
+"exam",
+"excel",
+"excess",
+"exert",
+"exile",
+"exist",
+"exit",
+"exodus",
+"expel",
+"extant",
+"extent",
+"extol",
+"extra",
+"exude",
+"exult",
+"exxon",
+"ey",
+"eye",
+"eyed",
+"ez",
+"ezra",
+"f",
+"f's",
+"f2",
+"f3",
+"f4",
+"f5",
+"f6",
+"f7",
+"f8",
+"f9",
+"fa",
+"faa",
+"faber",
+"fable",
+"face",
+"facet",
+"facile",
+"fact",
+"facto",
+"fad",
+"fade",
+"faery",
+"fag",
+"fahey",
+"fail",
+"fain",
+"faint",
+"fair",
+"fairy",
+"faith",
+"fake",
+"fall",
+"FALSE",
+"fame",
+"fan",
+"fancy",
+"fang",
+"fanny",
+"fanout",
+"far",
+"farad",
+"farce",
+"fare",
+"fargo",
+"farley",
+"farm",
+"faro",
+"fast",
+"fat",
+"fatal",
+"fate",
+"fatty",
+"fault",
+"faun",
+"fauna",
+"faust",
+"fawn",
+"fay",
+"faze",
+"fb",
+"fbi",
+"fc",
+"fcc",
+"fd",
+"fda",
+"fe",
+"fear",
+"feast",
+"feat",
+"feb",
+"fed",
+"fee",
+"feed",
+"feel",
+"feet",
+"feign",
+"feint",
+"felice",
+"felix",
+"fell",
+"felon",
+"felt",
+"femur",
+"fence",
+"fend",
+"fermi",
+"fern",
+"ferric",
+"ferry",
+"fest",
+"fetal",
+"fetch",
+"fete",
+"fetid",
+"fetus",
+"feud",
+"fever",
+"few",
+"ff",
+"fff",
+"ffff",
+"fg",
+"fgh",
+"fh",
+"fi",
+"fiat",
+"fib",
+"fibrin",
+"fiche",
+"fide",
+"fief",
+"field",
+"fiend",
+"fiery",
+"fife",
+"fifo",
+"fifth",
+"fifty",
+"fig",
+"fight",
+"filch",
+"file",
+"filet",
+"fill",
+"filler",
+"filly",
+"film",
+"filmy",
+"filth",
+"fin",
+"final",
+"finale",
+"finch",
+"find",
+"fine",
+"finite",
+"fink",
+"finn",
+"finny",
+"fir",
+"fire",
+"firm",
+"first",
+"fish",
+"fishy",
+"fisk",
+"fiske",
+"fist",
+"fit",
+"fitch",
+"five",
+"fix",
+"fj",
+"fjord",
+"fk",
+"fl",
+"flack",
+"flag",
+"flail",
+"flair",
+"flak",
+"flake",
+"flaky",
+"flam",
+"flame",
+"flank",
+"flap",
+"flare",
+"flash",
+"flask",
+"flat",
+"flatus",
+"flaw",
+"flax",
+"flea",
+"fleck",
+"fled",
+"flee",
+"fleet",
+"flesh",
+"flew",
+"flex",
+"flick",
+"flier",
+"flinch",
+"fling",
+"flint",
+"flip",
+"flirt",
+"flit",
+"flo",
+"float",
+"floc",
+"flock",
+"floe",
+"flog",
+"flood",
+"floor",
+"flop",
+"floppy",
+"flora",
+"flour",
+"flout",
+"flow",
+"flown",
+"floyd",
+"flu",
+"flub",
+"flue",
+"fluff",
+"fluid",
+"fluke",
+"flung",
+"flush",
+"flute",
+"flux",
+"fly",
+"flyer",
+"flynn",
+"fm",
+"fmc",
+"fn",
+"fo",
+"foal",
+"foam",
+"foamy",
+"fob",
+"focal",
+"foci",
+"focus",
+"fodder",
+"foe",
+"fog",
+"foggy",
+"fogy",
+"foil",
+"foist",
+"fold",
+"foley",
+"folio",
+"folk",
+"folly",
+"fond",
+"font",
+"food",
+"fool",
+"foot",
+"foote",
+"fop",
+"for",
+"foray",
+"force",
+"ford",
+"fore",
+"forge",
+"forgot",
+"fork",
+"form",
+"fort",
+"forte",
+"forth",
+"forty",
+"forum",
+"foss",
+"fossil",
+"foul",
+"found",
+"fount",
+"four",
+"fovea",
+"fowl",
+"fox",
+"foxy",
+"foyer",
+"fp",
+"fpc",
+"fq",
+"fr",
+"frail",
+"frame",
+"fran",
+"franc",
+"franca",
+"frank",
+"franz",
+"frau",
+"fraud",
+"fray",
+"freak",
+"fred",
+"free",
+"freed",
+"freer",
+"frenzy",
+"freon",
+"fresh",
+"fret",
+"freud",
+"frey",
+"freya",
+"friar",
+"frick",
+"fried",
+"frill",
+"frilly",
+"frisky",
+"fritz",
+"fro",
+"frock",
+"frog",
+"from",
+"front",
+"frost",
+"froth",
+"frown",
+"froze",
+"fruit",
+"fry",
+"frye",
+"fs",
+"ft",
+"ftc",
+"fu",
+"fuchs",
+"fudge",
+"fuel",
+"fugal",
+"fugue",
+"fuji",
+"full",
+"fully",
+"fum",
+"fume",
+"fun",
+"fund",
+"fungal",
+"fungi",
+"funk",
+"funny",
+"fur",
+"furl",
+"furry",
+"fury",
+"furze",
+"fuse",
+"fuss",
+"fussy",
+"fusty",
+"fuzz",
+"fuzzy",
+"fv",
+"fw",
+"fx",
+"fy",
+"fz",
+"g",
+"g's",
+"g2",
+"g3",
+"g4",
+"g5",
+"g6",
+"g7",
+"g8",
+"g9",
+"ga",
+"gab",
+"gable",
+"gabon",
+"gad",
+"gadget",
+"gaff",
+"gaffe",
+"gag",
+"gage",
+"gail",
+"gain",
+"gait",
+"gal",
+"gala",
+"galaxy",
+"gale",
+"galen",
+"gall",
+"gallop",
+"galt",
+"gam",
+"game",
+"gamin",
+"gamma",
+"gamut",
+"gander",
+"gang",
+"gao",
+"gap",
+"gape",
+"gar",
+"garb",
+"garish",
+"garner",
+"garry",
+"garth",
+"gary",
+"gas",
+"gash",
+"gasp",
+"gassy",
+"gate",
+"gates",
+"gator",
+"gauche",
+"gaudy",
+"gauge",
+"gaul",
+"gaunt",
+"gaur",
+"gauss",
+"gauze",
+"gave",
+"gavel",
+"gavin",
+"gawk",
+"gawky",
+"gay",
+"gaze",
+"gb",
+"gc",
+"gd",
+"ge",
+"gear",
+"gecko",
+"gee",
+"geese",
+"geigy",
+"gel",
+"geld",
+"gem",
+"gemma",
+"gene",
+"genie",
+"genii",
+"genoa",
+"genre",
+"gent",
+"gentry",
+"genus",
+"gerbil",
+"germ",
+"gerry",
+"get",
+"getty",
+"gf",
+"gg",
+"ggg",
+"gggg",
+"gh",
+"ghana",
+"ghent",
+"ghetto",
+"ghi",
+"ghost",
+"ghoul",
+"gi",
+"giant",
+"gibbs",
+"gibby",
+"gibe",
+"giddy",
+"gift",
+"gig",
+"gil",
+"gila",
+"gild",
+"giles",
+"gill",
+"gilt",
+"gimbal",
+"gimpy",
+"gin",
+"gina",
+"ginn",
+"gino",
+"gird",
+"girl",
+"girth",
+"gist",
+"give",
+"given",
+"gj",
+"gk",
+"gl",
+"glad",
+"gladdy",
+"glade",
+"glamor",
+"gland",
+"glans",
+"glare",
+"glass",
+"glaze",
+"gleam",
+"glean",
+"glee",
+"glen",
+"glenn",
+"glib",
+"glide",
+"glint",
+"gloat",
+"glob",
+"globe",
+"glom",
+"gloom",
+"glory",
+"gloss",
+"glove",
+"glow",
+"glue",
+"glued",
+"gluey",
+"gluing",
+"glum",
+"glut",
+"glyph",
+"gm",
+"gmt",
+"gn",
+"gnarl",
+"gnash",
+"gnat",
+"gnaw",
+"gnome",
+"gnp",
+"gnu",
+"go",
+"goa",
+"goad",
+"goal",
+"goat",
+"gob",
+"goer",
+"goes",
+"goff",
+"gog",
+"goggle",
+"gogh",
+"gogo",
+"gold",
+"golf",
+"golly",
+"gone",
+"gong",
+"goo",
+"good",
+"goode",
+"goody",
+"goof",
+"goofy",
+"goose",
+"gop",
+"gordon",
+"gore",
+"goren",
+"gorge",
+"gorky",
+"gorse",
+"gory",
+"gosh",
+"gospel",
+"got",
+"gouda",
+"gouge",
+"gould",
+"gourd",
+"gout",
+"gown",
+"gp",
+"gpo",
+"gq",
+"gr",
+"grab",
+"grace",
+"grad",
+"grade",
+"grady",
+"graff",
+"graft",
+"grail",
+"grain",
+"grand",
+"grant",
+"grape",
+"graph",
+"grasp",
+"grass",
+"grata",
+"grate",
+"grater",
+"grave",
+"gravy",
+"gray",
+"graze",
+"great",
+"grebe",
+"greed",
+"greedy",
+"greek",
+"green",
+"greer",
+"greet",
+"greg",
+"gregg",
+"greta",
+"grew",
+"grey",
+"grid",
+"grief",
+"grieve",
+"grill",
+"grim",
+"grime",
+"grimm",
+"grin",
+"grind",
+"grip",
+"gripe",
+"grist",
+"grit",
+"groan",
+"groat",
+"groin",
+"groom",
+"grope",
+"gross",
+"groton",
+"group",
+"grout",
+"grove",
+"grow",
+"growl",
+"grown",
+"grub",
+"gruff",
+"grunt",
+"gs",
+"gsa",
+"gt",
+"gu",
+"guam",
+"guano",
+"guard",
+"guess",
+"guest",
+"guide",
+"guild",
+"guile",
+"guilt",
+"guise",
+"guitar",
+"gules",
+"gulf",
+"gull",
+"gully",
+"gulp",
+"gum",
+"gumbo",
+"gummy",
+"gun",
+"gunk",
+"gunky",
+"gunny",
+"gurgle",
+"guru",
+"gus",
+"gush",
+"gust",
+"gusto",
+"gusty",
+"gut",
+"gutsy",
+"guy",
+"guyana",
+"gv",
+"gw",
+"gwen",
+"gwyn",
+"gx",
+"gy",
+"gym",
+"gyp",
+"gypsy",
+"gyro",
+"gz",
+"h",
+"h's",
+"h2",
+"h3",
+"h4",
+"h5",
+"h6",
+"h7",
+"h8",
+"h9",
+"ha",
+"haag",
+"haas",
+"habib",
+"habit",
+"hack",
+"had",
+"hades",
+"hadron",
+"hagen",
+"hager",
+"hague",
+"hahn",
+"haifa",
+"haiku",
+"hail",
+"hair",
+"hairy",
+"haiti",
+"hal",
+"hale",
+"haley",
+"half",
+"hall",
+"halma",
+"halo",
+"halt",
+"halvah",
+"halve",
+"ham",
+"hamal",
+"hamlin",
+"han",
+"hand",
+"handy",
+"haney",
+"hang",
+"hank",
+"hanna",
+"hanoi",
+"hans",
+"hansel",
+"hap",
+"happy",
+"hard",
+"hardy",
+"hare",
+"harem",
+"hark",
+"harley",
+"harm",
+"harp",
+"harpy",
+"harry",
+"harsh",
+"hart",
+"harvey",
+"hash",
+"hasp",
+"hast",
+"haste",
+"hasty",
+"hat",
+"hatch",
+"hate",
+"hater",
+"hath",
+"hatred",
+"haul",
+"haunt",
+"have",
+"haven",
+"havoc",
+"haw",
+"hawk",
+"hay",
+"haydn",
+"hayes",
+"hays",
+"hazard",
+"haze",
+"hazel",
+"hazy",
+"hb",
+"hc",
+"hd",
+"he",
+"he'd",
+"he'll",
+"head",
+"heady",
+"heal",
+"healy",
+"heap",
+"hear",
+"heard",
+"heart",
+"heat",
+"heath",
+"heave",
+"heavy",
+"hebe",
+"hebrew",
+"heck",
+"heckle",
+"hedge",
+"heed",
+"heel",
+"heft",
+"hefty",
+"heigh",
+"heine",
+"heinz",
+"heir",
+"held",
+"helen",
+"helga",
+"helix",
+"hell",
+"hello",
+"helm",
+"helmut",
+"help",
+"hem",
+"hemp",
+"hen",
+"hence",
+"henri",
+"henry",
+"her",
+"hera",
+"herb",
+"herd",
+"here",
+"hero",
+"heroic",
+"heron",
+"herr",
+"hertz",
+"hess",
+"hesse",
+"hettie",
+"hetty",
+"hew",
+"hewitt",
+"hewn",
+"hex",
+"hey",
+"hf",
+"hg",
+"hh",
+"hhh",
+"hhhh",
+"hi",
+"hiatt",
+"hick",
+"hicks",
+"hid",
+"hide",
+"high",
+"hij",
+"hike",
+"hill",
+"hilly",
+"hilt",
+"hilum",
+"him",
+"hind",
+"hindu",
+"hines",
+"hinge",
+"hint",
+"hip",
+"hippo",
+"hippy",
+"hiram",
+"hire",
+"hirsch",
+"his",
+"hiss",
+"hit",
+"hitch",
+"hive",
+"hj",
+"hk",
+"hl",
+"hm",
+"hn",
+"ho",
+"hoagy",
+"hoar",
+"hoard",
+"hob",
+"hobbs",
+"hobby",
+"hobo",
+"hoc",
+"hock",
+"hodge",
+"hodges",
+"hoe",
+"hoff",
+"hog",
+"hogan",
+"hoi",
+"hokan",
+"hold",
+"holdup",
+"hole",
+"holly",
+"holm",
+"holst",
+"holt",
+"home",
+"homo",
+"honda",
+"hondo",
+"hone",
+"honey",
+"hong",
+"honk",
+"hooch",
+"hood",
+"hoof",
+"hook",
+"hookup",
+"hoop",
+"hoot",
+"hop",
+"hope",
+"horde",
+"horn",
+"horny",
+"horse",
+"horus",
+"hose",
+"host",
+"hot",
+"hotbox",
+"hotel",
+"hough",
+"hound",
+"hour",
+"house",
+"hove",
+"hovel",
+"hover",
+"how",
+"howdy",
+"howe",
+"howl",
+"hoy",
+"hoyt",
+"hp",
+"hq",
+"hr",
+"hs",
+"ht",
+"hu",
+"hub",
+"hubbub",
+"hubby",
+"huber",
+"huck",
+"hue",
+"hued",
+"huff",
+"hug",
+"huge",
+"hugh",
+"hughes",
+"hugo",
+"huh",
+"hulk",
+"hull",
+"hum",
+"human",
+"humid",
+"hump",
+"humus",
+"hun",
+"hunch",
+"hung",
+"hunk",
+"hunt",
+"hurd",
+"hurl",
+"huron",
+"hurrah",
+"hurry",
+"hurst",
+"hurt",
+"hurty",
+"hush",
+"husky",
+"hut",
+"hutch",
+"hv",
+"hw",
+"hx",
+"hy",
+"hyde",
+"hydra",
+"hydro",
+"hyena",
+"hying",
+"hyman",
+"hymen",
+"hymn",
+"hymnal",
+"hz",
+"i",
+"i'd",
+"i'll",
+"i'm",
+"i's",
+"i've",
+"i2",
+"i3",
+"i4",
+"i5",
+"i6",
+"i7",
+"i8",
+"i9",
+"ia",
+"iambic",
+"ian",
+"ib",
+"ibex",
+"ibid",
+"ibis",
+"ibm",
+"ibn",
+"ic",
+"icc",
+"ice",
+"icing",
+"icky",
+"icon",
+"icy",
+"id",
+"ida",
+"idaho",
+"idea",
+"ideal",
+"idiom",
+"idiot",
+"idle",
+"idol",
+"idyll",
+"ie",
+"ieee",
+"if",
+"iffy",
+"ifni",
+"ig",
+"igloo",
+"igor",
+"ih",
+"ii",
+"iii",
+"iiii",
+"ij",
+"ijk",
+"ik",
+"ike",
+"il",
+"ileum",
+"iliac",
+"iliad",
+"ill",
+"illume",
+"ilona",
+"im",
+"image",
+"imbue",
+"imp",
+"impel",
+"import",
+"impute",
+"in",
+"inane",
+"inapt",
+"inc",
+"inca",
+"incest",
+"inch",
+"incur",
+"index",
+"india",
+"indies",
+"indy",
+"inept",
+"inert",
+"infect",
+"infer",
+"infima",
+"infix",
+"infra",
+"ingot",
+"inhere",
+"injun",
+"ink",
+"inlay",
+"inlet",
+"inman",
+"inn",
+"inner",
+"input",
+"insect",
+"inset",
+"insult",
+"intend",
+"inter",
+"into",
+"inure",
+"invoke",
+"io",
+"ion",
+"ionic",
+"iota",
+"iowa",
+"ip",
+"ipso",
+"iq",
+"ir",
+"ira",
+"iran",
+"iraq",
+"irate",
+"ire",
+"irene",
+"iris",
+"irish",
+"irk",
+"irma",
+"iron",
+"irony",
+"irs",
+"irvin",
+"irwin",
+"is",
+"isaac",
+"isabel",
+"ising",
+"isis",
+"islam",
+"island",
+"isle",
+"isn't",
+"israel",
+"issue",
+"it",
+"it&t",
+"it'd",
+"it'll",
+"italy",
+"itch",
+"item",
+"ito",
+"itt",
+"iu",
+"iv",
+"ivan",
+"ive",
+"ivory",
+"ivy",
+"iw",
+"ix",
+"iy",
+"iz",
+"j",
+"j's",
+"j2",
+"j3",
+"j4",
+"j5",
+"j6",
+"j7",
+"j8",
+"j9",
+"ja",
+"jab",
+"jack",
+"jacky",
+"jacm",
+"jacob",
+"jacobi",
+"jade",
+"jag",
+"jail",
+"jaime",
+"jake",
+"jam",
+"james",
+"jan",
+"jane",
+"janet",
+"janos",
+"janus",
+"japan",
+"jar",
+"jason",
+"java",
+"jaw",
+"jay",
+"jazz",
+"jazzy",
+"jb",
+"jc",
+"jd",
+"je",
+"jean",
+"jed",
+"jeep",
+"jeff",
+"jejune",
+"jelly",
+"jenny",
+"jeres",
+"jerk",
+"jerky",
+"jerry",
+"jersey",
+"jess",
+"jesse",
+"jest",
+"jesus",
+"jet",
+"jew",
+"jewel",
+"jewett",
+"jewish",
+"jf",
+"jg",
+"jh",
+"ji",
+"jibe",
+"jiffy",
+"jig",
+"jill",
+"jilt",
+"jim",
+"jimmy",
+"jinx",
+"jive",
+"jj",
+"jjj",
+"jjjj",
+"jk",
+"jkl",
+"jl",
+"jm",
+"jn",
+"jo",
+"joan",
+"job",
+"jock",
+"jockey",
+"joe",
+"joel",
+"joey",
+"jog",
+"john",
+"johns",
+"join",
+"joint",
+"joke",
+"jolla",
+"jolly",
+"jolt",
+"jon",
+"jonas",
+"jones",
+"jorge",
+"jose",
+"josef",
+"joshua",
+"joss",
+"jostle",
+"jot",
+"joule",
+"joust",
+"jove",
+"jowl",
+"jowly",
+"joy",
+"joyce",
+"jp",
+"jq",
+"jr",
+"js",
+"jt",
+"ju",
+"juan",
+"judas",
+"judd",
+"jude",
+"judge",
+"judo",
+"judy",
+"jug",
+"juggle",
+"juice",
+"juicy",
+"juju",
+"juke",
+"jukes",
+"julep",
+"jules",
+"julia",
+"julie",
+"julio",
+"july",
+"jumbo",
+"jump",
+"jumpy",
+"junco",
+"june",
+"junk",
+"junky",
+"juno",
+"junta",
+"jura",
+"jure",
+"juror",
+"jury",
+"just",
+"jut",
+"jute",
+"jv",
+"jw",
+"jx",
+"jy",
+"jz",
+"k",
+"k's",
+"k2",
+"k3",
+"k4",
+"k5",
+"k6",
+"k7",
+"k8",
+"k9",
+"ka",
+"kabul",
+"kafka",
+"kahn",
+"kajar",
+"kale",
+"kalmia",
+"kane",
+"kant",
+"kapok",
+"kappa",
+"karate",
+"karen",
+"karl",
+"karma",
+"karol",
+"karp",
+"kate",
+"kathy",
+"katie",
+"katz",
+"kava",
+"kay",
+"kayo",
+"kazoo",
+"kb",
+"kc",
+"kd",
+"ke",
+"keats",
+"keel",
+"keen",
+"keep",
+"keg",
+"keith",
+"keller",
+"kelly",
+"kelp",
+"kemp",
+"ken",
+"keno",
+"kent",
+"kenya",
+"kepler",
+"kept",
+"kern",
+"kerr",
+"kerry",
+"ketch",
+"kevin",
+"key",
+"keyed",
+"keyes",
+"keys",
+"kf",
+"kg",
+"kh",
+"khaki",
+"khan",
+"khmer",
+"ki",
+"kick",
+"kid",
+"kidde",
+"kidney",
+"kiev",
+"kigali",
+"kill",
+"kim",
+"kin",
+"kind",
+"king",
+"kink",
+"kinky",
+"kiosk",
+"kiowa",
+"kirby",
+"kirk",
+"kirov",
+"kiss",
+"kit",
+"kite",
+"kitty",
+"kiva",
+"kivu",
+"kiwi",
+"kj",
+"kk",
+"kkk",
+"kkkk",
+"kl",
+"klan",
+"klaus",
+"klein",
+"kline",
+"klm",
+"klux",
+"km",
+"kn",
+"knack",
+"knapp",
+"knauer",
+"knead",
+"knee",
+"kneel",
+"knelt",
+"knew",
+"knick",
+"knife",
+"knit",
+"knob",
+"knock",
+"knoll",
+"knot",
+"knott",
+"know",
+"known",
+"knox",
+"knurl",
+"ko",
+"koala",
+"koch",
+"kodak",
+"kola",
+"kombu",
+"kong",
+"koran",
+"korea",
+"kp",
+"kq",
+"kr",
+"kraft",
+"krause",
+"kraut",
+"krebs",
+"kruse",
+"ks",
+"kt",
+"ku",
+"kudo",
+"kudzu",
+"kuhn",
+"kulak",
+"kurd",
+"kurt",
+"kv",
+"kw",
+"kx",
+"ky",
+"kyle",
+"kyoto",
+"kz",
+"l",
+"l's",
+"l2",
+"l3",
+"l4",
+"l5",
+"l6",
+"l7",
+"l8",
+"l9",
+"la",
+"lab",
+"laban",
+"label",
+"labia",
+"labile",
+"lac",
+"lace",
+"lack",
+"lacy",
+"lad",
+"laden",
+"ladle",
+"lady",
+"lag",
+"lager",
+"lagoon",
+"lagos",
+"laid",
+"lain",
+"lair",
+"laity",
+"lake",
+"lam",
+"lamar",
+"lamb",
+"lame",
+"lamp",
+"lana",
+"lance",
+"land",
+"lane",
+"lang",
+"lange",
+"lanka",
+"lanky",
+"lao",
+"laos",
+"lap",
+"lapel",
+"lapse",
+"larch",
+"lard",
+"lares",
+"large",
+"lark",
+"larkin",
+"larry",
+"lars",
+"larva",
+"lase",
+"lash",
+"lass",
+"lasso",
+"last",
+"latch",
+"late",
+"later",
+"latest",
+"latex",
+"lath",
+"lathe",
+"latin",
+"latus",
+"laud",
+"laue",
+"laugh",
+"launch",
+"laura",
+"lava",
+"law",
+"lawn",
+"lawson",
+"lax",
+"lay",
+"layup",
+"laze",
+"lazy",
+"lb",
+"lc",
+"ld",
+"le",
+"lea",
+"leach",
+"lead",
+"leaf",
+"leafy",
+"leak",
+"leaky",
+"lean",
+"leap",
+"leapt",
+"lear",
+"learn",
+"lease",
+"leash",
+"least",
+"leave",
+"led",
+"ledge",
+"lee",
+"leech",
+"leeds",
+"leek",
+"leer",
+"leery",
+"leeway",
+"left",
+"lefty",
+"leg",
+"legal",
+"leggy",
+"legion",
+"leigh",
+"leila",
+"leland",
+"lemma",
+"lemon",
+"len",
+"lena",
+"lend",
+"lenin",
+"lenny",
+"lens",
+"lent",
+"leo",
+"leon",
+"leona",
+"leone",
+"leper",
+"leroy",
+"less",
+"lessee",
+"lest",
+"let",
+"lethe",
+"lev",
+"levee",
+"level",
+"lever",
+"levi",
+"levin",
+"levis",
+"levy",
+"lew",
+"lewd",
+"lewis",
+"leyden",
+"lf",
+"lg",
+"lh",
+"li",
+"liar",
+"libel",
+"libido",
+"libya",
+"lice",
+"lick",
+"lid",
+"lie",
+"lied",
+"lien",
+"lieu",
+"life",
+"lifo",
+"lift",
+"light",
+"like",
+"liken",
+"lila",
+"lilac",
+"lilly",
+"lilt",
+"lily",
+"lima",
+"limb",
+"limbo",
+"lime",
+"limit",
+"limp",
+"lin",
+"lind",
+"linda",
+"linden",
+"line",
+"linen",
+"lingo",
+"link",
+"lint",
+"linus",
+"lion",
+"lip",
+"lipid",
+"lisa",
+"lise",
+"lisle",
+"lisp",
+"list",
+"listen",
+"lit",
+"lithe",
+"litton",
+"live",
+"liven",
+"livid",
+"livre",
+"liz",
+"lizzie",
+"lj",
+"lk",
+"ll",
+"lll",
+"llll",
+"lloyd",
+"lm",
+"lmn",
+"ln",
+"lo",
+"load",
+"loaf",
+"loam",
+"loamy",
+"loan",
+"loath",
+"lob",
+"lobar",
+"lobby",
+"lobe",
+"lobo",
+"local",
+"loci",
+"lock",
+"locke",
+"locus",
+"lodge",
+"loeb",
+"loess",
+"loft",
+"lofty",
+"log",
+"logan",
+"loge",
+"logic",
+"loin",
+"loire",
+"lois",
+"loiter",
+"loki",
+"lola",
+"loll",
+"lolly",
+"lomb",
+"lome",
+"lone",
+"long",
+"look",
+"loom",
+"loon",
+"loop",
+"loose",
+"loot",
+"lop",
+"lope",
+"lopez",
+"lord",
+"lore",
+"loren",
+"los",
+"lose",
+"loss",
+"lossy",
+"lost",
+"lot",
+"lotte",
+"lotus",
+"lou",
+"loud",
+"louis",
+"louise",
+"louse",
+"lousy",
+"louver",
+"love",
+"low",
+"lowe",
+"lower",
+"lowry",
+"loy",
+"loyal",
+"lp",
+"lq",
+"lr",
+"ls",
+"lsi",
+"lt",
+"ltv",
+"lu",
+"lucas",
+"lucia",
+"lucid",
+"luck",
+"lucky",
+"lucre",
+"lucy",
+"lug",
+"luge",
+"luger",
+"luis",
+"luke",
+"lull",
+"lulu",
+"lumbar",
+"lumen",
+"lump",
+"lumpy",
+"lunar",
+"lunch",
+"lund",
+"lung",
+"lunge",
+"lura",
+"lurch",
+"lure",
+"lurid",
+"lurk",
+"lush",
+"lust",
+"lusty",
+"lute",
+"lutz",
+"lux",
+"luxe",
+"luzon",
+"lv",
+"lw",
+"lx",
+"ly",
+"lydia",
+"lye",
+"lying",
+"lykes",
+"lyle",
+"lyman",
+"lymph",
+"lynch",
+"lynn",
+"lynx",
+"lyon",
+"lyons",
+"lyra",
+"lyric",
+"lz",
+"m",
+"m&m",
+"m's",
+"m2",
+"m3",
+"m4",
+"m5",
+"m6",
+"m7",
+"m8",
+"m9",
+"ma",
+"mabel",
+"mac",
+"mace",
+"mach",
+"macho",
+"mack",
+"mackey",
+"macon",
+"macro",
+"mad",
+"madam",
+"made",
+"madman",
+"madsen",
+"mae",
+"magi",
+"magic",
+"magma",
+"magna",
+"magog",
+"maid",
+"maier",
+"mail",
+"maim",
+"main",
+"maine",
+"major",
+"make",
+"malady",
+"malay",
+"male",
+"mali",
+"mall",
+"malt",
+"malta",
+"mambo",
+"mamma",
+"mammal",
+"man",
+"mana",
+"manama",
+"mane",
+"mange",
+"mania",
+"manic",
+"mann",
+"manna",
+"manor",
+"mans",
+"manse",
+"mantle",
+"many",
+"mao",
+"maori",
+"map",
+"maple",
+"mar",
+"marc",
+"march",
+"marco",
+"marcy",
+"mardi",
+"mare",
+"margo",
+"maria",
+"marie",
+"marin",
+"marine",
+"mario",
+"mark",
+"marks",
+"marlin",
+"marrow",
+"marry",
+"mars",
+"marsh",
+"mart",
+"marty",
+"marx",
+"mary",
+"maser",
+"mash",
+"mask",
+"mason",
+"masque",
+"mass",
+"mast",
+"mat",
+"match",
+"mate",
+"mateo",
+"mater",
+"math",
+"matte",
+"maul",
+"mauve",
+"mavis",
+"maw",
+"mawr",
+"max",
+"maxim",
+"maxima",
+"may",
+"maya",
+"maybe",
+"mayer",
+"mayhem",
+"mayo",
+"mayor",
+"mayst",
+"mazda",
+"maze",
+"mb",
+"mba",
+"mc",
+"mccoy",
+"mcgee",
+"mckay",
+"mckee",
+"mcleod",
+"md",
+"me",
+"mead",
+"meal",
+"mealy",
+"mean",
+"meant",
+"meat",
+"meaty",
+"mecca",
+"mecum",
+"medal",
+"medea",
+"media",
+"medic",
+"medley",
+"meek",
+"meet",
+"meg",
+"mega",
+"meier",
+"meir",
+"mel",
+"meld",
+"melee",
+"mellow",
+"melon",
+"melt",
+"memo",
+"memoir",
+"men",
+"mend",
+"menlo",
+"menu",
+"merck",
+"mercy",
+"mere",
+"merge",
+"merit",
+"merle",
+"merry",
+"mesa",
+"mescal",
+"mesh",
+"meson",
+"mess",
+"messy",
+"met",
+"metal",
+"mete",
+"meter",
+"metro",
+"mew",
+"meyer",
+"meyers",
+"mezzo",
+"mf",
+"mg",
+"mh",
+"mi",
+"miami",
+"mica",
+"mice",
+"mickey",
+"micky",
+"micro",
+"mid",
+"midas",
+"midge",
+"midst",
+"mien",
+"miff",
+"mig",
+"might",
+"mike",
+"mila",
+"milan",
+"milch",
+"mild",
+"mildew",
+"mile",
+"miles",
+"milk",
+"milky",
+"mill",
+"mills",
+"milt",
+"mimi",
+"mimic",
+"mince",
+"mind",
+"mine",
+"mini",
+"minim",
+"mink",
+"minnow",
+"minor",
+"minos",
+"minot",
+"minsk",
+"mint",
+"minus",
+"mira",
+"mirage",
+"mire",
+"mirth",
+"miser",
+"misery",
+"miss",
+"missy",
+"mist",
+"misty",
+"mit",
+"mite",
+"mitre",
+"mitt",
+"mix",
+"mixup",
+"mizar",
+"mj",
+"mk",
+"ml",
+"mm",
+"mmm",
+"mmmm",
+"mn",
+"mno",
+"mo",
+"moan",
+"moat",
+"mob",
+"mobil",
+"mock",
+"modal",
+"mode",
+"model",
+"modem",
+"modish",
+"moe",
+"moen",
+"mohr",
+"moire",
+"moist",
+"molal",
+"molar",
+"mold",
+"mole",
+"moll",
+"mollie",
+"molly",
+"molt",
+"molten",
+"mommy",
+"mona",
+"monad",
+"mondo",
+"monel",
+"money",
+"monic",
+"monk",
+"mont",
+"monte",
+"month",
+"monty",
+"moo",
+"mood",
+"moody",
+"moon",
+"moor",
+"moore",
+"moose",
+"moot",
+"mop",
+"moral",
+"morale",
+"moran",
+"more",
+"morel",
+"morn",
+"moron",
+"morse",
+"morsel",
+"mort",
+"mosaic",
+"moser",
+"moses",
+"moss",
+"mossy",
+"most",
+"mot",
+"motel",
+"motet",
+"moth",
+"mother",
+"motif",
+"motor",
+"motto",
+"mould",
+"mound",
+"mount",
+"mourn",
+"mouse",
+"mousy",
+"mouth",
+"move",
+"movie",
+"mow",
+"moyer",
+"mp",
+"mph",
+"mq",
+"mr",
+"mrs",
+"ms",
+"mt",
+"mu",
+"much",
+"muck",
+"mucus",
+"mud",
+"mudd",
+"muddy",
+"muff",
+"muffin",
+"mug",
+"muggy",
+"mugho",
+"muir",
+"mulch",
+"mulct",
+"mule",
+"mull",
+"multi",
+"mum",
+"mummy",
+"munch",
+"mung",
+"munson",
+"muon",
+"muong",
+"mural",
+"muriel",
+"murk",
+"murky",
+"murre",
+"muse",
+"mush",
+"mushy",
+"music",
+"musk",
+"muslim",
+"must",
+"musty",
+"mute",
+"mutt",
+"muzak",
+"muzo",
+"mv",
+"mw",
+"mx",
+"my",
+"myel",
+"myers",
+"mylar",
+"mynah",
+"myopia",
+"myra",
+"myron",
+"myrrh",
+"myself",
+"myth",
+"mz",
+"n",
+"n's",
+"n2",
+"n3",
+"n4",
+"n5",
+"n6",
+"n7",
+"n8",
+"n9",
+"na",
+"naacp",
+"nab",
+"nadir",
+"nag",
+"nagoya",
+"nagy",
+"naiad",
+"nail",
+"nair",
+"naive",
+"naked",
+"name",
+"nan",
+"nancy",
+"naomi",
+"nap",
+"nary",
+"nasa",
+"nasal",
+"nash",
+"nasty",
+"nat",
+"natal",
+"nate",
+"nato",
+"natty",
+"nature",
+"naval",
+"nave",
+"navel",
+"navy",
+"nay",
+"nazi",
+"nb",
+"nbc",
+"nbs",
+"nc",
+"ncaa",
+"ncr",
+"nd",
+"ne",
+"neal",
+"near",
+"neat",
+"neath",
+"neck",
+"ned",
+"nee",
+"need",
+"needy",
+"neff",
+"negate",
+"negro",
+"nehru",
+"neil",
+"nell",
+"nelsen",
+"neon",
+"nepal",
+"nero",
+"nerve",
+"ness",
+"nest",
+"net",
+"neuron",
+"neva",
+"neve",
+"new",
+"newel",
+"newt",
+"next",
+"nf",
+"ng",
+"nh",
+"ni",
+"nib",
+"nibs",
+"nice",
+"nicety",
+"niche",
+"nick",
+"niece",
+"niger",
+"nigh",
+"night",
+"nih",
+"nikko",
+"nil",
+"nile",
+"nimbus",
+"nimh",
+"nina",
+"nine",
+"ninth",
+"niobe",
+"nip",
+"nit",
+"nitric",
+"nitty",
+"nixon",
+"nj",
+"nk",
+"nl",
+"nm",
+"nn",
+"nnn",
+"nnnn",
+"no",
+"noaa",
+"noah",
+"nob",
+"nobel",
+"noble",
+"nod",
+"nodal",
+"node",
+"noel",
+"noise",
+"noisy",
+"nolan",
+"noll",
+"nolo",
+"nomad",
+"non",
+"nonce",
+"none",
+"nook",
+"noon",
+"noose",
+"nop",
+"nor",
+"nora",
+"norm",
+"norma",
+"north",
+"norway",
+"nose",
+"not",
+"notch",
+"note",
+"notre",
+"noun",
+"nov",
+"nova",
+"novak",
+"novel",
+"novo",
+"now",
+"np",
+"nq",
+"nr",
+"nrc",
+"ns",
+"nsf",
+"nt",
+"ntis",
+"nu",
+"nuance",
+"nubia",
+"nuclei",
+"nude",
+"nudge",
+"null",
+"numb",
+"nun",
+"nurse",
+"nut",
+"nv",
+"nw",
+"nx",
+"ny",
+"nyc",
+"nylon",
+"nymph",
+"nyu",
+"nz",
+"o",
+"o'er",
+"o's",
+"o2",
+"o3",
+"o4",
+"o5",
+"o6",
+"o7",
+"o8",
+"o9",
+"oa",
+"oaf",
+"oak",
+"oaken",
+"oakley",
+"oar",
+"oases",
+"oasis",
+"oat",
+"oath",
+"ob",
+"obese",
+"obey",
+"objet",
+"oboe",
+"oc",
+"occur",
+"ocean",
+"oct",
+"octal",
+"octave",
+"octet",
+"od",
+"odd",
+"ode",
+"odin",
+"odium",
+"oe",
+"of",
+"off",
+"offal",
+"offend",
+"offer",
+"oft",
+"often",
+"og",
+"ogden",
+"ogle",
+"ogre",
+"oh",
+"ohio",
+"ohm",
+"ohmic",
+"oi",
+"oil",
+"oily",
+"oint",
+"oj",
+"ok",
+"okay",
+"ol",
+"olaf",
+"olav",
+"old",
+"olden",
+"oldy",
+"olga",
+"olin",
+"olive",
+"olsen",
+"olson",
+"om",
+"omaha",
+"oman",
+"omega",
+"omen",
+"omit",
+"on",
+"once",
+"one",
+"onion",
+"only",
+"onset",
+"onto",
+"onus",
+"onward",
+"onyx",
+"oo",
+"ooo",
+"oooo",
+"ooze",
+"op",
+"opal",
+"opec",
+"opel",
+"open",
+"opera",
+"opium",
+"opt",
+"optic",
+"opus",
+"oq",
+"or",
+"oral",
+"orate",
+"orb",
+"orbit",
+"orchid",
+"ordain",
+"order",
+"ore",
+"organ",
+"orgy",
+"orin",
+"orion",
+"ornery",
+"orono",
+"orr",
+"os",
+"osaka",
+"oscar",
+"osier",
+"oslo",
+"ot",
+"other",
+"otis",
+"ott",
+"otter",
+"otto",
+"ou",
+"ouch",
+"ought",
+"ounce",
+"our",
+"oust",
+"out",
+"ouvre",
+"ouzel",
+"ouzo",
+"ov",
+"ova",
+"oval",
+"ovary",
+"ovate",
+"oven",
+"over",
+"overt",
+"ovid",
+"ow",
+"owe",
+"owens",
+"owing",
+"owl",
+"owly",
+"own",
+"ox",
+"oxen",
+"oxeye",
+"oxide",
+"oxnard",
+"oy",
+"oz",
+"ozark",
+"ozone",
+"p",
+"p's",
+"p2",
+"p3",
+"p4",
+"p5",
+"p6",
+"p7",
+"p8",
+"p9",
+"pa",
+"pablo",
+"pabst",
+"pace",
+"pack",
+"packet",
+"pact",
+"pad",
+"paddy",
+"padre",
+"paean",
+"pagan",
+"page",
+"paid",
+"pail",
+"pain",
+"paine",
+"paint",
+"pair",
+"pal",
+"pale",
+"pall",
+"palm",
+"palo",
+"palsy",
+"pam",
+"pampa",
+"pan",
+"panama",
+"panda",
+"pane",
+"panel",
+"pang",
+"panic",
+"pansy",
+"pant",
+"panty",
+"paoli",
+"pap",
+"papa",
+"papal",
+"papaw",
+"paper",
+"pappy",
+"papua",
+"par",
+"parch",
+"pardon",
+"pare",
+"pareto",
+"paris",
+"park",
+"parke",
+"parks",
+"parr",
+"parry",
+"parse",
+"part",
+"party",
+"pascal",
+"pasha",
+"paso",
+"pass",
+"passe",
+"past",
+"paste",
+"pasty",
+"pat",
+"patch",
+"pate",
+"pater",
+"path",
+"patio",
+"patsy",
+"patti",
+"patton",
+"patty",
+"paul",
+"paula",
+"pauli",
+"paulo",
+"pause",
+"pave",
+"paw",
+"pawn",
+"pax",
+"pay",
+"payday",
+"payne",
+"paz",
+"pb",
+"pbs",
+"pc",
+"pd",
+"pe",
+"pea",
+"peace",
+"peach",
+"peak",
+"peaky",
+"peal",
+"peale",
+"pear",
+"pearl",
+"pease",
+"peat",
+"pebble",
+"pecan",
+"peck",
+"pecos",
+"pedal",
+"pedro",
+"pee",
+"peed",
+"peek",
+"peel",
+"peep",
+"peepy",
+"peer",
+"peg",
+"peggy",
+"pelt",
+"pen",
+"penal",
+"pence",
+"pencil",
+"pend",
+"penh",
+"penn",
+"penna",
+"penny",
+"pent",
+"peony",
+"pep",
+"peppy",
+"pepsi",
+"per",
+"perch",
+"percy",
+"perez",
+"peril",
+"perk",
+"perky",
+"perle",
+"perry",
+"persia",
+"pert",
+"perth",
+"peru",
+"peruse",
+"pest",
+"peste",
+"pet",
+"petal",
+"pete",
+"peter",
+"petit",
+"petri",
+"petty",
+"pew",
+"pewee",
+"pf",
+"pg",
+"ph",
+"ph.d",
+"phage",
+"phase",
+"phd",
+"phenol",
+"phi",
+"phil",
+"phlox",
+"phon",
+"phone",
+"phony",
+"photo",
+"phyla",
+"physic",
+"pi",
+"piano",
+"pica",
+"pick",
+"pickup",
+"picky",
+"pie",
+"piece",
+"pier",
+"pierce",
+"piety",
+"pig",
+"piggy",
+"pike",
+"pile",
+"pill",
+"pilot",
+"pimp",
+"pin",
+"pinch",
+"pine",
+"ping",
+"pinion",
+"pink",
+"pint",
+"pinto",
+"pion",
+"piotr",
+"pious",
+"pip",
+"pipe",
+"piper",
+"pique",
+"pit",
+"pitch",
+"pith",
+"pithy",
+"pitney",
+"pitt",
+"pity",
+"pius",
+"pivot",
+"pixel",
+"pixy",
+"pizza",
+"pj",
+"pk",
+"pl",
+"place",
+"plague",
+"plaid",
+"plain",
+"plan",
+"plane",
+"plank",
+"plant",
+"plasm",
+"plat",
+"plate",
+"plato",
+"play",
+"playa",
+"plaza",
+"plea",
+"plead",
+"pleat",
+"pledge",
+"pliny",
+"plod",
+"plop",
+"plot",
+"plow",
+"pluck",
+"plug",
+"plum",
+"plumb",
+"plume",
+"plump",
+"plunk",
+"plus",
+"plush",
+"plushy",
+"pluto",
+"ply",
+"pm",
+"pn",
+"po",
+"poach",
+"pobox",
+"pod",
+"podge",
+"podia",
+"poe",
+"poem",
+"poesy",
+"poet",
+"poetry",
+"pogo",
+"poi",
+"point",
+"poise",
+"poke",
+"pol",
+"polar",
+"pole",
+"police",
+"polio",
+"polis",
+"polk",
+"polka",
+"poll",
+"polo",
+"pomona",
+"pomp",
+"ponce",
+"pond",
+"pong",
+"pont",
+"pony",
+"pooch",
+"pooh",
+"pool",
+"poole",
+"poop",
+"poor",
+"pop",
+"pope",
+"poppy",
+"porch",
+"pore",
+"pork",
+"porous",
+"port",
+"porte",
+"portia",
+"porto",
+"pose",
+"posey",
+"posh",
+"posit",
+"posse",
+"post",
+"posy",
+"pot",
+"potts",
+"pouch",
+"pound",
+"pour",
+"pout",
+"pow",
+"powder",
+"power",
+"pp",
+"ppm",
+"ppp",
+"pppp",
+"pq",
+"pqr",
+"pr",
+"prado",
+"pram",
+"prank",
+"pratt",
+"pray",
+"preen",
+"prefix",
+"prep",
+"press",
+"prexy",
+"prey",
+"priam",
+"price",
+"prick",
+"pride",
+"prig",
+"prim",
+"prima",
+"prime",
+"primp",
+"prince",
+"print",
+"prior",
+"prism",
+"prissy",
+"privy",
+"prize",
+"pro",
+"probe",
+"prod",
+"prof",
+"prom",
+"prone",
+"prong",
+"proof",
+"prop",
+"propyl",
+"prose",
+"proud",
+"prove",
+"prow",
+"prowl",
+"proxy",
+"prune",
+"pry",
+"ps",
+"psalm",
+"psi",
+"psych",
+"pt",
+"pta",
+"pu",
+"pub",
+"puck",
+"puddly",
+"puerto",
+"puff",
+"puffy",
+"pug",
+"pugh",
+"puke",
+"pull",
+"pulp",
+"pulse",
+"puma",
+"pump",
+"pun",
+"punch",
+"punic",
+"punish",
+"punk",
+"punky",
+"punt",
+"puny",
+"pup",
+"pupal",
+"pupil",
+"puppy",
+"pure",
+"purge",
+"purl",
+"purr",
+"purse",
+"pus",
+"pusan",
+"pusey",
+"push",
+"pussy",
+"put",
+"putt",
+"putty",
+"pv",
+"pvc",
+"pw",
+"px",
+"py",
+"pygmy",
+"pyle",
+"pyre",
+"pyrex",
+"pyrite",
+"pz",
+"q",
+"q's",
+"q2",
+"q3",
+"q4",
+"q5",
+"q6",
+"q7",
+"q8",
+"q9",
+"qa",
+"qatar",
+"qb",
+"qc",
+"qd",
+"qe",
+"qed",
+"qf",
+"qg",
+"qh",
+"qi",
+"qj",
+"qk",
+"ql",
+"qm",
+"qn",
+"qo",
+"qp",
+"qq",
+"qqq",
+"qqqq",
+"qr",
+"qrs",
+"qs",
+"qt",
+"qu",
+"qua",
+"quack",
+"quad",
+"quaff",
+"quail",
+"quake",
+"qualm",
+"quark",
+"quarry",
+"quart",
+"quash",
+"quasi",
+"quay",
+"queasy",
+"queen",
+"queer",
+"quell",
+"query",
+"quest",
+"queue",
+"quick",
+"quid",
+"quiet",
+"quill",
+"quilt",
+"quinn",
+"quint",
+"quip",
+"quirk",
+"quirt",
+"quit",
+"quite",
+"quito",
+"quiz",
+"quo",
+"quod",
+"quota",
+"quote",
+"qv",
+"qw",
+"qx",
+"qy",
+"qz",
+"r",
+"r&d",
+"r's",
+"r2",
+"r3",
+"r4",
+"r5",
+"r6",
+"r7",
+"r8",
+"r9",
+"ra",
+"rabat",
+"rabbi",
+"rabbit",
+"rabid",
+"rabin",
+"race",
+"rack",
+"racy",
+"radar",
+"radii",
+"radio",
+"radium",
+"radix",
+"radon",
+"rae",
+"rafael",
+"raft",
+"rag",
+"rage",
+"raid",
+"rail",
+"rain",
+"rainy",
+"raise",
+"raj",
+"rajah",
+"rake",
+"rally",
+"ralph",
+"ram",
+"raman",
+"ramo",
+"ramp",
+"ramsey",
+"ran",
+"ranch",
+"rand",
+"randy",
+"rang",
+"range",
+"rangy",
+"rank",
+"rant",
+"raoul",
+"rap",
+"rape",
+"rapid",
+"rapt",
+"rare",
+"rasa",
+"rascal",
+"rash",
+"rasp",
+"rat",
+"rata",
+"rate",
+"rater",
+"ratio",
+"rattle",
+"raul",
+"rave",
+"ravel",
+"raven",
+"raw",
+"ray",
+"raze",
+"razor",
+"rb",
+"rc",
+"rca",
+"rd",
+"re",
+"reach",
+"read",
+"ready",
+"reagan",
+"real",
+"realm",
+"ream",
+"reap",
+"rear",
+"reave",
+"reb",
+"rebel",
+"rebut",
+"recipe",
+"reck",
+"recur",
+"red",
+"redeem",
+"reduce",
+"reed",
+"reedy",
+"reef",
+"reek",
+"reel",
+"reese",
+"reeve",
+"refer",
+"regal",
+"regina",
+"regis",
+"reich",
+"reid",
+"reign",
+"rein",
+"relax",
+"relay",
+"relic",
+"reman",
+"remedy",
+"remit",
+"remus",
+"rena",
+"renal",
+"rend",
+"rene",
+"renown",
+"rent",
+"rep",
+"repel",
+"repent",
+"resin",
+"resort",
+"rest",
+"ret",
+"retch",
+"return",
+"reub",
+"rev",
+"reveal",
+"revel",
+"rever",
+"revet",
+"revved",
+"rex",
+"rf",
+"rg",
+"rh",
+"rhea",
+"rheum",
+"rhine",
+"rhino",
+"rho",
+"rhoda",
+"rhode",
+"rhyme",
+"ri",
+"rib",
+"rica",
+"rice",
+"rich",
+"rick",
+"rico",
+"rid",
+"ride",
+"ridge",
+"rifle",
+"rift",
+"rig",
+"riga",
+"rigel",
+"riggs",
+"right",
+"rigid",
+"riley",
+"rill",
+"rilly",
+"rim",
+"rime",
+"rimy",
+"ring",
+"rink",
+"rinse",
+"rio",
+"riot",
+"rip",
+"ripe",
+"ripen",
+"ripley",
+"rise",
+"risen",
+"risk",
+"risky",
+"rite",
+"ritz",
+"rival",
+"riven",
+"river",
+"rivet",
+"riyadh",
+"rj",
+"rk",
+"rl",
+"rm",
+"rn",
+"ro",
+"roach",
+"road",
+"roam",
+"roar",
+"roast",
+"rob",
+"robe",
+"robin",
+"robot",
+"rock",
+"rocket",
+"rocky",
+"rod",
+"rode",
+"rodeo",
+"roe",
+"roger",
+"rogue",
+"roil",
+"role",
+"roll",
+"roman",
+"rome",
+"romeo",
+"romp",
+"ron",
+"rondo",
+"rood",
+"roof",
+"rook",
+"rookie",
+"rooky",
+"room",
+"roomy",
+"roost",
+"root",
+"rope",
+"rosa",
+"rose",
+"rosen",
+"ross",
+"rosy",
+"rot",
+"rotc",
+"roth",
+"rotor",
+"rouge",
+"rough",
+"round",
+"rouse",
+"rout",
+"route",
+"rove",
+"row",
+"rowdy",
+"rowe",
+"roy",
+"royal",
+"royce",
+"rp",
+"rpm",
+"rq",
+"rr",
+"rrr",
+"rrrr",
+"rs",
+"rst",
+"rsvp",
+"rt",
+"ru",
+"ruanda",
+"rub",
+"rube",
+"ruben",
+"rubin",
+"rubric",
+"ruby",
+"ruddy",
+"rude",
+"rudy",
+"rue",
+"rufus",
+"rug",
+"ruin",
+"rule",
+"rum",
+"rumen",
+"rummy",
+"rump",
+"rumpus",
+"run",
+"rune",
+"rung",
+"runge",
+"runic",
+"runt",
+"runty",
+"rupee",
+"rural",
+"ruse",
+"rush",
+"rusk",
+"russ",
+"russo",
+"rust",
+"rusty",
+"rut",
+"ruth",
+"rutty",
+"rv",
+"rw",
+"rx",
+"ry",
+"ryan",
+"ryder",
+"rye",
+"rz",
+"s",
+"s's",
+"s2",
+"s3",
+"s4",
+"s5",
+"s6",
+"s7",
+"s8",
+"s9",
+"sa",
+"sabine",
+"sable",
+"sabra",
+"sac",
+"sachs",
+"sack",
+"sad",
+"saddle",
+"sadie",
+"safari",
+"safe",
+"sag",
+"saga",
+"sage",
+"sago",
+"said",
+"sail",
+"saint",
+"sake",
+"sal",
+"salad",
+"sale",
+"salem",
+"saline",
+"salk",
+"salle",
+"sally",
+"salon",
+"salt",
+"salty",
+"salve",
+"salvo",
+"sam",
+"samba",
+"same",
+"sammy",
+"samoa",
+"samuel",
+"san",
+"sana",
+"sand",
+"sandal",
+"sandy",
+"sane",
+"sang",
+"sank",
+"sans",
+"santa",
+"santo",
+"sao",
+"sap",
+"sappy",
+"sara",
+"sarah",
+"saran",
+"sari",
+"sash",
+"sat",
+"satan",
+"satin",
+"satyr",
+"sauce",
+"saucy",
+"saud",
+"saudi",
+"saul",
+"sault",
+"saute",
+"save",
+"savoy",
+"savvy",
+"saw",
+"sawyer",
+"sax",
+"saxon",
+"say",
+"sb",
+"sc",
+"scab",
+"scala",
+"scald",
+"scale",
+"scalp",
+"scam",
+"scamp",
+"scan",
+"scant",
+"scar",
+"scare",
+"scarf",
+"scary",
+"scat",
+"scaup",
+"scene",
+"scent",
+"school",
+"scion",
+"scm",
+"scoff",
+"scold",
+"scoop",
+"scoot",
+"scope",
+"scops",
+"score",
+"scoria",
+"scorn",
+"scot",
+"scott",
+"scour",
+"scout",
+"scowl",
+"scram",
+"scrap",
+"scrape",
+"screw",
+"scrim",
+"scrub",
+"scuba",
+"scud",
+"scuff",
+"scull",
+"scum",
+"scurry",
+"sd",
+"se",
+"sea",
+"seal",
+"seam",
+"seamy",
+"sean",
+"sear",
+"sears",
+"season",
+"seat",
+"sec",
+"secant",
+"sect",
+"sedan",
+"seder",
+"sedge",
+"see",
+"seed",
+"seedy",
+"seek",
+"seem",
+"seen",
+"seep",
+"seethe",
+"seize",
+"self",
+"sell",
+"selma",
+"semi",
+"sen",
+"send",
+"seneca",
+"senor",
+"sense",
+"sent",
+"sentry",
+"seoul",
+"sepal",
+"sepia",
+"sepoy",
+"sept",
+"septa",
+"sequin",
+"sera",
+"serf",
+"serge",
+"serif",
+"serum",
+"serve",
+"servo",
+"set",
+"seth",
+"seton",
+"setup",
+"seven",
+"sever",
+"severe",
+"sew",
+"sewn",
+"sex",
+"sexy",
+"sf",
+"sg",
+"sh",
+"shack",
+"shad",
+"shade",
+"shady",
+"shafer",
+"shaft",
+"shag",
+"shah",
+"shake",
+"shaken",
+"shako",
+"shaky",
+"shale",
+"shall",
+"sham",
+"shame",
+"shank",
+"shape",
+"shard",
+"share",
+"shari",
+"shark",
+"sharp",
+"shave",
+"shaw",
+"shawl",
+"shay",
+"she",
+"she'd",
+"shea",
+"sheaf",
+"shear",
+"sheath",
+"shed",
+"sheen",
+"sheep",
+"sheer",
+"sheet",
+"sheik",
+"shelf",
+"shell",
+"shied",
+"shift",
+"shill",
+"shim",
+"shin",
+"shine",
+"shinto",
+"shiny",
+"ship",
+"shire",
+"shirk",
+"shirt",
+"shish",
+"shiv",
+"shoal",
+"shock",
+"shod",
+"shoe",
+"shoji",
+"shone",
+"shoo",
+"shook",
+"shoot",
+"shop",
+"shore",
+"short",
+"shot",
+"shout",
+"shove",
+"show",
+"shown",
+"showy",
+"shrank",
+"shred",
+"shrew",
+"shrike",
+"shrub",
+"shrug",
+"shu",
+"shuck",
+"shun",
+"shunt",
+"shut",
+"shy",
+"si",
+"sial",
+"siam",
+"sian",
+"sib",
+"sibley",
+"sibyl",
+"sic",
+"sick",
+"side",
+"sidle",
+"siege",
+"siena",
+"sieve",
+"sift",
+"sigh",
+"sight",
+"sigma",
+"sign",
+"signal",
+"signor",
+"silas",
+"silk",
+"silky",
+"sill",
+"silly",
+"silo",
+"silt",
+"silty",
+"sima",
+"simon",
+"simons",
+"sims",
+"sin",
+"sinai",
+"since",
+"sine",
+"sinew",
+"sing",
+"singe",
+"sinh",
+"sink",
+"sinus",
+"sioux",
+"sip",
+"sir",
+"sire",
+"siren",
+"sis",
+"sisal",
+"sit",
+"site",
+"situ",
+"situs",
+"siva",
+"six",
+"sixgun",
+"sixth",
+"sixty",
+"size",
+"sj",
+"sk",
+"skat",
+"skate",
+"skeet",
+"skew",
+"ski",
+"skid",
+"skied",
+"skiff",
+"skill",
+"skim",
+"skimp",
+"skimpy",
+"skin",
+"skip",
+"skirt",
+"skit",
+"skulk",
+"skull",
+"skunk",
+"sky",
+"skye",
+"sl",
+"slab",
+"slack",
+"slag",
+"slain",
+"slake",
+"slam",
+"slang",
+"slant",
+"slap",
+"slash",
+"slat",
+"slate",
+"slater",
+"slav",
+"slave",
+"slay",
+"sled",
+"sleek",
+"sleep",
+"sleet",
+"slept",
+"slew",
+"slice",
+"slick",
+"slid",
+"slide",
+"slim",
+"slime",
+"slimy",
+"sling",
+"slip",
+"slit",
+"sliver",
+"sloan",
+"slob",
+"sloe",
+"slog",
+"sloop",
+"slop",
+"slope",
+"slosh",
+"slot",
+"sloth",
+"slow",
+"slug",
+"sluice",
+"slum",
+"slump",
+"slung",
+"slur",
+"slurp",
+"sly",
+"sm",
+"smack",
+"small",
+"smart",
+"smash",
+"smear",
+"smell",
+"smelt",
+"smile",
+"smirk",
+"smith",
+"smithy",
+"smog",
+"smoke",
+"smoky",
+"smug",
+"smut",
+"sn",
+"snack",
+"snafu",
+"snag",
+"snail",
+"snake",
+"snap",
+"snare",
+"snark",
+"snarl",
+"snatch",
+"sneak",
+"sneer",
+"snell",
+"snick",
+"sniff",
+"snip",
+"snipe",
+"snob",
+"snook",
+"snoop",
+"snore",
+"snort",
+"snout",
+"snow",
+"snowy",
+"snub",
+"snuff",
+"snug",
+"so",
+"soak",
+"soap",
+"soapy",
+"soar",
+"sob",
+"sober",
+"social",
+"sock",
+"sod",
+"soda",
+"sofa",
+"sofia",
+"soft",
+"soften",
+"soggy",
+"soil",
+"sol",
+"solar",
+"sold",
+"sole",
+"solemn",
+"solid",
+"solo",
+"solon",
+"solve",
+"soma",
+"somal",
+"some",
+"son",
+"sonar",
+"song",
+"sonic",
+"sonny",
+"sonora",
+"sony",
+"soon",
+"soot",
+"sooth",
+"sop",
+"sora",
+"sorb",
+"sore",
+"sorry",
+"sort",
+"sos",
+"sou",
+"sough",
+"soul",
+"sound",
+"soup",
+"sour",
+"source",
+"sousa",
+"south",
+"sow",
+"sown",
+"soy",
+"soya",
+"sp",
+"spa",
+"space",
+"spade",
+"spain",
+"span",
+"spar",
+"spare",
+"sparge",
+"spark",
+"spasm",
+"spat",
+"spate",
+"spawn",
+"spay",
+"speak",
+"spear",
+"spec",
+"speck",
+"sped",
+"speed",
+"spell",
+"spend",
+"spent",
+"sperm",
+"sperry",
+"spew",
+"spica",
+"spice",
+"spicy",
+"spike",
+"spiky",
+"spill",
+"spilt",
+"spin",
+"spine",
+"spiny",
+"spire",
+"spiro",
+"spit",
+"spite",
+"spitz",
+"splat",
+"splay",
+"spline",
+"split",
+"spoil",
+"spoke",
+"spoof",
+"spook",
+"spooky",
+"spool",
+"spoon",
+"spore",
+"sport",
+"spot",
+"spout",
+"sprain",
+"spray",
+"spree",
+"sprig",
+"spruce",
+"sprue",
+"spud",
+"spume",
+"spun",
+"spunk",
+"spur",
+"spurn",
+"spurt",
+"spy",
+"sq",
+"squad",
+"squat",
+"squaw",
+"squibb",
+"squid",
+"squint",
+"sr",
+"sri",
+"ss",
+"sss",
+"ssss",
+"sst",
+"st",
+"st.",
+"stab",
+"stack",
+"stacy",
+"staff",
+"stag",
+"stage",
+"stagy",
+"stahl",
+"staid",
+"stain",
+"stair",
+"stake",
+"stale",
+"stalk",
+"stall",
+"stamp",
+"stan",
+"stance",
+"stand",
+"stank",
+"staph",
+"star",
+"stare",
+"stark",
+"starr",
+"start",
+"stash",
+"state",
+"statue",
+"stave",
+"stay",
+"stead",
+"steak",
+"steal",
+"steam",
+"steed",
+"steel",
+"steele",
+"steen",
+"steep",
+"steer",
+"stein",
+"stella",
+"stem",
+"step",
+"stern",
+"steve",
+"stew",
+"stick",
+"stiff",
+"stile",
+"still",
+"stilt",
+"sting",
+"stingy",
+"stink",
+"stint",
+"stir",
+"stock",
+"stoic",
+"stoke",
+"stole",
+"stomp",
+"stone",
+"stony",
+"stood",
+"stool",
+"stoop",
+"stop",
+"store",
+"storey",
+"stork",
+"storm",
+"story",
+"stout",
+"stove",
+"stow",
+"strafe",
+"strap",
+"straw",
+"stray",
+"strewn",
+"strip",
+"stroll",
+"strom",
+"strop",
+"strum",
+"strut",
+"stu",
+"stuart",
+"stub",
+"stuck",
+"stud",
+"study",
+"stuff",
+"stuffy",
+"stump",
+"stun",
+"stung",
+"stunk",
+"stunt",
+"sturm",
+"style",
+"styli",
+"styx",
+"su",
+"suave",
+"sub",
+"subtly",
+"such",
+"suck",
+"sud",
+"sudan",
+"suds",
+"sue",
+"suey",
+"suez",
+"sugar",
+"suit",
+"suite",
+"sulfa",
+"sulk",
+"sulky",
+"sully",
+"sultry",
+"sum",
+"sumac",
+"summon",
+"sun",
+"sung",
+"sunk",
+"sunny",
+"sunset",
+"suny",
+"sup",
+"super",
+"supra",
+"sure",
+"surf",
+"surge",
+"sus",
+"susan",
+"sushi",
+"susie",
+"sutton",
+"sv",
+"sw",
+"swab",
+"swag",
+"swain",
+"swam",
+"swami",
+"swamp",
+"swampy",
+"swan",
+"swank",
+"swap",
+"swarm",
+"swart",
+"swat",
+"swath",
+"sway",
+"swear",
+"sweat",
+"sweaty",
+"swede",
+"sweep",
+"sweet",
+"swell",
+"swelt",
+"swept",
+"swift",
+"swig",
+"swim",
+"swine",
+"swing",
+"swipe",
+"swirl",
+"swish",
+"swiss",
+"swoop",
+"sword",
+"swore",
+"sworn",
+"swum",
+"swung",
+"sx",
+"sy",
+"sybil",
+"sykes",
+"sylow",
+"sylvan",
+"synge",
+"synod",
+"syria",
+"syrup",
+"sz",
+"t",
+"t's",
+"t2",
+"t3",
+"t4",
+"t5",
+"t6",
+"t7",
+"t8",
+"t9",
+"ta",
+"tab",
+"table",
+"taboo",
+"tabu",
+"tabula",
+"tacit",
+"tack",
+"tacky",
+"tacoma",
+"tact",
+"tad",
+"taffy",
+"taft",
+"tag",
+"tahoe",
+"tail",
+"taint",
+"take",
+"taken",
+"talc",
+"tale",
+"talk",
+"talky",
+"tall",
+"tallow",
+"tally",
+"talon",
+"talus",
+"tam",
+"tame",
+"tamp",
+"tampa",
+"tan",
+"tang",
+"tango",
+"tangy",
+"tanh",
+"tank",
+"tansy",
+"tanya",
+"tao",
+"taos",
+"tap",
+"tapa",
+"tape",
+"taper",
+"tapir",
+"tapis",
+"tappa",
+"tar",
+"tara",
+"tardy",
+"tariff",
+"tarry",
+"tart",
+"task",
+"tass",
+"taste",
+"tasty",
+"tat",
+"tate",
+"tater",
+"tattle",
+"tatty",
+"tau",
+"taunt",
+"taut",
+"tavern",
+"tawny",
+"tax",
+"taxi",
+"tb",
+"tc",
+"td",
+"te",
+"tea",
+"teach",
+"teal",
+"team",
+"tear",
+"tease",
+"teat",
+"tech",
+"tecum",
+"ted",
+"teddy",
+"tee",
+"teem",
+"teen",
+"teensy",
+"teet",
+"teeth",
+"telex",
+"tell",
+"tempo",
+"tempt",
+"ten",
+"tend",
+"tenet",
+"tenney",
+"tenon",
+"tenor",
+"tense",
+"tensor",
+"tent",
+"tenth",
+"tepee",
+"tepid",
+"term",
+"tern",
+"terra",
+"terre",
+"terry",
+"terse",
+"tess",
+"test",
+"testy",
+"tete",
+"texan",
+"texas",
+"text",
+"tf",
+"tg",
+"th",
+"thai",
+"than",
+"thank",
+"that",
+"thaw",
+"the",
+"thea",
+"thee",
+"theft",
+"their",
+"them",
+"theme",
+"then",
+"there",
+"these",
+"theta",
+"they",
+"thick",
+"thief",
+"thigh",
+"thin",
+"thine",
+"thing",
+"think",
+"third",
+"this",
+"thong",
+"thor",
+"thorn",
+"thorny",
+"those",
+"thou",
+"thread",
+"three",
+"threw",
+"throb",
+"throes",
+"throw",
+"thrum",
+"thud",
+"thug",
+"thule",
+"thumb",
+"thump",
+"thus",
+"thy",
+"thyme",
+"ti",
+"tiber",
+"tibet",
+"tibia",
+"tic",
+"tick",
+"ticket",
+"tid",
+"tidal",
+"tidbit",
+"tide",
+"tidy",
+"tie",
+"tied",
+"tier",
+"tift",
+"tiger",
+"tight",
+"til",
+"tilde",
+"tile",
+"till",
+"tilt",
+"tilth",
+"tim",
+"time",
+"timex",
+"timid",
+"timon",
+"tin",
+"tina",
+"tine",
+"tinge",
+"tint",
+"tiny",
+"tioga",
+"tip",
+"tipoff",
+"tippy",
+"tipsy",
+"tire",
+"tit",
+"titan",
+"tithe",
+"title",
+"titus",
+"tj",
+"tk",
+"tl",
+"tm",
+"tn",
+"tnt",
+"to",
+"toad",
+"toady",
+"toast",
+"toby",
+"today",
+"todd",
+"toe",
+"tofu",
+"tog",
+"togo",
+"togs",
+"toil",
+"toilet",
+"token",
+"tokyo",
+"told",
+"toll",
+"tom",
+"tomb",
+"tome",
+"tommy",
+"ton",
+"tonal",
+"tone",
+"tong",
+"toni",
+"tonic",
+"tonk",
+"tonsil",
+"tony",
+"too",
+"took",
+"tool",
+"toot",
+"tooth",
+"top",
+"topaz",
+"topic",
+"topple",
+"topsy",
+"tor",
+"torah",
+"torch",
+"tore",
+"tori",
+"torn",
+"torr",
+"torso",
+"tort",
+"torus",
+"tory",
+"toss",
+"tot",
+"total",
+"tote",
+"totem",
+"touch",
+"tough",
+"tour",
+"tout",
+"tow",
+"towel",
+"tower",
+"town",
+"toxic",
+"toxin",
+"toy",
+"tp",
+"tq",
+"tr",
+"trace",
+"track",
+"tract",
+"tracy",
+"trade",
+"trag",
+"trail",
+"train",
+"trait",
+"tram",
+"tramp",
+"trap",
+"trash",
+"trawl",
+"tray",
+"tread",
+"treat",
+"treble",
+"tree",
+"trek",
+"trench",
+"trend",
+"tress",
+"triad",
+"trial",
+"tribe",
+"trick",
+"tried",
+"trig",
+"trill",
+"trim",
+"trio",
+"trip",
+"tripe",
+"trite",
+"triton",
+"trod",
+"troll",
+"troop",
+"trot",
+"trout",
+"troy",
+"truce",
+"truck",
+"trudge",
+"trudy",
+"TRUE",
+"truly",
+"trump",
+"trunk",
+"truss",
+"trust",
+"truth",
+"trw",
+"try",
+"ts",
+"tsar",
+"tt",
+"ttl",
+"ttt",
+"tttt",
+"tty",
+"tu",
+"tub",
+"tuba",
+"tube",
+"tuck",
+"tudor",
+"tuff",
+"tuft",
+"tug",
+"tulane",
+"tulip",
+"tulle",
+"tulsa",
+"tum",
+"tun",
+"tuna",
+"tune",
+"tung",
+"tunic",
+"tunis",
+"tunnel",
+"tuple",
+"turf",
+"turin",
+"turk",
+"turn",
+"turvy",
+"tusk",
+"tussle",
+"tutor",
+"tutu",
+"tuv",
+"tv",
+"tva",
+"tw",
+"twa",
+"twain",
+"tweak",
+"tweed",
+"twice",
+"twig",
+"twill",
+"twin",
+"twine",
+"twirl",
+"twist",
+"twisty",
+"twit",
+"two",
+"twx",
+"tx",
+"ty",
+"tyburn",
+"tying",
+"tyler",
+"type",
+"typic",
+"typo",
+"tyson",
+"tz",
+"u",
+"u's",
+"u2",
+"u3",
+"u4",
+"u5",
+"u6",
+"u7",
+"u8",
+"u9",
+"ua",
+"ub",
+"uc",
+"ucla",
+"ud",
+"ue",
+"uf",
+"ug",
+"ugh",
+"ugly",
+"uh",
+"ui",
+"uj",
+"uk",
+"ul",
+"ulan",
+"ulcer",
+"ultra",
+"um",
+"umber",
+"umbra",
+"umpire",
+"un",
+"unary",
+"uncle",
+"under",
+"unify",
+"union",
+"unit",
+"unite",
+"unity",
+"unix",
+"until",
+"uo",
+"up",
+"upend",
+"uphold",
+"upon",
+"upper",
+"uproar",
+"upset",
+"uptake",
+"upton",
+"uq",
+"ur",
+"urban",
+"urbane",
+"urea",
+"urge",
+"uri",
+"urine",
+"uris",
+"urn",
+"ursa",
+"us",
+"usa",
+"usaf",
+"usage",
+"usc",
+"usda",
+"use",
+"useful",
+"usgs",
+"usher",
+"usia",
+"usn",
+"usps",
+"ussr",
+"usual",
+"usurp",
+"usury",
+"ut",
+"utah",
+"utica",
+"utile",
+"utmost",
+"utter",
+"uu",
+"uuu",
+"uuuu",
+"uv",
+"uvw",
+"uw",
+"ux",
+"uy",
+"uz",
+"v",
+"v's",
+"v2",
+"v3",
+"v4",
+"v5",
+"v6",
+"v7",
+"v8",
+"v9",
+"va",
+"vacua",
+"vacuo",
+"vade",
+"vaduz",
+"vague",
+"vail",
+"vain",
+"vale",
+"valet",
+"valeur",
+"valid",
+"value",
+"valve",
+"vamp",
+"van",
+"vance",
+"vane",
+"vary",
+"vase",
+"vast",
+"vat",
+"vault",
+"vb",
+"vc",
+"vd",
+"ve",
+"veal",
+"veda",
+"vee",
+"veer",
+"veery",
+"vega",
+"veil",
+"vein",
+"velar",
+"veldt",
+"vella",
+"vellum",
+"venal",
+"vend",
+"venial",
+"venom",
+"vent",
+"venus",
+"vera",
+"verb",
+"verde",
+"verdi",
+"verge",
+"verity",
+"verna",
+"verne",
+"versa",
+"verse",
+"verve",
+"very",
+"vessel",
+"vest",
+"vet",
+"vetch",
+"veto",
+"vex",
+"vf",
+"vg",
+"vh",
+"vi",
+"via",
+"vial",
+"vicar",
+"vice",
+"vichy",
+"vicky",
+"vida",
+"video",
+"vie",
+"viet",
+"view",
+"vigil",
+"vii",
+"viii",
+"vile",
+"villa",
+"vine",
+"vinyl",
+"viola",
+"violet",
+"virgil",
+"virgo",
+"virus",
+"vis",
+"visa",
+"vise",
+"visit",
+"visor",
+"vista",
+"vita",
+"vitae",
+"vital",
+"vito",
+"vitro",
+"viva",
+"vivian",
+"vivid",
+"vivo",
+"vixen",
+"viz",
+"vj",
+"vk",
+"vl",
+"vm",
+"vn",
+"vo",
+"vocal",
+"vogel",
+"vogue",
+"voice",
+"void",
+"volt",
+"volta",
+"volvo",
+"vomit",
+"von",
+"voss",
+"vote",
+"vouch",
+"vow",
+"vowel",
+"vp",
+"vq",
+"vr",
+"vs",
+"vt",
+"vu",
+"vulcan",
+"vv",
+"vvv",
+"vvvv",
+"vw",
+"vx",
+"vy",
+"vying",
+"vz",
+"w",
+"w's",
+"w2",
+"w3",
+"w4",
+"w5",
+"w6",
+"w7",
+"w8",
+"w9",
+"wa",
+"waals",
+"wac",
+"wack",
+"wacke",
+"wacky",
+"waco",
+"wad",
+"wade",
+"wadi",
+"wafer",
+"wag",
+"wage",
+"waggle",
+"wah",
+"wahl",
+"wail",
+"waist",
+"wait",
+"waite",
+"waive",
+"wake",
+"waken",
+"waldo",
+"wale",
+"walk",
+"walkie",
+"wall",
+"walls",
+"wally",
+"walsh",
+"walt",
+"walton",
+"waltz",
+"wan",
+"wand",
+"wane",
+"wang",
+"want",
+"war",
+"ward",
+"ware",
+"warm",
+"warmth",
+"warn",
+"warp",
+"warren",
+"wart",
+"warty",
+"wary",
+"was",
+"wash",
+"washy",
+"wasp",
+"wast",
+"waste",
+"watch",
+"water",
+"watt",
+"watts",
+"wave",
+"wavy",
+"wax",
+"waxen",
+"waxy",
+"way",
+"wayne",
+"wb",
+"wc",
+"wd",
+"we",
+"we'd",
+"we'll",
+"we're",
+"we've",
+"weak",
+"weal",
+"wealth",
+"wean",
+"wear",
+"weary",
+"weave",
+"web",
+"webb",
+"weber",
+"weco",
+"wed",
+"wedge",
+"wee",
+"weed",
+"weedy",
+"week",
+"weeks",
+"weep",
+"wehr",
+"wei",
+"weigh",
+"weir",
+"weird",
+"weiss",
+"welch",
+"weld",
+"well",
+"wells",
+"welsh",
+"welt",
+"wendy",
+"went",
+"wept",
+"were",
+"wert",
+"west",
+"wet",
+"wf",
+"wg",
+"wh",
+"whack",
+"whale",
+"wham",
+"wharf",
+"what",
+"wheat",
+"whee",
+"wheel",
+"whelk",
+"whelm",
+"whelp",
+"when",
+"where",
+"whet",
+"which",
+"whiff",
+"whig",
+"while",
+"whim",
+"whine",
+"whinny",
+"whip",
+"whir",
+"whirl",
+"whisk",
+"whit",
+"white",
+"whiz",
+"who",
+"who'd",
+"whoa",
+"whole",
+"whom",
+"whoop",
+"whoosh",
+"whop",
+"whose",
+"whup",
+"why",
+"wi",
+"wick",
+"wide",
+"widen",
+"widow",
+"width",
+"wield",
+"wier",
+"wife",
+"wig",
+"wild",
+"wile",
+"wiley",
+"wilkes",
+"will",
+"willa",
+"wills",
+"wilma",
+"wilt",
+"wily",
+"win",
+"wince",
+"winch",
+"wind",
+"windy",
+"wine",
+"wing",
+"wink",
+"winnie",
+"wino",
+"winter",
+"winy",
+"wipe",
+"wire",
+"wiry",
+"wise",
+"wish",
+"wishy",
+"wisp",
+"wispy",
+"wit",
+"witch",
+"with",
+"withe",
+"withy",
+"witt",
+"witty",
+"wive",
+"wj",
+"wk",
+"wl",
+"wm",
+"wn",
+"wo",
+"woe",
+"wok",
+"woke",
+"wold",
+"wolf",
+"wolfe",
+"wolff",
+"wolve",
+"woman",
+"womb",
+"women",
+"won",
+"won't",
+"wonder",
+"wong",
+"wont",
+"woo",
+"wood",
+"woods",
+"woody",
+"wool",
+"woozy",
+"word",
+"wordy",
+"wore",
+"work",
+"world",
+"worm",
+"wormy",
+"worn",
+"worry",
+"worse",
+"worst",
+"worth",
+"wotan",
+"would",
+"wound",
+"wove",
+"woven",
+"wow",
+"wp",
+"wq",
+"wr",
+"wrack",
+"wrap",
+"wrath",
+"wreak",
+"wreck",
+"wrest",
+"wring",
+"wrist",
+"writ",
+"write",
+"writhe",
+"wrong",
+"wrote",
+"wry",
+"ws",
+"wt",
+"wu",
+"wuhan",
+"wv",
+"ww",
+"www",
+"wwww",
+"wx",
+"wxy",
+"wy",
+"wyatt",
+"wyeth",
+"wylie",
+"wyman",
+"wyner",
+"wynn",
+"wz",
+"x",
+"x's",
+"x2",
+"x3",
+"x4",
+"x5",
+"x6",
+"x7",
+"x8",
+"x9",
+"xa",
+"xb",
+"xc",
+"xd",
+"xe",
+"xenon",
+"xerox",
+"xf",
+"xg",
+"xh",
+"xi",
+"xj",
+"xk",
+"xl",
+"xm",
+"xn",
+"xo",
+"xp",
+"xq",
+"xr",
+"xs",
+"xt",
+"xu",
+"xv",
+"xw",
+"xx",
+"xxx",
+"xxxx",
+"xy",
+"xylem",
+"xyz",
+"xz",
+"y",
+"y's",
+"y2",
+"y3",
+"y4",
+"y5",
+"y6",
+"y7",
+"y8",
+"y9",
+"ya",
+"yacht",
+"yah",
+"yak",
+"yale",
+"yalta",
+"yam",
+"yamaha",
+"yang",
+"yank",
+"yap",
+"yaqui",
+"yard",
+"yarn",
+"yates",
+"yaw",
+"yawl",
+"yawn",
+"yb",
+"yc",
+"yd",
+"ye",
+"yea",
+"yeah",
+"year",
+"yearn",
+"yeast",
+"yeasty",
+"yeats",
+"yell",
+"yelp",
+"yemen",
+"yen",
+"yet",
+"yf",
+"yg",
+"yh",
+"yi",
+"yield",
+"yin",
+"yip",
+"yj",
+"yk",
+"yl",
+"ym",
+"ymca",
+"yn",
+"yo",
+"yodel",
+"yoder",
+"yoga",
+"yogi",
+"yoke",
+"yokel",
+"yolk",
+"yon",
+"yond",
+"yore",
+"york",
+"yost",
+"you",
+"you'd",
+"young",
+"your",
+"youth",
+"yow",
+"yp",
+"yq",
+"yr",
+"ys",
+"yt",
+"yu",
+"yucca",
+"yuck",
+"yuh",
+"yuki",
+"yukon",
+"yule",
+"yv",
+"yves",
+"yw",
+"ywca",
+"yx",
+"yy",
+"yyy",
+"yyyy",
+"yz",
+"z",
+"z's",
+"z2",
+"z3",
+"z4",
+"z5",
+"z6",
+"z7",
+"z8",
+"z9",
+"za",
+"zag",
+"zaire",
+"zan",
+"zap",
+"zazen",
+"zb",
+"zc",
+"zd",
+"ze",
+"zeal",
+"zealot",
+"zebra",
+"zeiss",
+"zen",
+"zero",
+"zest",
+"zesty",
+"zeta",
+"zeus",
+"zf",
+"zg",
+"zh",
+"zi",
+"zig",
+"zilch",
+"zinc",
+"zing",
+"zion",
+"zip",
+"zj",
+"zk",
+"zl",
+"zloty",
+"zm",
+"zn",
+"zo",
+"zoe",
+"zomba",
+"zone",
+"zoo",
+"zoom",
+"zorn",
+"zp",
+"zq",
+"zr",
+"zs",
+"zt",
+"zu",
+"zurich",
+"zv",
+"zw",
+"zx",
+"zy",
+"zz",
+"zzz",
+"zzzz",
+"!",
+"!!",
+"""""",
+"#",
+"##",
+"$",
+"$$",
+"%",
+"%%",
+"&",
+"(",
+"()",
+")",
+"*",
+"**",
+"+",
+"-",
+"0",
+"1",
+"10",
+"100",
+"1000",
+"100th",
+"101",
+"101st",
+"10th",
+"11",
+"111",
+"1111",
+"11th",
+"12",
+"123",
+"1234",
+"12th",
+"13",
+"13th",
+"14",
+"1492",
+"14th",
+"15",
+"1500",
+"15th",
+"16",
+"1600",
+"16th",
+"17",
+"1700",
+"1776",
+"17th",
+"18",
+"1800",
+"1812",
+"18th",
+"19",
+"1900",
+"1910",
+"1920",
+"1925",
+"1930",
+"1935",
+"1940",
+"1945",
+"1950",
+"1955",
+"1960",
+"1965",
+"1970",
+"1975",
+"1980",
+"1985",
+"1990",
+"1991",
+"1992",
+"1993",
+"1994",
+"1995",
+"1996",
+"1997",
+"19th",
+"1st",
+"2",
+"20",
+"200",
+"2000",
+"2001",
+"2020",
+"20th",
+"21",
+"21st",
+"22",
+"222",
+"2222",
+"22nd",
+"23",
+"234",
+"2345",
+"23rd",
+"24",
+"2468",
+"24th",
+"25",
+"25th",
+"26",
+"26th",
+"27",
+"27th",
+"28",
+"28th",
+"29",
+"29th",
+"2a",
+"2b",
+"2c",
+"2d",
+"2e",
+"2f",
+"2g",
+"2h",
+"2i",
+"2j",
+"2k",
+"2l",
+"2m",
+"2n",
+"2nd",
+"2o",
+"2p",
+"2q",
+"2r",
+"2s",
+"2t",
+"2u",
+"2v",
+"2w",
+"2x",
+"2y",
+"2z",
+"3",
+"30",
+"300",
+"3000",
+"30th",
+"31",
+"31st",
+"32",
+"32nd",
+"33",
+"333",
+"3333",
+"33rd",
+"34",
+"345",
+"3456",
+"34th",
+"35",
+"35th",
+"36",
+"36th",
+"37",
+"37th",
+"38",
+"38th",
+"39",
+"39th",
+"3a",
+"3b",
+"3c",
+"3d",
+"3e",
+"3f",
+"3g",
+"3h",
+"3i",
+"3j",
+"3k",
+"3l",
+"3m",
+"3n",
+"3o",
+"3p",
+"3q",
+"3r",
+"3rd",
+"3s",
+"3t",
+"3u",
+"3v",
+"3w",
+"3x",
+"3y",
+"3z",
+"4",
+"40",
+"400",
+"4000",
+"40th",
+"41",
+"41st",
+"42",
+"42nd",
+"43",
+"4321",
+"43rd",
+"44",
+"444",
+"4444",
+"44th",
+"45",
+"456",
+"4567",
+"45th",
+"46",
+"46th",
+"47",
+"47th",
+"48",
+"48th",
+"49",
+"49th",
+"4a",
+"4b",
+"4c",
+"4d",
+"4e",
+"4f",
+"4g",
+"4h",
+"4i",
+"4j",
+"4k",
+"4l",
+"4m",
+"4n",
+"4o",
+"4p",
+"4q",
+"4r",
+"4s",
+"4t",
+"4th",
+"4u",
+"4v",
+"4w",
+"4x",
+"4y",
+"4z",
+"5",
+"50",
+"500",
+"5000",
+"50th",
+"51",
+"51st",
+"52",
+"52nd",
+"53",
+"53rd",
+"54",
+"54th",
+"55",
+"555",
+"5555",
+"55th",
+"56",
+"567",
+"5678",
+"56th",
+"57",
+"57th",
+"58",
+"58th",
+"59",
+"59th",
+"5a",
+"5b",
+"5c",
+"5d",
+"5e",
+"5f",
+"5g",
+"5h",
+"5i",
+"5j",
+"5k",
+"5l",
+"5m",
+"5n",
+"5o",
+"5p",
+"5q",
+"5r",
+"5s",
+"5t",
+"5th",
+"5u",
+"5v",
+"5w",
+"5x",
+"5y",
+"5z",
+"6",
+"60",
+"600",
+"6000",
+"60th",
+"61",
+"61st",
+"62",
+"62nd",
+"63",
+"63rd",
+"64",
+"65",
+"65th",
+"66",
+"666",
+"6666",
+"66th",
+"67",
+"678",
+"6789",
+"67th",
+"68",
+"68th",
+"69",
+"69th",
+"6a",
+"6b",
+"6c",
+"6d",
+"6e",
+"6f",
+"6g",
+"6h",
+"6i",
+"6j",
+"6k",
+"6l",
+"6m",
+"6n",
+"6o",
+"6p",
+"6q",
+"6r",
+"6s",
+"6t",
+"6th",
+"6u",
+"6v",
+"6w",
+"6x",
+"6y",
+"6z",
+"7",
+"70",
+"700",
+"7000",
+"70th",
+"71",
+"71st",
+"72",
+"72nd",
+"73",
+"73rd",
+"74",
+"74th",
+"75",
+"75th",
+"76",
+"76th",
+"77",
+"777",
+"7777",
+"77th",
+"78",
+"789",
+"78th",
+"79",
+"79th",
+"7a",
+"7b",
+"7c",
+"7d",
+"7e",
+"7f",
+"7g",
+"7h",
+"7i",
+"7j",
+"7k",
+"7l",
+"7m",
+"7n",
+"7o",
+"7p",
+"7q",
+"7r",
+"7s",
+"7t",
+"7th",
+"7u",
+"7v",
+"7w",
+"7x",
+"7y",
+"7z",
+"8",
+"80",
+"800",
+"8000",
+"80th",
+"81",
+"81st",
+"82",
+"82nd",
+"83",
+"83rd",
+"84",
+"84th",
+"85",
+"85th",
+"86",
+"86th",
+"87",
+"87th",
+"88",
+"888",
+"8888",
+"88th",
+"89",
+"89th",
+"8a",
+"8b",
+"8c",
+"8d",
+"8e",
+"8f",
+"8g",
+"8h",
+"8i",
+"8j",
+"8k",
+"8l",
+"8m",
+"8n",
+"8o",
+"8p",
+"8q",
+"8r",
+"8s",
+"8t",
+"8th",
+"8u",
+"8v",
+"8w",
+"8x",
+"8y",
+"8z",
+"9",
+"90",
+"900",
+"9000",
+"90th",
+"91",
+"91st",
+"92",
+"92nd",
+"93",
+"93rd",
+"94",
+"94th",
+"95",
+"95th",
+"96",
+"96th",
+"97",
+"97th",
+"98",
+"9876",
+"98th",
+"99",
+"999",
+"9999",
+"99th",
+"9a",
+"9b",
+"9c",
+"9d",
+"9e",
+"9f",
+"9g",
+"9h",
+"9i",
+"9j",
+"9k",
+"9l",
+"9m",
+"9n",
+"9o",
+"9p",
+"9q",
+"9r",
+"9s",
+"9t",
+"9th",
+"9u",
+"9v",
+"9w",
+"9x",
+"9y",
+"9z",
+":",
+";",
+"=",
+"?",
+"??",
+"@" };
+
+const char *getDiceWd(unsigned int n) {
+ return Dicewds8k[n & 0X1fff];
+}
diff --git a/exceptions.h b/exceptions.h
new file mode 100644
index 0000000..773c574
--- /dev/null
+++ b/exceptions.h
@@ -0,0 +1,43 @@
+/*
+ exceptions.h - exception declarations for cexcept.h
+ (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef EXCEPTIONS_H__
+#define EXCEPTIONS_H__
+
+#include "cexcept.h"
+
+/* The simplest approach is to have all exceptions defined in one place. */
+enum exception_code {
+ /* general exceptions */
+ no_exception = 0, /* used to exit the Try block */
+ out_of_memory_exception,
+ system_call_failed_exception,
+
+ /* library exceptions */
+ lib_crypto_exception
+};
+
+define_exception_type(enum exception_code);
+extern struct exception_context *the_exception_context;
+
+#endif /* EXCEPTIONS_H__ */
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..cb3b0e0
--- /dev/null
+++ b/main.c
@@ -0,0 +1,222 @@
+/*
+ main.c - main program
+ (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+#include "secure_memory.h"
+#include "secure_random.h"
+#include "pwgen.h"
+#include "exceptions.h"
+
+static char rcsid[] = "$Id: main.c 1 2005-11-13 20:23:40Z zvrba $";
+
+static struct exception_context exception_context;
+struct exception_context *the_exception_context = &exception_context;
+
+static void exit_cleanup(void)
+{
+ SRNG_destroy((struct SRNG_st*)G_secure_memory->random_state);
+ secure_memory_destroy();
+}
+
+static void usage(const char *argv0)
+{
+ fprintf(stderr, "USAGE: %s <-p[e] | -A[adhsy] | -r | -s[e]> N\n", argv0);
+ fprintf(stderr,
+ "\nPASSPHRASE of N words from Diceware dictionary\n"
+ " -p generate passphrase\n"
+ " -pe generate enhanced (with symbols) passphrase\n"
+ "\nSKEY PASSWORD of N words from S/Key dictionary\n"
+ " -s generate passphrase\n"
+ " -se generate enhanced (with symbols) passphrase\n"
+ "\nASCII RANDOM of N elements (at least one option MUST be present)\n"
+ " -A Each letter adds the following random elements in output:\n"
+ " a alphanumeric characters\n"
+ " d decimal digits\n"
+ " h hexadecimal digits\n"
+ " s special characters\n"
+ " y 3-4 letter syllables\n"
+ "\nRAW RANDOM\n"
+ " -r output BASE64 encoded string of N random BITS\n"
+ " -k output koremutake encoding of N random BITS\n");
+ exit(1);
+}
+
+static unsigned int get_allowed_characters(const char *p)
+{
+ unsigned int characters = 0;
+
+ while(*p) {
+ switch(*p) {
+ case 'a':
+ characters |= chr_alphanumeric;
+ break;
+ case 'd':
+ characters |= chr_dec_digits;
+ break;
+ case 'h':
+ characters |= chr_hex_digits;
+ break;
+ case 's':
+ characters |= chr_special;
+ break;
+ case 'y':
+ characters |= chr_syllables;
+ break;
+ default:
+ return 0;
+ }
+ ++p;
+ }
+
+ /* filter out some combinations for correct entropy estimation */
+ if(characters & chr_alphanumeric)
+ characters &= ~(chr_dec_digits | chr_hex_digits);
+ if(characters & chr_hex_digits)
+ characters &= ~chr_dec_digits;
+ if((characters & chr_syllables)
+ && (characters & (chr_alphanumeric | chr_dec_digits | chr_hex_digits))) {
+ characters &= ~(chr_alphanumeric | chr_dec_digits | chr_hex_digits);
+ characters |= chr_dec_digits;
+ }
+
+ return characters;
+}
+
+int main(int argc, char **argv)
+{
+ const char *getDiceWd(unsigned int);
+ const char *getSkeyWd(unsigned int);
+ unsigned int n;
+ unsigned int srng_state_len;
+ float entropy;
+ enum exception_code exception;
+ int retval = 0;
+
+ init_exception_context(&exception_context);
+
+ if(argc != 3)
+ usage(argv[0]);
+
+ n = atoi(argv[2]);
+ if(n < 1) {
+ fprintf(stderr, "ERROR: N must be an integer > 0\n");
+ usage(argv[0]);
+ }
+
+ srng_state_len = SRNG_init(NULL);
+ if(srng_state_len > MAX_RANDOM_STATE_SIZE) {
+ fprintf(stderr,
+ "FATAL: too small MAX_RANDOM_STATE_SIZE "
+ "(must be at least %u)\n", srng_state_len);
+ return 1;
+ }
+
+ Try {
+ secure_memory_init();
+ SRNG_init((struct SRNG_st*)G_secure_memory->random_state);
+
+ if(atexit(exit_cleanup) < 0) {
+ fprintf(stderr, "FATAL: can't register cleanup handlers: \n");
+ perror("atexit");
+ return 1;
+ }
+
+ if(!strcmp(argv[1], "-p"))
+ entropy = pwgen_diceware(
+ (struct SRNG_st*)G_secure_memory->random_state, n, 0,
+ getDiceWd, 8192, G_secure_memory->random_numbers,
+ G_secure_memory->passphrase);
+ else if(!strcmp(argv[1], "-pe"))
+ entropy = pwgen_diceware(
+ (struct SRNG_st*)G_secure_memory->random_state, n, 1,
+ getDiceWd, 8192, G_secure_memory->random_numbers,
+ G_secure_memory->passphrase);
+ else if(!strcmp(argv[1], "-r"))
+ entropy = pwgen_raw(
+ (struct SRNG_st*)G_secure_memory->random_state, n,
+ G_secure_memory->random_numbers,
+ G_secure_memory->passphrase);
+ else if(!strcmp(argv[1], "-k"))
+ entropy = pwgen_koremutake(
+ (struct SRNG_st*)G_secure_memory->random_state, n,
+ G_secure_memory->random_numbers,
+ G_secure_memory->passphrase);
+ else if(!strcmp(argv[1], "-s"))
+ entropy = pwgen_diceware(
+ (struct SRNG_st*)G_secure_memory->random_state, n, 0,
+ getSkeyWd, 2048, G_secure_memory->random_numbers,
+ G_secure_memory->passphrase);
+ else if(!strcmp(argv[1], "-se"))
+ entropy = pwgen_diceware(
+ (struct SRNG_st*)G_secure_memory->random_state, n, 1,
+ getSkeyWd, 2048, G_secure_memory->random_numbers,
+ G_secure_memory->passphrase);
+ else if(!strncmp(argv[1], "-A", 2)) {
+ unsigned int characters = get_allowed_characters(argv[1]+2);
+
+ if(!characters)
+ usage(argv[0]);
+ entropy = pwgen_ascii(
+ (struct SRNG_st*)G_secure_memory->random_state, n,
+ characters, G_secure_memory->random_numbers,
+ G_secure_memory->passphrase);
+ } else {
+ usage(argv[0]);
+ }
+ } Catch(exception) {
+ switch(exception) {
+ case out_of_memory_exception:
+ fprintf(stderr, "FATAL: out of memory.\n");
+ retval = 1;
+ break;
+ case lib_crypto_exception:
+ fprintf(stderr, "FATAL: crypto library error.\n");
+ retval = 1;
+ break;
+ case system_call_failed_exception:
+ fprintf(stderr, "FATAL: system call failed.\n");
+ retval = 1;
+ break;
+ default:
+ fprintf(stderr, "FATAL: unhandled exception %u.\n", exception);
+ retval = 1;
+ }
+ }
+
+ if(!retval) {
+ printf("----------------\n");
+ /*
+ * SECURITY NOTE
+ * I have no idea how printf(3) is implemented and it just MIGHT copy
+ * some sensitive data to its own stack.
+ */
+ printf("%s ;ENTROPY=%.2f bits\n", G_secure_memory->passphrase,
+ entropy);
+ printf("----------------\n");
+ }
+ return retval;
+}
diff --git a/pwgen.c b/pwgen.c
new file mode 100644
index 0000000..64cc180
--- /dev/null
+++ b/pwgen.c
@@ -0,0 +1,313 @@
+/*
+ pwgen.c - actual password generation
+ (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "secure_random.h"
+#include "pwgen.h"
+#include "exceptions.h"
+
+static char rcsid[] = "$Id: pwgen.c 1 2005-11-13 20:23:40Z zvrba $";
+
+/**
+ * @file
+ * This is intended to be the UI-independent part of password generation.
+ *
+ * @note On the programming style in this code: I'm aware that strcat()
+ * in a loop has quadratic performance, but here I just don't care and it
+ * makes my life easier.
+ */
+
+/******************************************************************************
+ * Tables and entropy constants.
+ *****************************************************************************/
+static const char *t_alphanumeric[36] = {
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
+ "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X",
+ "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
+};
+
+static const char *t_dec_digits[36] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const char *t_hex_digits[36] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F",
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F",
+ NULL, NULL, NULL, NULL
+};
+
+static const char *t_special[36] = {
+ "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_",
+ "+", "=", "[", "]", "{", "}", ";", ":", "'", "\"", ",", ".",
+ "<", ">", "/", "?", "`", "~", "|", "\\", "--", "==", "..", "//"
+};
+
+static const char *t_syllables_lm[36] = {
+ "B", "C", "D", "F", "G", "H",
+ "J", "K", "L", "M", "N", "P",
+ "QU", "R", "S", "T", "V", "W",
+ "X", "Z", "CH", "CR", "FR", "ND",
+ "NG", "NK", "NT", "PH", "PR", "RD",
+ "SH", "SL", "SP", "ST", "TH", "TR"
+};
+
+static const char *t_syllables_r[6] = {
+ "A", "E", "I", "O", "U", "Y"
+};
+
+static const char *koremutake_syllables[128] = {
+ "BA", "BE", "BI", "BO", "BU", "BY", "DA", "DE",
+ "DI", "DO", "DU", "DY", "FA", "FE", "FI", "FO",
+ "FU", "FY", "GA", "GE", "GI", "GO", "GU", "GY",
+ "HA", "HE", "HI", "HO", "HU", "HY", "JA", "JE",
+ "JI", "JO", "JU", "JY", "KA", "KE", "KI", "KO",
+ "KU", "KY", "LA", "LE", "LI", "LO", "LU", "LY",
+ "MA", "ME", "MI", "MO", "MU", "MY", "NA", "NE",
+ "NI", "NO", "NU", "NY", "PA", "PE", "PI", "PO",
+ "PU", "PY", "RA", "RE", "RI", "RO", "RU", "RY",
+ "SA", "SE", "SI", "SO", "SU", "SY", "TA", "TE",
+ "TI", "TO", "TU", "TY", "VA", "VE", "VI", "VO",
+ "VU", "VY", "BRA", "BRE", "BRI", "BRO", "BRU", "BRY",
+ "DRA", "DRE", "DRI", "DRO", "DRU", "DRY", "FRA", "FRE",
+ "FRI", "FRO", "FRU", "FRY", "GRA", "GRE", "GRI", "GRO",
+ "GRU", "GRY", "PRA", "PRE", "PRI", "PRO", "PRU", "PRY",
+ "STA", "STE", "STI", "STO", "STU", "STY", "TRA", "TRE"
+};
+
+#define N_CHARACTER_CLASSES 5
+static struct {
+ enum character_classes chr; /* character class */
+ const char **dice12; /* first two dice throws */
+ const char **dice3; /* possibly 3rd dice or NULL */
+ float entropy; /* entropy per element */
+} character_classes[N_CHARACTER_CLASSES] = {
+ { chr_alphanumeric, t_alphanumeric, NULL, 5.17 },
+ { chr_dec_digits, t_dec_digits, NULL, 3.32 },
+ { chr_hex_digits, t_hex_digits, NULL, 4 },
+ { chr_special, t_special, NULL, 5.17 },
+ { chr_syllables, t_syllables_lm, t_syllables_r, 7.75 }
+};
+
+/* This is ONLY for passphrase enhancement. */
+static const char t_passphrase_enh[36] = {
+ '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_',
+ '+', '=', '[', ']', '{', '}', ';', ':', '\'', '\'', ',', '.',
+ '<', '>', '/', '?', '`', '~', '|', '\\', 'U', 'O', 'E', 'Y'
+};
+
+/******************************************************************************
+ * Methods for password generation.
+ *****************************************************************************/
+
+float pwgen_diceware(
+ struct SRNG_st *random_state,
+ unsigned int number_of_words,
+ int is_enhanced,
+ const char * (*get_word)(unsigned int),
+ unsigned int dictionary_size,
+ unsigned int *random_buffer,
+ char *password_buffer)
+{
+ unsigned int i, word_length, output_index = 0;
+ const char *word;
+ float entropy = 0;
+
+ *password_buffer = 0;
+ for(i = 0; i < number_of_words; i++) {
+ SRNG_bytes(random_state, random_buffer, sizeof(*random_buffer));
+ word = get_word(*random_buffer);
+ word_length = strlen(word);
+
+ sprintf(password_buffer + output_index, "%s ", word);
+ entropy += log(dictionary_size) / log(2);
+
+ if(is_enhanced) {
+ unsigned int char_pos, char_idx;
+
+ /* add a random symbol at random position into each word */
+ SRNG_bytes(random_state, random_buffer, 2*sizeof(*random_buffer));
+ char_pos = random_buffer[0] % word_length;
+ char_idx = random_buffer[1] % sizeof(t_passphrase_enh);
+ password_buffer[output_index+char_pos] =
+ t_passphrase_enh[char_idx];
+
+ /* 5.17 = log2(36) for each symbol plus the position randomness */
+ entropy += 5.17 + log(word_length) / log(2);
+ }
+ output_index += word_length+1;
+ }
+
+ return entropy;
+}
+
+//*********************************************************************
+//* Base64 - a simple base64 encoder and decoder.
+//*
+//* Copyright (c) 1999, Bob Withers - bwit@pobox.com
+//*
+//* This code may be freely used for any purpose, either personal
+//* or commercial, provided the authors copyright notice remains
+//* intact.
+//*
+//* Converted to C in 2005 by Zeljko Vrba <zvrba@globalnet.hr>
+//*********************************************************************
+static void base64_encode(
+ const unsigned char *in,
+ unsigned int len,
+ char *out)
+{
+ static const char fillchar = '=';
+ static const char *cvt =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+ unsigned int i;
+ unsigned char c;
+
+ /*
+ * SECURITY NOTE: single byte from the in string gets copied to the
+ * local stack in each iteration of the loop.
+ */
+
+ for (i = 0; i < len; ++i) {
+ c = (in[i] >> 2) & 0x3f;
+ *out++ = cvt[c];
+ c = (in[i] << 4) & 0x3f;
+ if(++i < len)
+ c |= (in[i] >> 4) & 0x0f;
+ *out++ = cvt[c];
+ if(i < len) {
+ c = (in[i] << 2) & 0x3f;
+ if(++i < len)
+ c |= (in[i] >> 6) & 0x03;
+ *out++ = cvt[c];
+ } else {
+ ++i;
+ *out++ = fillchar;
+ }
+
+ if(i < len) {
+ c = in[i] & 0x3f;
+ *out++ = cvt[c];
+ } else {
+ *out++ = fillchar;
+ }
+ }
+ *out++ = 0;
+}
+
+float pwgen_raw(
+ struct SRNG_st *random_state,
+ unsigned int number_of_bits,
+ unsigned int *random_buffer,
+ char *password_buffer)
+{
+ unsigned int number_of_bytes = ((number_of_bits-1)>>3)+1;
+
+ SRNG_bytes(random_state, random_buffer, number_of_bytes);
+ base64_encode((unsigned char*)random_buffer, number_of_bytes,
+ password_buffer);
+ return number_of_bytes << 3;
+}
+
+/*
+ * This rounds the number of bits to the next higher multiple of 7 (since
+ * there are 128=2^7 syllables in the koremutake list).
+ */
+float pwgen_koremutake(
+ struct SRNG_st *random_state,
+ unsigned int number_of_bits,
+ unsigned int *random_buffer,
+ char *password_buffer)
+{
+ unsigned int i, number_of_bytes = ((number_of_bits-1)/7)+1;
+ unsigned char *u8buf = (unsigned char*)random_buffer;
+
+ SRNG_bytes(random_state, random_buffer, number_of_bytes);
+ *password_buffer = 0;
+ for(i = 0; i < number_of_bytes; i++)
+ strcat(password_buffer, koremutake_syllables[u8buf[i] & 127]);
+ return number_of_bytes * 7;
+}
+
+static void select_class(
+ struct SRNG_st *random_state,
+ unsigned int allowed_classes,
+ unsigned int *random_buffer)
+{
+ do {
+ SRNG_bytes(random_state, random_buffer, sizeof(*random_buffer));
+ *random_buffer %= N_CHARACTER_CLASSES; /* not a LCG, so % is OK */
+ } while(!(allowed_classes & character_classes[*random_buffer].chr));
+}
+
+float pwgen_ascii(
+ struct SRNG_st *random_state,
+ unsigned int number_of_components,
+ unsigned int allowed_classes,
+ unsigned int *random_buffer,
+ char *password_buffer)
+{
+ unsigned int i;
+ unsigned int *character_class = random_buffer;
+ unsigned int *dice12 = character_class + 1;
+ unsigned int *dice3 = character_class + 2;
+ float entropy = 0;
+
+ password_buffer[0] = 0;
+ for(i = 0; i < number_of_components; i++) {
+retry:
+ /* select character class and throw 3 dice */
+ select_class(random_state, allowed_classes, character_class);
+ SRNG_bytes(random_state, dice12, 2);
+ *dice12 %= 36; /* 1st and 2nd dice */
+ *dice3 %= 6; /* 3rd dice */
+
+ if(character_classes[*character_class].dice12[*dice12]) {
+ strcat(password_buffer,
+ character_classes[*character_class].dice12[*dice12]);
+ if(!character_classes[*character_class].dice3)
+ entropy += character_classes[*character_class].entropy;
+ } else {
+ goto retry;
+ }
+
+ if(character_classes[*character_class].dice3) {
+ if(character_classes[*character_class].dice3[*dice3]) {
+ strcat(password_buffer,
+ character_classes[*character_class].dice3[*dice3]);
+ entropy += character_classes[*character_class].entropy;
+ } else {
+ goto retry;
+ }
+ }
+ }
+
+ return entropy;
+}
+
diff --git a/pwgen.h b/pwgen.h
new file mode 100644
index 0000000..26211fb
--- /dev/null
+++ b/pwgen.h
@@ -0,0 +1,130 @@
+/*
+ pwgen.h - interface to platform-independent password generation
+ (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef PWGEN_H__
+#define PWGEN_H__
+
+/**
+ * @file
+ * This defines the interface to platform-independent secure password
+ * generation routines.
+ */
+
+/**
+ * Generate passphrase by the 'diceware' method: a number of words selected
+ * from a fixed list.
+ *
+ * @param random_state
+ * @param number_of_words
+ * @param is_enhanced If non-0, generates an enhanced passhprase.
+ * @param get_word Pointer to the 'get word' function.
+ * @param dictionary_size Number of words in the dictionary.
+ * @param random_buffer Buffer into which to generate random numbers.
+ * @param password_buffer Buffer to output passphrase to.
+ *
+ * @note rndbuf and pwbuf are provided so that all sensitive output can
+ * be put into the secure memory, if available. There are no sizes
+ * specified, but generally rndbuf should have at least 64 bytes,
+ * and pwbuf at least 512 bytes.
+ *
+ * @return Estimated password entropy.
+ */
+float pwgen_diceware(
+ struct SRNG_st *random_state,
+ unsigned int number_of_words,
+ int is_enhanced,
+ const char * (*get_word)(unsigned int),
+ unsigned int dictionary_size,
+ unsigned int *random_buffer,
+ char *password_buffer);
+
+/**
+ * Generate a raw random passphrase of n bits encoded into base64.
+ *
+ * @param random_state Random state.
+ * @param number_of_bits Number of bits.
+ * @param random_buffer Buffer into which to generate random numbers.
+ * @param password_buffer Buffer to output passphrase to.
+ *
+ * @todo Use our own base64 encoder so we don't have to use mlockall()
+ * and OpenSSL.
+ *
+ * @return Estimated password entropy.
+ */
+float pwgen_raw(
+ struct SRNG_st *random_state,
+ unsigned int number_of_bits,
+ unsigned int *random_buffer,
+ char *password_buffer);
+
+/**
+ * Generate a raw random passphrase of n bits encoded by koremutake encoding
+ * into a pronouncable word.
+ *
+ * @param random_state Random state.
+ * @param number_of_bits Number of bits.
+ * @param random_buffer Buffer into which to generate random numbers.
+ * @param password_buffer Buffer to output passphrase to.
+ *
+ * @todo Use our own base64 encoder so we don't have to use mlockall()
+ * and OpenSSL.
+ *
+ * @return Estimated password entropy.
+ */
+float pwgen_koremutake(
+ struct SRNG_st *random_state,
+ unsigned int number_of_bits,
+ unsigned int *random_buffer,
+ char *password_buffer);
+
+/** Allowable character classes for pwgen_ascii. */
+enum character_classes {
+ chr_alphanumeric = 1,
+ chr_dec_digits = 2,
+ chr_hex_digits = 4,
+ chr_special = 8,
+ chr_syllables = 16
+};
+
+/**
+ * Generate alphanumeric password generated from various 'classes'.
+ *
+ * @param random_state Random state.
+ * @param number_of_components Number of components.
+ * @param character_classes Bit-set of allowed character classes.
+ * @param random_buffer Buffer into which to generate random
+ * numbers.
+ * @param password_buffer Buffer to output passphrase to.
+ *
+ * @see character_classes.
+ *
+ * @return Estimated password entropy.
+ */
+float pwgen_ascii(
+ struct SRNG_st *random_state,
+ unsigned int number_of_components,
+ unsigned int character_classes,
+ unsigned int *random_buffer,
+ char *password_buffer);
+
+#endif /* PWGEN_H__ */
diff --git a/secpwgen.1 b/secpwgen.1
new file mode 100644
index 0000000..5d6761f
--- /dev/null
+++ b/secpwgen.1
@@ -0,0 +1,293 @@
+.\" (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+.\"
+.\" Permission is hereby granted, free of charge, to any person obtaining
+.\" a copy of this software and associated documentation files (the
+.\" "Software"), to deal in the Software without restriction, including
+.\" without limitation the rights to use, copy, modify, merge, publish,
+.\" distribute, sublicense, and/or sell copies of the Software, and to
+.\" permit persons to whom the Software is furnished to do so, subject to
+.\" the following conditions:
+.\"
+.\" The above copyright notice and this permission notice shall be
+.\" included in all copies or substantial portions of the Software.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+.\" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+.\" IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+.\" CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+.\" TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+.\" SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+.Dd April 4, 2005
+.Dt secpwgen 1
+.Os
+.Sh NAME
+.Nm secpwgen
+.Nd "secure password generator"
+.Sh SYNOPSIS
+.Nm
+.Fl p[e]
+.Ar n
+.Nm
+.Fl s[e]
+.Ar n
+.Nm
+.Fl A[adhsy]
+.Ar n
+.Nm
+.Fl r
+.Ar n
+.Nm
+.Fl k
+.Ar n
+.Sh DESCRIPTION
+The
+.Nm
+command is used to generate secure, high-entropy passwords by
+several methods. It aims to generate passwords that are strong and secure
+enough for cryptographic purposes (e.g. for protecting keys). The exact
+method is chosen by the options listed below:
+.Bl -tag -width ".Fl d"
+.It Fl p
+Diceware method with the diceware dictionary.
+.Ar n
+is the number of words in the password. If the method is specified as
+.Fl pe
+then an enhanced password is generated.
+.It Fl s
+Same as
+.Fl p
+and
+.Fl pe
+but with the S/Key dictionary.
+.It Fl A
+Generates an ASCII password of
+.Ar n
+parts. At least one letter after A is mandatory. Each letter incorporates
+additional set of components from which random elements are drawn. See the
+exact method description below.
+.It Fl r
+Generates a random password and outputs it as base-64 encoded string.
+.Ar n
+is the desired number of bits of entropy. It will be rounded up to the
+next higher multiple of 8.
+.It Fl k
+Same as
+.Fl r
+but uses the "koremutake" encoding instead of base 64 encoding. Koremutake
+is yet another way of producing pronouncible phrases from long bit strings.
+.It Ar n
+Specifies the size of the password. The exact meaning depends on the
+method and is described above in options.
+.El
+.Pp
+The program outputs the generated passphrase and a calculated entropy
+of the passphrase.
+.Sh METHOD DESCRIPTIONS
+The following subsections give detailed explanations of the password
+generation methods.
+.Ss DICEWARE METHOD
+This method selects
+.Ar n
+random words from the given dictionary. The diceware dictionary contains
+8192 words, and the S/Key dictionary contains 2048 words. Both dictionaries
+have been taken from the internet (see references).
+.Ss ENHANCED DICEWARE METHOD
+Extends the diceware method by chosing a random letter in each word
+and replacing that letter with one of 32 special symbols and 4 upper-case
+letters (all words in the dictionary are lower-case).
+.Ss ASCII METHOD
+Draws
+.Ar n
+random elements from randomly chosen allowed sets and concatenates
+them in a single string. The allowed sets are specified by the letters
+following the
+.Fl A
+flag and have these meanings:
+.Pp
+.Bl -tag -width "X" -compact
+.It a
+alphanumeric characters
+.It d
+decimal digits
+.It h
+hexadecimal digits
+.It s
+special characters
+.It y
+3- and 4-letter syllables
+.El
+.Pp
+Note that these sets are not all mutually exclusive. Such combinations
+will have the same effect as specifying a single "larger" set.
+.Ss RANDOM METHODS
+Rounds
+.Ar n
+up to the next higher multiple of 8 (7 in case of koremutake) bits (does
+nothing if it is already a multiple) and generates
+.Ar n/8
+(
+.Ar n/7
+)
+random bytes. The resulting passphrase is output as a base-64 or koremutake
+encoded string.
+.Pp
+In case of koremutake, for programming simplicity, each random byte is taken
+mod 128 and looked up in the syllable dictionary. Since the random number
+generator is assumed to be secure, i.e. generates uniformly distributed
+radnom numbers, there is no weakness by using the mod operation.
+.Sh SECURITY
+First of all, a
+.Sy warning:
+as recommended on the diceware site, NEVER actually put spaces between
+individual words of the generated passphrase. On many keyboards the space
+key has very distinctive sound which makes possible for the attacker to
+learn the number of words and possibly the number of letters in each word
+(in correct order). These facts divulge much information and make passphrase
+easier to guess.
+.Pp
+In the author's opinion the program is written very carefully so that the
+generated passphrase can't end up accidentaly on the swap or core file. The
+steps taken in securing the program:
+.Bl -bullet
+.It
+Dedicating a separate block of memory for all confidential data.
+.It
+Zeroing that block of memory upon program exit (by registering the atexit()
+function).
+.It
+Locking all programs' memory with mlockall(MCL_FUTURE), if possible (the
+program must be run with root privileges or installed setuid root to be
+able to do that).
+.Pp
+On some systems, locking memory with mlockall causes the program to fail
+(because some library routines try to allocate too much memory). In that
+case mlock is used with reduced security: the stack is not locked in memory.
+.It
+Disabling core-dumps in the event of crash.
+.It
+Cryptographically strong random number generator (using OpenSSL or cryptlib).
+The exact method for generation is described in its respective source file.
+.El
+.Pp
+The strength of the chain equals the strength of its weakest link. You should
+put as much trust in this program as you trust the implementation of any of
+the following used components: C library, the cryptographic toolkit used for
+random number generation, the kernel, and, ultimately, the system
+administrator (although not a SW component :), a malicious sysadmin can modify
+the kernel or system libraries to log somewhere all output of a program).
+.Pp
+You should build the program as statically linked, if at all possible. There
+are numerous ways in which dynamic linking can be used to subvert this
+programs' security. Unfortunately, there is no reliable nor portable way to
+discover at run-time if the program is statically or dynamically linked.
+.Ss OPENSSL NOTES
+This program does not take any steps to initialize the entropy pool. OpenSSL
+uses the system-provided /dev/[u]random as the source of randomness.
+OpenSSL should report an error on systems that do not provide the /dev/random
+device. If you are sure that your system does not support these
+devices (most notably, WIN32 systems) and the program does not report an
+error then
+.Sy do not use it
+if you want really secure and unguessable passwords. There are many real-life
+examples where the system security was compromised because of poor random
+number generators.
+.Ss CRYPTLIB NOTES
+For maximum security, it is recommended to use cryptlib if at all possible.
+Citing its manual, it is designed around a B3 kernel and tries very hard to
+protect and sanitize all sensitive data (including locking it in memory if
+possible). Also, there are no issues about initializing the entropy pool.
+.Sh EXAMPLES
+Generate an 4-word enhanced passphrase from the diceware dictionary:
+.Nm
+command:
+.Pp
+.Dl "secpwgen -pe 4"
+.Pp
+gives the following typical output when run without root privileges:
+.Pp
+.Bd -literal -unfilled -offset indent
+mlockall: Operation not permitted
+WARNING: using insecure memory.
+----------------
+ha'e ap.x ro|ue si+th ;ENTROPY=81.32 bits
+----------------
+INFO: zeroing memory.
+.Ed
+.Sh DIAGNOSTICS
+Exit status is 0 on success, and 1 if the command
+encounters a fatal error. Informational messages are omitted from this
+listing. Their meaning can be deduced from the source.
+.Bl -diag
+.It "WARNING: using insecure memory."
+This message is not only pertained to memory; for example it can happen that
+the program can't turn off core file generation. The exact cause is seen
+in system error messages preceding the warning.
+.Pp
+If this message is printed, you must assume that the generated password can
+end up in plain text on the swap device, core file or other from where it
+could be retrieved by an adversary.
+.It "FATAL: out of memory."
+Cannot allocate enough memory.
+.It "FATAL: system call failed. There is no way..."
+The program, if installed as SUID root, drops its root privileges
+as soon as it obtains secure memory. This didn't succeed, and
+because of documented buffer overflows (see the
+.Sx BUGS
+section below) the program refuses to execute. Executing a SUID
+program with the potential of buffer overflows is an extreme
+security risk.
+.It "FATAL: too small MAX_RANDOM_STATE_SIZE..."
+The MAX_RANDOM_STATE_SIZE macro in secure_memory.h should be enlarged
+to at least the size displayed after the message and the program
+recompiled.
+.It "FATAL: unhandled exception"
+This is a real bug in the program. Report this to the author
+along with the exact command-line arguments, the compiler used,
+operating system, etc.
+.It "ERROR: some garbage left to cryptlib."
+This is an indication of the bug in the program. Report this to the author
+along with other data described above. Nothing "bad" happened; everything
+was properly cleaned by cryptlib on exit. It is just an indication that
+some objects were not freed by the program before shutting down cryptlib.
+.El
+.Sh SEE ALSO
+.Xr pwgen 1 ,
+.Xr mlockall 2
+.Rs
+.%T "Diceware Passphrase Home Page"
+.%O http://www.diceware.com
+.Re
+.Rs
+.%T "Koremutake encoding"
+.%O http://shorl.com/koremutake.php
+.Re
+.Rs
+.%T "RFC1760: The S/KEY One-Time Password System"
+.Re
+.Rs
+.%T "RFC2289: A One-Time Password System"
+.Re
+.Rs
+.%A Peter Gutmann
+.%T cryptlib
+.%O http://www.cs.auckland.ac.nz/~pgut001/cryptlib/
+.Re
+.Rs
+.%T OpenSSL
+.%O http://www.openssl.org
+.Re
+.Sh AUTHORS
+The secpwgen program and this manual page were written by
+.An Zeljko Vrba Aq zvrba@globalnet.hr .
+.Sh BUGS
+The program
+.Sy will crash
+if
+.Ar n
+is too big. No checks are made for the internal buffer sizes. However, since
+this program is intended to be used by humans who must memorize their
+passphrases, this is not an issue. The program works correctly for "reasonable"
+sizes of
+.Ar n
+(e.g. less than 256).
diff --git a/secure_memory.h b/secure_memory.h
new file mode 100644
index 0000000..d48d6d6
--- /dev/null
+++ b/secure_memory.h
@@ -0,0 +1,57 @@
+/*
+ secure_memory.h - definitions of data structures residing in secure memory
+ (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef SECURE_MEMORY_H__
+#define SECURE_MEMORY_H__
+
+/**
+ * @file
+ * This defines the contents of the secure memory.
+ */
+
+/** Maximum size of random state. */
+#define MAX_RANDOM_STATE_SIZE 8192
+
+struct secure_memory {
+ unsigned char random_state[MAX_RANDOM_STATE_SIZE];
+ unsigned int random_numbers[64];
+ char passphrase[1];
+};
+
+extern struct secure_memory *G_secure_memory;
+extern unsigned int G_secure_memory_size;
+
+/**
+ * Set up a chunk of secure memory.
+ *
+ * @return 0 if at least one operation failed, 1 otherwise. In either case
+ * the program execution can continue. There may be other side-effects such
+ * as printing warnings. If there was a fatal error, this function will
+ * terminate the program.
+ */
+int secure_memory_init(void);
+
+/** Destroy secure memory. Zeroes it before destruction. */
+void secure_memory_destroy(void);
+
+#endif /* SECURE_MEMORY_H__ */
diff --git a/secure_memory_unix.c b/secure_memory_unix.c
new file mode 100644
index 0000000..1ccf855
--- /dev/null
+++ b/secure_memory_unix.c
@@ -0,0 +1,135 @@
+/*
+ secure_memory_unix.c - secure memory implementation for UNIX systems
+ (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include "secure_random.h"
+#include "secure_memory.h"
+#include "exceptions.h"
+
+static char rcsid[] = "$Id: secure_memory_unix.c 1 2005-11-13 20:23:40Z zvrba $";
+
+#ifndef MAP_ANON
+#define MAP_ANON MAP_ANONYMOUS
+#endif
+
+struct secure_memory *G_secure_memory;
+unsigned int G_secure_memory_size;
+static long G_pagesize;
+
+static int allocate_secure_memory(void)
+{
+ int retval = 1;
+
+ if((G_pagesize = sysconf(_SC_PAGESIZE)) < 0) {
+ perror("sysconf");
+ Throw(system_call_failed_exception);
+ }
+
+ G_secure_memory_size = 16*G_pagesize;
+ G_secure_memory = mmap(NULL, G_secure_memory_size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ if(G_secure_memory == MAP_FAILED) {
+ perror("mmap");
+ Throw(out_of_memory_exception);
+ }
+
+ /* This is to guarantee segfault on buffer overrun. */
+ if(mprotect((char*)G_secure_memory + 15*G_pagesize, G_pagesize,
+ PROT_NONE) < 0) {
+ perror("mprotect");
+ Throw(system_call_failed_exception);
+ }
+
+#ifdef DISABLE_MLOCKALL
+ /*
+ * On some OSes (most notably some Linux 2.6 kernels versions), some
+ * libraries try to allocate too much space and then crash (because
+ * the allocation would exceed the maximum allowed number of locked
+ * pages). Which results in a crash.
+ *
+ * However, this gives lower security since the stack pages are not
+ * locked in memory.
+ */
+ if(mlock(G_secure_memory, G_secure_memory_size) < 0) {
+ perror("mlock");
+ retval = 0;
+ }
+#else
+ if(mlockall(MCL_FUTURE) < 0) {
+ perror("mlockall");
+ retval = 0;
+ }
+#endif
+
+ return retval;
+}
+
+static void drop_privileges(void)
+{
+ if(seteuid(getuid()) < 0) {
+ perror("seteuid");
+ Throw(system_call_failed_exception);
+ }
+}
+
+static int disable_core_file(void)
+{
+ int retval = 1;
+ struct rlimit rlim = { 0, 0 };
+
+ if(setrlimit(RLIMIT_CORE, &rlim) < 0) {
+ perror("setrlimit");
+ retval = 0;
+ }
+
+ return retval;
+}
+
+int secure_memory_init(void)
+{
+ int success;
+
+ success = allocate_secure_memory();
+ drop_privileges();
+ success &= disable_core_file();
+
+ if(!success)
+ fprintf(stderr, "WARNING: using insecure memory.\n");
+
+ return success;
+}
+
+void secure_memory_destroy(void)
+{
+ printf("INFO: zeroing memory.\n");
+ memset(G_secure_memory, 0, G_secure_memory_size - G_pagesize);
+}
+
diff --git a/secure_random.h b/secure_random.h
new file mode 100644
index 0000000..d0eb42a
--- /dev/null
+++ b/secure_random.h
@@ -0,0 +1,69 @@
+/*
+ secure_random.h - interface for secure random number generator
+ (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef SECURE_RANDOM_H__
+#define SECURE_RANDOM_H__
+
+/**
+ @file
+ This file defines the SRNG interface.
+*/
+
+/** Opaque structure used to hold secure random generator state. */
+struct SRNG_st;
+
+/**
+ Initialize the secure random number generator.
+ @param st The state variable which should be initialized. The behaviour
+ depends whether this is NULL or not.
+ @return The size of the initialized state.
+
+ An exception is thrown on error.
+
+ @note The interface is designed such that it is possible to provide a
+ secure (e.g. memory-locked) buffer for the state. If \e st is
+ NULL, the function does nothing, but still returns the size that
+ needs to be reserved for the state.
+*/
+unsigned int SRNG_init(struct SRNG_st *st);
+
+/**
+ Obtain \e n bytes of randomness from the generator.
+
+ @param st Pointer to generator state.
+ @param buf Buffer to store random bytes.
+ @param n Number of random bytes to retrieve.
+
+ An exception is thrown on error.
+*/
+void SRNG_bytes(
+ struct SRNG_st *st,
+ void *buf,
+ unsigned int n);
+
+/**
+ * Destroy the RNG state. \e st is pointer returned by SRNG_init().
+ */
+void SRNG_destroy(struct SRNG_st *st);
+
+#endif /* SECURE_RANDOM_H__ */
diff --git a/secure_random_cryptlib.c b/secure_random_cryptlib.c
new file mode 100644
index 0000000..ba0fbe8
--- /dev/null
+++ b/secure_random_cryptlib.c
@@ -0,0 +1,84 @@
+/*
+ secure_random_openssl.c - secure random number generator using OpenSSL
+ (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <cryptlib.h>
+#include "exceptions.h"
+
+static char rcsid[] = "$Id: secure_random_cryptlib.c 1 2005-11-13 20:23:40Z zvrba $";
+
+/**
+ @file
+ Cryptlib random number generator.
+*/
+
+struct SRNG_st {
+ CRYPT_CONTEXT ctx;
+ char rnd[64];
+};
+
+#define CALL_CL(func, ...) do { \
+ int ret__ = func(__VA_ARGS__); \
+ if(ret__ != CRYPT_OK) { \
+ fprintf(stderr, "cryptlib error: %d\n", ret__); \
+ Throw(lib_crypto_exception); \
+ } \
+} while(0)
+
+unsigned int SRNG_init(struct SRNG_st *st)
+{
+ if(!st)
+ goto end;
+
+ CALL_CL(cryptInit);
+ CALL_CL(cryptAddRandom, NULL, CRYPT_RANDOM_SLOWPOLL);
+ CALL_CL(cryptCreateContext, &st->ctx, CRYPT_UNUSED, CRYPT_ALGO_RC4);
+ CALL_CL(cryptGenerateKey, st->ctx);
+
+end:
+ return sizeof(struct SRNG_st);
+}
+
+void SRNG_bytes(
+ struct SRNG_st *st,
+ void *buf,
+ unsigned int n)
+{
+ assert(n < sizeof(st->rnd));
+ CALL_CL(cryptEncrypt, st->ctx, st->rnd, sizeof(st->rnd));
+ memcpy(buf, st->rnd, n);
+}
+
+void SRNG_destroy(struct SRNG_st *st)
+{
+ printf("INFO: destroying random number generator.\n");
+ CALL_CL(cryptDestroyContext, st->ctx);
+ if(cryptEnd() != CRYPT_OK) {
+ fprintf(stderr, "ERROR: some garbage left to cryptlib.");
+ }
+ memset(st, 0, sizeof(*st));
+}
+
diff --git a/secure_random_openssl.c b/secure_random_openssl.c
new file mode 100644
index 0000000..fe29165
--- /dev/null
+++ b/secure_random_openssl.c
@@ -0,0 +1,108 @@
+/*
+ secure_random_openssl.c - secure random number generator using OpenSSL
+ (c) 2004-2005 Zeljko Vrba <zvrba@globalnet.hr>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/blowfish.h>
+#include "exceptions.h"
+
+static char rcsid[] = "$Id: secure_random_openssl.c 1 2005-11-13 20:23:40Z zvrba $";
+
+/**
+ @file
+ This implementation uses the Blowfish cipher and low-level interfaces
+ usable both in SSLEay and OpenSSL (the latter is interesting in porting
+ to e.g. PalmOS).
+
+ The generator gathers a small amount of true randomness from the system and
+ uses it to initialize the blowfish key and the randomness buffer. Further
+ random bytes are obtained by encrypting the previous contents of the
+ random buffer.
+*/
+
+/* Blowfish parameters. */
+#define KEY_SIZE 16 /* 128-bit key size */
+#define BLOCK_SIZE 8 /* 64-bit block size */
+
+struct SRNG_st {
+ BF_KEY key;
+ unsigned char rnd[2*BLOCK_SIZE];
+ unsigned int idx;
+ unsigned char keydata[KEY_SIZE];
+};
+
+unsigned int SRNG_init(struct SRNG_st *st)
+{
+ if(!st)
+ goto end;
+
+ if(!RAND_bytes(st->keydata, sizeof(st->keydata))
+ || !RAND_bytes(st->rnd, sizeof(st->rnd))) {
+ ERR_print_errors_fp(stderr);
+ Throw(lib_crypto_exception);
+ }
+
+ BF_set_key(&st->key, sizeof(st->keydata), st->keydata);
+ st->idx = 0;
+
+end:
+ return sizeof(struct SRNG_st);
+}
+
+void SRNG_bytes(
+ struct SRNG_st *st,
+ void *buf,
+ unsigned int n)
+{
+ unsigned char *out = buf, *src, *dst;
+
+ while(1) {
+ /*
+ * this swaps src and dst to point to differenct halves of st->rnd on
+ * each iteration. st->idx is either 0 or BLOCK_SIZE. it is initialized
+ * to 0 in SRNG_init.
+ */
+ src = st->rnd + st->idx;
+ dst = st->rnd + (BLOCK_SIZE - st->idx);
+ st->idx = BLOCK_SIZE - st->idx;
+
+ BF_ecb_encrypt(src, dst, &st->key, BF_ENCRYPT);
+
+ if(n < BLOCK_SIZE) {
+ memcpy(out, dst, n);
+ break;
+ }
+
+ memcpy(out, dst, BLOCK_SIZE);
+ n -= BLOCK_SIZE; out += BLOCK_SIZE;
+ }
+}
+
+void SRNG_destroy(struct SRNG_st *st)
+{
+ printf("INFO: destroying random number generator.\n");
+ memset(st, 0, sizeof(*st));
+}
+
diff --git a/skeylist.c b/skeylist.c
new file mode 100644
index 0000000..4e36a51
--- /dev/null
+++ b/skeylist.c
@@ -0,0 +1,263 @@
+static const char *skeylist[2048] =
+{ "a", "abe", "ace", "act", "ad", "ada", "add",
+"ago", "aid", "aim", "air", "all", "alp", "am", "amy",
+"an", "ana", "and", "ann", "ant", "any", "ape", "aps",
+"apt", "arc", "are", "ark", "arm", "art", "as", "ash",
+"ask", "at", "ate", "aug", "auk", "ave", "awe", "awk",
+"awl", "awn", "ax", "aye", "bad", "bag", "bah", "bam",
+"ban", "bar", "bat", "bay", "be", "bed", "bee", "beg",
+"ben", "bet", "bey", "bib", "bid", "big", "bin", "bit",
+"bob", "bog", "bon", "boo", "bop", "bow", "boy", "bub",
+"bud", "bug", "bum", "bun", "bus", "but", "buy", "by",
+"bye", "cab", "cal", "cam", "can", "cap", "car", "cat",
+"caw", "cod", "cog", "col", "con", "coo", "cop", "cot",
+"cow", "coy", "cry", "cub", "cue", "cup", "cur", "cut",
+"dab", "dad", "dam", "dan", "dar", "day", "dee", "del",
+"den", "des", "dew", "did", "die", "dig", "din", "dip",
+"do", "doe", "dog", "don", "dot", "dow", "dry", "dub",
+"dud", "due", "dug", "dun", "ear", "eat", "ed", "eel",
+"egg", "ego", "eli", "elk", "elm", "ely", "em", "end",
+"est", "etc", "eva", "eve", "ewe", "eye", "fad", "fan",
+"far", "fat", "fay", "fed", "fee", "few", "fib", "fig",
+"fin", "fir", "fit", "flo", "fly", "foe", "fog", "for",
+"fry", "fum", "fun", "fur", "gab", "gad", "gag", "gal",
+"gam", "gap", "gas", "gay", "gee", "gel", "gem", "get",
+"gig", "gil", "gin", "go", "got", "gum", "gun", "gus",
+"gut", "guy", "gym", "gyp", "ha", "had", "hal", "ham",
+"han", "hap", "has", "hat", "haw", "hay", "he", "hem",
+"hen", "her", "hew", "hey", "hi", "hid", "him", "hip",
+"his", "hit", "ho", "hob", "hoc", "hoe", "hog", "hop",
+"hot", "how", "hub", "hue", "hug", "huh", "hum", "hut",
+"i", "icy", "ida", "if", "ike", "ill", "ink", "inn",
+"io", "ion", "iq", "ira", "ire", "irk", "is", "it",
+"its", "ivy", "jab", "jag", "jam", "jan", "jar", "jaw",
+"jay", "jet", "jig", "jim", "jo", "job", "joe", "jog",
+"jot", "joy", "jug", "jut", "kay", "keg", "ken", "key",
+"kid", "kim", "kin", "kit", "la", "lab", "lac", "lad",
+"lag", "lam", "lap", "law", "lay", "lea", "led", "lee",
+"leg", "len", "leo", "let", "lew", "lid", "lie", "lin",
+"lip", "lit", "lo", "lob", "log", "lop", "los", "lot",
+"lou", "low", "loy", "lug", "lye", "ma", "mac", "mad",
+"mae", "man", "mao", "map", "mat", "maw", "may", "me",
+"meg", "mel", "men", "met", "mew", "mid", "min", "mit",
+"mob", "mod", "moe", "moo", "mop", "mos", "mot", "mow",
+"mud", "mug", "mum", "my", "nab", "nag", "nan", "nap",
+"nat", "nay", "ne", "ned", "nee", "net", "new", "nib",
+"nil", "nip", "nit", "no", "nob", "nod", "non", "nor",
+"not", "nov", "now", "nu", "nun", "nut", "o", "oaf",
+"oak", "oar", "oat", "odd", "ode", "of", "off", "oft",
+"oh", "oil", "ok", "old", "on", "one", "or", "orb",
+"ore", "orr", "os", "ott", "our", "out", "ova", "ow",
+"owe", "owl", "own", "ox", "pa", "pad", "pal", "pam",
+"pan", "pap", "par", "pat", "paw", "pay", "pea", "peg",
+"pen", "pep", "per", "pet", "pew", "phi", "pi", "pie",
+"pin", "pit", "ply", "po", "pod", "poe", "pop", "pot",
+"pow", "pro", "pry", "pub", "pug", "pun", "pup", "put",
+"quo", "rag", "ram", "ran", "rap", "rat", "raw", "ray",
+"reb", "red", "rep", "ret", "rib", "rid", "rig", "rim",
+"rio", "rip", "rob", "rod", "roe", "ron", "rot", "row",
+"roy", "rub", "rue", "rug", "rum", "run", "rye", "sac",
+"sad", "sag", "sal", "sam", "san", "sap", "sat", "saw",
+"say", "sea", "sec", "see", "sen", "set", "sew", "she",
+"shy", "sin", "sip", "sir", "sis", "sit", "ski", "sky",
+"sly", "so", "sob", "sod", "son", "sop", "sow", "soy",
+"spa", "spy", "sub", "sud", "sue", "sum", "sun", "sup",
+"tab", "tad", "tag", "tan", "tap", "tar", "tea", "ted",
+"tee", "ten", "the", "thy", "tic", "tie", "tim", "tin",
+"tip", "to", "toe", "tog", "tom", "ton", "too", "top",
+"tow", "toy", "try", "tub", "tug", "tum", "tun", "two",
+"un", "up", "us", "use", "van", "vat", "vet", "vie",
+"wad", "wag", "war", "was", "way", "we", "web", "wed",
+"wee", "wet", "who", "why", "win", "wit", "wok", "won",
+"woo", "wow", "wry", "wu", "yam", "yap", "yaw", "ye",
+"yea", "yes", "yet", "you", "abed", "abel", "abet", "able",
+"abut", "ache", "acid", "acme", "acre", "acta", "acts", "adam",
+"adds", "aden", "afar", "afro", "agee", "ahem", "ahoy", "aida",
+"aide", "aids", "airy", "ajar", "akin", "alan", "alec", "alga",
+"alia", "ally", "alma", "aloe", "also", "alto", "alum", "alva",
+"amen", "ames", "amid", "ammo", "amok", "amos", "amra", "andy",
+"anew", "anna", "anne", "ante", "anti", "aqua", "arab", "arch",
+"area", "argo", "arid", "army", "arts", "arty", "asia", "asks",
+"atom", "aunt", "aura", "auto", "aver", "avid", "avis", "avon",
+"avow", "away", "awry", "babe", "baby", "bach", "back", "bade",
+"bail", "bait", "bake", "bald", "bale", "bali", "balk", "ball",
+"balm", "band", "bane", "bang", "bank", "barb", "bard", "bare",
+"bark", "barn", "barr", "base", "bash", "bask", "bass", "bate",
+"bath", "bawd", "bawl", "bead", "beak", "beam", "bean", "bear",
+"beat", "beau", "beck", "beef", "been", "beer", "beet", "bela",
+"bell", "belt", "bend", "bent", "berg", "bern", "bert", "bess",
+"best", "beta", "beth", "bhoy", "bias", "bide", "bien", "bile",
+"bilk", "bill", "bind", "bing", "bird", "bite", "bits", "blab",
+"blat", "bled", "blew", "blob", "bloc", "blot", "blow", "blue",
+"blum", "blur", "boar", "boat", "boca", "bock", "bode", "body",
+"bogy", "bohr", "boil", "bold", "bolo", "bolt", "bomb", "bona",
+"bond", "bone", "bong", "bonn", "bony", "book", "boom", "boon",
+"boot", "bore", "borg", "born", "bose", "boss", "both", "bout",
+"bowl", "boyd", "brad", "brae", "brag", "bran", "bray", "bred",
+"brew", "brig", "brim", "brow", "buck", "budd", "buff", "bulb",
+"bulk", "bull", "bunk", "bunt", "buoy", "burg", "burl", "burn",
+"burr", "burt", "bury", "bush", "buss", "bust", "busy", "byte",
+"cady", "cafe", "cage", "cain", "cake", "calf", "call", "calm",
+"came", "cane", "cant", "card", "care", "carl", "carr", "cart",
+"case", "cash", "cask", "cast", "cave", "ceil", "cell", "cent",
+"cern", "chad", "char", "chat", "chaw", "chef", "chen", "chew",
+"chic", "chin", "chou", "chow", "chub", "chug", "chum", "cite",
+"city", "clad", "clam", "clan", "claw", "clay", "clod", "clog",
+"clot", "club", "clue", "coal", "coat", "coca", "cock", "coco",
+"coda", "code", "cody", "coed", "coil", "coin", "coke", "cola",
+"cold", "colt", "coma", "comb", "come", "cook", "cool", "coon",
+"coot", "cord", "core", "cork", "corn", "cost", "cove", "cowl",
+"crab", "crag", "cram", "cray", "crew", "crib", "crow", "crud",
+"cuba", "cube", "cuff", "cull", "cult", "cuny", "curb", "curd",
+"cure", "curl", "curt", "cuts", "dade", "dale", "dame", "dana",
+"dane", "dang", "dank", "dare", "dark", "darn", "dart", "dash",
+"data", "date", "dave", "davy", "dawn", "days", "dead", "deaf",
+"deal", "dean", "dear", "debt", "deck", "deed", "deem", "deer",
+"deft", "defy", "dell", "dent", "deny", "desk", "dial", "dice",
+"died", "diet", "dime", "dine", "ding", "dint", "dire", "dirt",
+"disc", "dish", "disk", "dive", "dock", "does", "dole", "doll",
+"dolt", "dome", "done", "doom", "door", "dora", "dose", "dote",
+"doug", "dour", "dove", "down", "drab", "drag", "dram", "draw",
+"drew", "drub", "drug", "drum", "dual", "duck", "duct", "duel",
+"duet", "duke", "dull", "dumb", "dune", "dunk", "dusk", "dust",
+"duty", "each", "earl", "earn", "ease", "east", "easy", "eben",
+"echo", "eddy", "eden", "edge", "edgy", "edit", "edna", "egan",
+"elan", "elba", "ella", "else", "emil", "emit", "emma", "ends",
+"eric", "eros", "even", "ever", "evil", "eyed", "face", "fact",
+"fade", "fail", "fain", "fair", "fake", "fall", "fame", "fang",
+"farm", "fast", "fate", "fawn", "fear", "feat", "feed", "feel",
+"feet", "fell", "felt", "fend", "fern", "fest", "feud", "fief",
+"figs", "file", "fill", "film", "find", "fine", "fink", "fire",
+"firm", "fish", "fisk", "fist", "fits", "five", "flag", "flak",
+"flam", "flat", "flaw", "flea", "fled", "flew", "flit", "floc",
+"flog", "flow", "flub", "flue", "foal", "foam", "fogy", "foil",
+"fold", "folk", "fond", "font", "food", "fool", "foot", "ford",
+"fore", "fork", "form", "fort", "foss", "foul", "four", "fowl",
+"frau", "fray", "fred", "free", "fret", "frey", "frog", "from",
+"fuel", "full", "fume", "fund", "funk", "fury", "fuse", "fuss",
+"gaff", "gage", "gail", "gain", "gait", "gala", "gale", "gall",
+"galt", "game", "gang", "garb", "gary", "gash", "gate", "gaul",
+"gaur", "gave", "gawk", "gear", "geld", "gene", "gent", "germ",
+"gets", "gibe", "gift", "gild", "gill", "gilt", "gina", "gird",
+"girl", "gist", "give", "glad", "glee", "glen", "glib", "glob",
+"glom", "glow", "glue", "glum", "glut", "goad", "goal", "goat",
+"goer", "goes", "gold", "golf", "gone", "gong", "good", "goof",
+"gore", "gory", "gosh", "gout", "gown", "grab", "grad", "gray",
+"greg", "grew", "grey", "grid", "grim", "grin", "grit", "grow",
+"grub", "gulf", "gull", "gunk", "guru", "gush", "gust", "gwen",
+"gwyn", "haag", "haas", "hack", "hail", "hair", "hale", "half",
+"hall", "halo", "halt", "hand", "hang", "hank", "hans", "hard",
+"hark", "harm", "hart", "hash", "hast", "hate", "hath", "haul",
+"have", "hawk", "hays", "head", "heal", "hear", "heat", "hebe",
+"heck", "heed", "heel", "heft", "held", "hell", "helm", "herb",
+"herd", "here", "hero", "hers", "hess", "hewn", "hick", "hide",
+"high", "hike", "hill", "hilt", "hind", "hint", "hire", "hiss",
+"hive", "hobo", "hock", "hoff", "hold", "hole", "holm", "holt",
+"home", "hone", "honk", "hood", "hoof", "hook", "hoot", "horn",
+"hose", "host", "hour", "hove", "howe", "howl", "hoyt", "huck",
+"hued", "huff", "huge", "hugh", "hugo", "hulk", "hull", "hunk",
+"hunt", "hurd", "hurl", "hurt", "hush", "hyde", "hymn", "ibis",
+"icon", "idea", "idle", "iffy", "inca", "inch", "into", "ions",
+"iota", "iowa", "iris", "irma", "iron", "isle", "itch", "item",
+"ivan", "jack", "jade", "jail", "jake", "jane", "java", "jean",
+"jeff", "jerk", "jess", "jest", "jibe", "jill", "jilt", "jive",
+"joan", "jobs", "jock", "joel", "joey", "john", "join", "joke",
+"jolt", "jove", "judd", "jude", "judo", "judy", "juju", "juke",
+"july", "june", "junk", "juno", "jury", "just", "jute", "kahn",
+"kale", "kane", "kant", "karl", "kate", "keel", "keen", "keno",
+"kent", "kern", "kerr", "keys", "kick", "kill", "kind", "king",
+"kirk", "kiss", "kite", "klan", "knee", "knew", "knit", "knob",
+"knot", "know", "koch", "kong", "kudo", "kurd", "kurt", "kyle",
+"lace", "lack", "lacy", "lady", "laid", "lain", "lair", "lake",
+"lamb", "lame", "land", "lane", "lang", "lard", "lark", "lass",
+"last", "late", "laud", "lava", "lawn", "laws", "lays", "lead",
+"leaf", "leak", "lean", "lear", "leek", "leer", "left", "lend",
+"lens", "lent", "leon", "lesk", "less", "lest", "lets", "liar",
+"lice", "lick", "lied", "lien", "lies", "lieu", "life", "lift",
+"like", "lila", "lilt", "lily", "lima", "limb", "lime", "lind",
+"line", "link", "lint", "lion", "lisa", "list", "live", "load",
+"loaf", "loam", "loan", "lock", "loft", "loge", "lois", "lola",
+"lone", "long", "look", "loon", "loot", "lord", "lore", "lose",
+"loss", "lost", "loud", "love", "lowe", "luck", "lucy", "luge",
+"luke", "lulu", "lund", "lung", "lura", "lure", "lurk", "lush",
+"lust", "lyle", "lynn", "lyon", "lyra", "mace", "made", "magi",
+"maid", "mail", "main", "make", "male", "mali", "mall", "malt",
+"mana", "mann", "many", "marc", "mare", "mark", "mars", "mart",
+"mary", "mash", "mask", "mass", "mast", "mate", "math", "maul",
+"mayo", "mead", "meal", "mean", "meat", "meek", "meet", "meld",
+"melt", "memo", "mend", "menu", "mert", "mesh", "mess", "mice",
+"mike", "mild", "mile", "milk", "mill", "milt", "mimi", "mind",
+"mine", "mini", "mink", "mint", "mire", "miss", "mist", "mite",
+"mitt", "moan", "moat", "mock", "mode", "mold", "mole", "moll",
+"molt", "mona", "monk", "mont", "mood", "moon", "moor", "moot",
+"more", "morn", "mort", "moss", "most", "moth", "move", "much",
+"muck", "mudd", "muff", "mule", "mull", "murk", "mush", "must",
+"mute", "mutt", "myra", "myth", "nagy", "nail", "nair", "name",
+"nary", "nash", "nave", "navy", "neal", "near", "neat", "neck",
+"need", "neil", "nell", "neon", "nero", "ness", "nest", "news",
+"newt", "nibs", "nice", "nick", "nile", "nina", "nine", "noah",
+"node", "noel", "noll", "none", "nook", "noon", "norm", "nose",
+"note", "noun", "nova", "nude", "null", "numb", "oath", "obey",
+"oboe", "odin", "ohio", "oily", "oint", "okay", "olaf", "oldy",
+"olga", "olin", "oman", "omen", "omit", "once", "ones", "only",
+"onto", "onus", "oral", "orgy", "oslo", "otis", "otto", "ouch",
+"oust", "outs", "oval", "oven", "over", "owly", "owns", "quad",
+"quit", "quod", "race", "rack", "racy", "raft", "rage", "raid",
+"rail", "rain", "rake", "rank", "rant", "rare", "rash", "rate",
+"rave", "rays", "read", "real", "ream", "rear", "reck", "reed",
+"reef", "reek", "reel", "reid", "rein", "rena", "rend", "rent",
+"rest", "rice", "rich", "rick", "ride", "rift", "rill", "rime",
+"ring", "rink", "rise", "risk", "rite", "road", "roam", "roar",
+"robe", "rock", "rode", "roil", "roll", "rome", "rood", "roof",
+"rook", "room", "root", "rosa", "rose", "ross", "rosy", "roth",
+"rout", "rove", "rowe", "rows", "rube", "ruby", "rude", "rudy",
+"ruin", "rule", "rung", "runs", "runt", "ruse", "rush", "rusk",
+"russ", "rust", "ruth", "sack", "safe", "sage", "said", "sail",
+"sale", "salk", "salt", "same", "sand", "sane", "sang", "sank",
+"sara", "saul", "save", "says", "scan", "scar", "scat", "scot",
+"seal", "seam", "sear", "seat", "seed", "seek", "seem", "seen",
+"sees", "self", "sell", "send", "sent", "sets", "sewn", "shag",
+"sham", "shaw", "shay", "shed", "shim", "shin", "shod", "shoe",
+"shot", "show", "shun", "shut", "sick", "side", "sift", "sigh",
+"sign", "silk", "sill", "silo", "silt", "sine", "sing", "sink",
+"sire", "site", "sits", "situ", "skat", "skew", "skid", "skim",
+"skin", "skit", "slab", "slam", "slat", "slay", "sled", "slew",
+"slid", "slim", "slit", "slob", "slog", "slot", "slow", "slug",
+"slum", "slur", "smog", "smug", "snag", "snob", "snow", "snub",
+"snug", "soak", "soar", "sock", "soda", "sofa", "soft", "soil",
+"sold", "some", "song", "soon", "soot", "sore", "sort", "soul",
+"sour", "sown", "stab", "stag", "stan", "star", "stay", "stem",
+"stew", "stir", "stow", "stub", "stun", "such", "suds", "suit",
+"sulk", "sums", "sung", "sunk", "sure", "surf", "swab", "swag",
+"swam", "swan", "swat", "sway", "swim", "swum", "tack", "tact",
+"tail", "take", "tale", "talk", "tall", "tank", "task", "tate",
+"taut", "teal", "team", "tear", "tech", "teem", "teen", "teet",
+"tell", "tend", "tent", "term", "tern", "tess", "test", "than",
+"that", "thee", "them", "then", "they", "thin", "this", "thud",
+"thug", "tick", "tide", "tidy", "tied", "tier", "tile", "till",
+"tilt", "time", "tina", "tine", "tint", "tiny", "tire", "toad",
+"togo", "toil", "told", "toll", "tone", "tong", "tony", "took",
+"tool", "toot", "tore", "torn", "tote", "tour", "tout", "town",
+"trag", "tram", "tray", "tree", "trek", "trig", "trim", "trio",
+"trod", "trot", "troy", "true", "tuba", "tube", "tuck", "tuft",
+"tuna", "tune", "tung", "turf", "turn", "tusk", "twig", "twin",
+"twit", "ulan", "unit", "urge", "used", "user", "uses", "utah",
+"vail", "vain", "vale", "vary", "vase", "vast", "veal", "veda",
+"veil", "vein", "vend", "vent", "verb", "very", "veto", "vice",
+"view", "vine", "vise", "void", "volt", "vote", "wack", "wade",
+"wage", "wail", "wait", "wake", "wale", "walk", "wall", "walt",
+"wand", "wane", "wang", "want", "ward", "warm", "warn", "wart",
+"wash", "wast", "wats", "watt", "wave", "wavy", "ways", "weak",
+"weal", "wean", "wear", "weed", "week", "weir", "weld", "well",
+"welt", "went", "were", "wert", "west", "wham", "what", "whee",
+"when", "whet", "whoa", "whom", "wick", "wife", "wild", "will",
+"wind", "wine", "wing", "wink", "wino", "wire", "wise", "wish",
+"with", "wolf", "wont", "wood", "wool", "word", "wore", "work",
+"worm", "worn", "wove", "writ", "wynn", "yale", "yang", "yank",
+"yard", "yarn", "yawl", "yawn", "yeah", "year", "yell", "yoga",
+"yoke" };
+
+const char *getSkeyWd(unsigned int n)
+{
+ return skeylist[n & 0x7ff];
+}