diff options
author | Benjamin Barenblat <bbaren@mit.edu> | 2015-03-14 19:47:09 -0400 |
---|---|---|
committer | Benjamin Barenblat <bbaren@mit.edu> | 2015-03-14 19:47:09 -0400 |
commit | aadb9e2e90925a187877241e50110e4ce7ea80a1 (patch) | |
tree | 7cb115e040db2a73c10e5da3f0fe4c16c9f39f9b |
Imported Upstream version 1.3upstream/1.3
-rw-r--r-- | ChangeLog | 36 | ||||
-rw-r--r-- | Makefile.proto | 100 | ||||
-rw-r--r-- | README | 27 | ||||
-rw-r--r-- | cexcept.h | 243 | ||||
-rw-r--r-- | diagnostics.h | 41 | ||||
-rw-r--r-- | diceware8k.c | 8201 | ||||
-rw-r--r-- | exceptions.h | 43 | ||||
-rw-r--r-- | main.c | 222 | ||||
-rw-r--r-- | pwgen.c | 313 | ||||
-rw-r--r-- | pwgen.h | 130 | ||||
-rw-r--r-- | secpwgen.1 | 293 | ||||
-rw-r--r-- | secure_memory.h | 57 | ||||
-rw-r--r-- | secure_memory_unix.c | 135 | ||||
-rw-r--r-- | secure_random.h | 69 | ||||
-rw-r--r-- | secure_random_cryptlib.c | 84 | ||||
-rw-r--r-- | secure_random_openssl.c | 108 | ||||
-rw-r--r-- | skeylist.c | 263 |
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 @@ -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__ */ @@ -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; +} @@ -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; +} + @@ -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]; +} |