Browse Source

new file: LICENSE
new file: MANIFEST
new file: mmgen-addrgen
new file: mmgen-keygen
new file: mmgen-passchg
new file: mmgen-walletchk
new file: mmgen-walletgen
new file: mmgen/Opts.py
new file: mmgen/__init__.py
new file: mmgen/addr.py
new file: mmgen/bitcoin.py
new file: mmgen/config.py
new file: mmgen/license.py
new file: mmgen/mn_electrum.py
new file: mmgen/mn_tirosh.py
new file: mmgen/mnemonic.py
new file: mmgen/utils.py
new file: mmgen/walletgen.py
new file: setup.py
new file: tests/addr.py
new file: tests/bitcoin.py
new file: tests/mn_electrum.py
new file: tests/mn_tirosh.py
new file: tests/mnemonic.py
new file: tests/test.py
new file: tests/utils.py
new file: tests/walletgen.py
new file: wordlists/mn_wordlist.c
new file: wordlists/mn_wordlist.py
new file: wordlists/mn_wordlist.sort.py
new file: wordlists/mnemonic.py
new file: wordlists/mnemonic.sort.py

philemon 11 years ago
commit
9f28397cfe
32 changed files with 12725 additions and 0 deletions
  1. 674 0
      LICENSE
  2. 18 0
      MANIFEST
  3. 1 0
      mmgen-addrgen
  4. 175 0
      mmgen-keygen
  5. 121 0
      mmgen-passchg
  6. 75 0
      mmgen-walletchk
  7. 168 0
      mmgen-walletgen
  8. 68 0
      mmgen/Opts.py
  9. 38 0
      mmgen/__init__.py
  10. 187 0
      mmgen/addr.py
  11. 153 0
      mmgen/bitcoin.py
  12. 48 0
      mmgen/config.py
  13. 649 0
      mmgen/license.py
  14. 1657 0
      mmgen/mn_electrum.py
  15. 1658 0
      mmgen/mn_tirosh.py
  16. 112 0
      mmgen/mnemonic.py
  17. 727 0
      mmgen/utils.py
  18. 87 0
      mmgen/walletgen.py
  19. 30 0
      setup.py
  20. 27 0
      tests/addr.py
  21. 190 0
      tests/bitcoin.py
  22. 24 0
      tests/mn_electrum.py
  23. 24 0
      tests/mn_tirosh.py
  24. 109 0
      tests/mnemonic.py
  25. 86 0
      tests/test.py
  26. 27 0
      tests/utils.py
  27. 27 0
      tests/walletgen.py
  28. 302 0
      wordlists/mn_wordlist.c
  29. 292 0
      wordlists/mn_wordlist.py
  30. 1642 0
      wordlists/mn_wordlist.sort.py
  31. 1691 0
      wordlists/mnemonic.py
  32. 1638 0
      wordlists/mnemonic.sort.py

+ 674 - 0
LICENSE

@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.

+ 18 - 0
MANIFEST

@@ -0,0 +1,18 @@
+# file GENERATED by distutils, do NOT edit
+mmgen-addrgen
+mmgen-keygen
+mmgen-passchg
+mmgen-walletchk
+mmgen-walletgen
+setup.py
+mmgen/Opts.py
+mmgen/__init__.py
+mmgen/addr.py
+mmgen/bitcoin.py
+mmgen/config.py
+mmgen/license.py
+mmgen/mn_electrum.py
+mmgen/mn_tirosh.py
+mmgen/mnemonic.py
+mmgen/utils.py
+mmgen/walletgen.py

+ 1 - 0
mmgen-addrgen

@@ -0,0 +1 @@
+mmgen-keygen

+ 175 - 0
mmgen-keygen

@@ -0,0 +1,175 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+mmgen-keygen: Generate addresses/secret keys from a mmgen deterministic 
+              wallet for a range of addresses.
+			  Call as 'btc-addrgen' for safe, reduced functionality
+			  with no output of secret keys.
+"""
+
+import sys
+
+from mmgen.Opts   import *
+from mmgen.config import *
+from mmgen.license import *
+from mmgen.utils  import *
+from mmgen.addr   import *
+
+invoked_as = sys.argv[0].split("-")[-1]
+gen_what = "addresses" if invoked_as == "addrgen" else "keys"
+
+if invoked_as == "keygen":
+	extra_help_data = (
+		"\n-A, --no-addresses       Print only secret keys, no addresses",
+		"\n-x, --b16                Print secret keys in hexadecimal too",
+		".\nBy default, both addresses and secret keys are generated"
+	)
+else: extra_help_data = ("","","")
+
+help_data = {
+	'prog_name': sys.argv[0].split("/")[-1],
+	'desc': """Generate a range of {} from a {} wallet, mnemonic,
+                  seed or password""".format(gen_what,proj_name),
+	'usage':"[opts] [infile] <address range>",
+	'options': """
+-h, --help               Print this help message{}
+-d, --outdir          d  Specify an alternate directory 'd' for output
+-e, --echo-passphrase    Display passphrase or mnemonic on screen upon entry
+-K, --no-keyconv         Use internal libraries for address generation
+                         instead of 'keyconv' 
+-l, --seed-len        N  Length of seed.  Options: {}
+                         (default: {})
+-p, --hash-preset     p  Use scrypt.hash() parameters from preset 'p'
+                         when hashing password (default: '{}')
+-P, --show-hash-presets  Show information on available hash presets
+-q, --quiet              Suppress warnings; overwrite files without asking
+-S, --stdout             Print {W} to stdout
+-v, --verbose            Produce more verbose output{}
+
+-b, --from-brain     l,p Generate {W} from a user-created password,
+                         i.e. a "brainwallet", using seed length 'l' and
+                         hash preset 'p' (comma-separated)
+-m, --from-mnemonic      Generate {W} from an electrum-like mnemonic
+-s, --from-seed          Generate {W} from a seed in .{S} format
+
+Address range may be a single number or a range in the form XXX-YYY{}
+
+If available, external 'keyconv' program will be used for address generation
+
+Data for the --from-<what> options will be taken from <infile> if <infile>
+is specified.  Otherwise, the user will be prompted to enter the data.  Note
+that passphrase data in a file may be arranged in free-form fashion, using
+any combination of spaces, tabs or newlines to separate words
+
+BRAINWALLET NOTE:
+
+As brainwallets require especially strong hashing to thwart dictionary
+attacks, the brainwallet hash preset must be specified by the user, using
+the 'p' parameter of the '--from-brain' option
+
+The '--from-brain' option also requires the user to specify a seed length
+(the 'l' parameter)
+
+For a brainwallet passphrase to always generate the same keys and addresses,
+the same 'l' and 'p' parameters to '--from-brain' must be used in all future
+invocations with that passphrase
+""".format(
+		extra_help_data[0],
+		", ".join([str(i) for i in seed_lens]),
+		seed_len,
+		hash_preset,
+		extra_help_data[1],
+		extra_help_data[2],
+		W=gen_what,
+		S=seed_ext
+	)
+}
+
+so = "h","A","d:","e","K","l:","p:","P","q","S","v","x","b:","m","s"
+lo = "help","no_addresses","outdir=","echo_passphrase","no_keyconv",\
+	  "seed_len=","hash_preset=","show_hash_presets","quiet","stdout",\
+	  "verbose","b16","from_brain=","from_mnemonic","from_seed"
+
+if invoked_as == "addrgen":
+	short_opts = so[0:1] + so[2:10] + so[11:]
+	long_opts  = lo[0:1] + lo[2:10] + lo[11:]
+else:
+	short_opts,long_opts = so,lo
+
+opts,cmd_args = process_opts(sys.argv,help_data,"".join(short_opts),long_opts)
+
+if 'show_hash_presets' in opts: show_hash_presets()
+
+# Sanity checking and processing of command-line arguments:
+
+opts['gen_what'] = gen_what
+
+set_if_unset_and_typeconvert(opts,(
+	('hash_preset',hash_preset,'str'),
+	('seed_len',seed_len,'int')
+))
+
+# Exits on invalid input
+check_opts(opts,('hash_preset','seed_len','outdir','from_brain'))
+
+if debug:
+	print "Processed options:     %s" % repr(opts)
+	print "Cmd args:              %s" % repr(cmd_args)
+
+if   len(cmd_args) == 1 and (
+			'from_mnemonic' in opts or
+			'from_brain' in opts or
+			'from_seed' in opts
+		): infile,addr_range = "",cmd_args[0]
+elif len(cmd_args) == 2:
+	infile,addr_range = cmd_args
+	check_infile(infile)
+else: usage(help_data)
+
+start,end = parse_address_range(addr_range)
+
+if not 'quiet' in opts: do_license_msg(); msg("\n")
+
+# Interact with user:
+
+if invoked_as == "keygen" and not 'quiet' in opts:
+	confirm_or_exit(cmessages['unencrypted_secret_keys'], 'continue')
+
+# Generate data:
+
+if invoked_as == "addrgen":
+	opts['print_addresses_only'] = True
+else:
+	if not 'no_addresses' in opts: opts['print_secret'] = True
+
+seed          = get_seed(infile,opts)
+seed_id       = make_chksum_8(seed)
+addr_data     = generate_addrs(seed, start, end, opts)
+addr_data_str = format_addr_data(addr_data, seed_id, opts)
+
+# Output data:
+if 'stdout' in opts:
+	if invoked_as == "keygen" and not 'quiet' in opts:
+		confirm = True
+	else: confirm = False
+	write_to_stdout(addr_data_str,confirm)
+elif not sys.stdout.isatty():
+	write_to_stdout(addr_data_str,confirm=False)
+else:
+	write_addr_data_to_file(seed, addr_data_str, start, end, opts)

+ 121 - 0
mmgen-passchg

@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+mmgen-passchg: Change a mmgen deterministic wallet's passphrase, label or
+               hash preset
+"""
+
+import sys
+import mmgen.Opts as Opts
+
+from mmgen.utils import *
+from mmgen.config import *
+
+help_data = {
+	'desc':  """Change the passphrase, hash preset or label of a {}
+                  deterministic wallet""".format(proj_name),
+	'usage':   "[opts] [filename]",
+	'options': """
+-h, --help                  Print this help message
+-d, --outdir             d  Specify an alternate directory 'd' for output
+-k, --keep-old-passphrase   Keep old passphrase (use when changing hash 
+                            strength or label only)
+-L, --label                 Change the wallet's label
+-p, --hash-preset        p  Change scrypt.hash() parameters to preset 'p'
+                            (default: '{}')
+-P, --show-hash-presets     Show information on available hash presets
+-v, --verbose               Produce more verbose output
+
+NOTE: The key ID will change if either the passphrase or hash preset
+      are changed
+""".format(hash_preset)
+}
+
+short_opts = "hd:kL:p:Pv"
+long_opts  = "help","outdir=","keep_old_passphrase","label=","hash_preset=",\
+			   "show_hash_presets","verbose"
+
+opts,cmd_args = Opts.process_opts(sys.argv,help_data,short_opts,long_opts)
+
+if 'show_hash_presets' in opts: show_hash_presets()
+
+set_if_unset_and_typeconvert(opts,(('hash_preset',hash_preset,'str'),))
+check_opts(opts,('hash_preset','outdir','label'))
+
+if len(cmd_args) != 1:
+	msg("One input file must be specified")
+	sys.exit(2)
+infile = cmd_args[0]
+
+# Old key:
+label,metadata,hash_preset,salt,enc_seed = get_data_from_wallet(infile,opts)
+seed_id,key_id = metadata[:2]
+passwd = " ".join(get_words("","","Enter old passphrase: ",opts))
+key = make_key(passwd, salt, hash_preset)
+seed = decrypt_seed(enc_seed, key, seed_id, key_id)
+
+changed = {} 
+
+if 'label' in opts:
+	if opts['label'] != label:
+		msg("Label changed: '%s' -> '%s'" % (label, opts['label']))
+		changed['label'] = True
+	else:
+		msg("Label is unchanged: '%s'" % (label))
+else: opts['label'] = label  # Copy the old label
+
+if 'hash_preset' in opts:
+	if hash_preset != opts['hash_preset']:
+		msg("Hash preset has changed (%s -> %s)" %
+			(hash_preset, opts['hash_preset']))
+		changed['preset'] = True
+	else:
+		msg("Hash preset is unchanged")
+else:
+	opts['hash_preset'] = hash_preset
+
+if 'keep_old_passphrase' in opts:
+	msg("Keeping old passphrase by user request")
+else:
+	new_passwd = get_first_passphrase_from_user(
+			"new passphrase", {'quiet': True })
+
+	if new_passwd == passwd:
+		msg("Passphrase is unchanged")
+	else:
+		msg("Passphrase has changed")
+		passwd = new_passwd
+		changed['passwd'] = True
+
+if 'preset' in changed or 'passwd' in changed: # Update key ID, salt
+	msg("Will update salt and key ID")
+
+	from hashlib import sha256
+	from Crypto import Random
+
+	salt = sha256(salt + Random.new().read(128)).digest()[:salt_len]
+	key = make_key(passwd, salt, opts['hash_preset'])
+	new_key_id = make_chksum_8(key)
+	msg("Key ID changed: %s -> %s" % (key_id,new_key_id))
+	key_id = new_key_id
+	enc_seed = encrypt_seed(seed, key, opts)
+elif not 'label' in changed:
+	msg("Data unchanged.  No file will be written")
+	sys.exit(2)
+
+write_wallet_to_file(seed, passwd, key_id, salt, enc_seed, opts)

+ 75 - 0
mmgen-walletchk

@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+mmgen-walletchk: Check integrity of a mmgen deterministic wallet, display
+                 information about it and export seed and mnemonic data
+"""
+
+import sys
+import mmgen.Opts as Opts
+
+from mmgen.utils import *
+
+help_data = {
+	'desc':  """Check integrity of a %s deterministic wallet, display
+                    its information and export seed and mnemonic data."""\
+					% proj_name,
+	'usage':   "[opts] [filename]",
+	'options': """
+-h, --help             Print this help message
+-e, --echo-passphrase  Print passphrase to screen when typing it
+-m, --export-mnemonic  Export the wallet's mnemonic to file
+-s, --export-seed      Export the wallet's seed to file
+-v, --verbose          Produce more verbose output
+"""
+}
+
+short_opts = "hemsv"
+long_opts  = "help","echo_passphrase","export_mnemonic","export_seed","verbose"
+
+opts,cmd_args = Opts.process_opts(sys.argv,help_data,short_opts,long_opts)
+
+if len(cmd_args) != 1:
+	msg("One input file must be specified")
+	sys.exit(2)
+
+if 'export_mnemonic' in opts:
+	msg("Exporting mnemonic data to file by user request")
+if 'export_seed' in opts:
+	msg("Exporting seed data to file by user request")
+
+seed = get_seed_from_wallet(cmd_args[0], opts)
+msg("Wallet is OK")
+
+if 'export_mnemonic' in opts:
+	wl = get_default_wordlist()
+
+	from mmgen.mnemonic import get_mnemonic_from_seed
+	p = True if debug else False
+	mn = get_mnemonic_from_seed(seed, wl, default_wl, print_info=p)
+
+	write_mnemonic_to_file(mn, seed, opts)
+
+	if debug: print "Mnemonic:\n%s" % " ".join(mn)
+
+if 'export_seed' in opts:
+	write_seed_to_file(seed, opts)
+
+	if debug:
+		from mmgen.bitcoin import b58encode_pad
+		print "Seed: %s" % col4(b58encode_pad(seed))

+ 168 - 0
mmgen-walletgen

@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+mmgen-walletgen: Generate a mmgen deterministic wallet
+"""
+
+import sys, os
+from hashlib import sha256
+
+from mmgen.Opts import *
+from mmgen.license import *
+from mmgen.config import *
+from mmgen.walletgen import *
+from mmgen.utils import *
+prog_name = sys.argv[0].split("/")[-1]
+
+help_data = {
+	'prog_name': prog_name,
+	'desc':    "Generate a {} deterministic wallet".format(proj_name),
+	'usage':   "[opts] [infile]",
+	'options': """
+-h, --help                 Print this help message
+-d, --outdir            d  Specify an alternate directory 'd' for output
+-e, --echo-passphrase      Print passphrase to screen when typing it
+-l, --seed-len          n  Create seed of length 'n'. Options: {}
+                           (default: {})
+-L, --label             l  Label to identify this wallet (32 chars max.
+                           Allowed symbols: A-Z, a-z, 0-9, " ", "_", ".")
+-p, --hash-preset       p  Use scrypt.hash() parameters from preset 'p'
+                           (default: '{}')
+-P, --show-hash-presets    Show information on available hash presets
+-q, --quiet                Suppress warnings; overwrite files without asking
+-u, --usr-randlen       n  Get 'n' characters of randomness from the user
+                           (default: {})
+
+-b, --from-brain       l,p Generate wallet from a user-created passphrase,
+                           i.e. a "brainwallet", using seed length 'l' and
+                           hash preset 'p' (comma-separated)
+-m, --from-mnemonic        Generate wallet from an Electrum-like mnemonic
+-s, --from-seed            Generate wallet from a seed in .{S} format
+
+By default (i.e. when invoked without any of the '--from-<what>' options),
+{} generates a wallet based on a random seed.
+
+Data for the --from-<what> options will be taken from <infile> if <infile>
+is specified.  Otherwise, the user will be prompted to enter the data.
+Note that passphrase data may be input in free-form fashion, using any
+combination of spaces or tabs (or newlines, in a file) between words.
+
+BRAINWALLET NOTE:
+
+As brainwallets require especially strong hashing to thwart dictionary
+attacks, the brainwallet hash preset must be specified by the user, using
+the 'p' parameter of the '--from-brain' option.  This preset should be
+stronger than the one used for hashing the seed (i.e. the default value or
+the one specified in the '--hash-preset' option).
+
+The '--from-brain' option also requires the user to specify a seed length
+(the 'l' parameter), which overrides both the default and any one given in
+the '--seed-len' option.
+
+For a brainwallet passphrase to always generate the same keys and addresses,
+the same 'l' and 'p' parameters to '--from-brain' must be used in all future
+invocations with that passphrase.
+""".format(
+		", ".join([str(i) for i in seed_lens]),
+		seed_len,
+		hash_preset,
+		usr_randlen,
+		prog_name,
+		S=seed_ext,
+	)
+}
+
+short_opts = "hd:el:L:p:Pqu:b:ms"
+long_opts  = "help","outdir=","echo_passphrase","seed_len=","label=",\
+		"hash_preset=","show_hash_presets","quiet","usr_randlen=",\
+        "from_brain=","from_mnemonic","from_seed"
+
+opts,cmd_args = process_opts(sys.argv,help_data,short_opts,long_opts)
+
+if 'show_hash_presets' in opts: show_hash_presets()
+
+# Argument sanity checks and processing:
+
+set_if_unset_and_typeconvert(opts,(
+	('usr_randlen',usr_randlen,'int'),
+	('hash_preset',hash_preset,'str'),
+	('seed_len',seed_len,'int')
+))
+
+# Exits on invalid input
+check_opts(opts,
+	('usr_randlen','hash_preset','seed_len','outdir','label','from_brain')
+)
+
+if debug:
+	print "Processed options:     %s" % repr(opts)
+	print "Cmd args:              %s" % repr(cmd_args)
+
+if len(cmd_args) == 1 and (
+		'from_brain' in opts or
+		'from_mnemonic' in opts or
+		'from_seed' in opts):
+	infile = cmd_args[0]
+	check_infile(infile)
+elif len(cmd_args) == 0: infile = ""
+else: usage(help_data)
+
+# Begin execution
+
+if not 'quiet' in opts: do_license_msg()
+
+msg_r("Acquiring random data from your computer...")
+
+try:
+	from Crypto import Random
+	r = Random.new()
+	os_rand_data = (r.read(256),r.read(128))
+except:
+	msg("FAILED\nUnable to generate random numbers. Exiting")
+	sys.exit(2)
+
+msg("OK")
+
+if debug: display_os_random_data(os_rand_data)
+
+usr_keys,key_timings = get_random_data_from_user(opts)
+msg("")
+
+if debug: display_user_random_data(usr_keys,key_timings)
+
+usr_rand_data = sha256(usr_keys).digest() + \
+				sha256("".join(key_timings)).digest()
+
+s = get_seed(infile,opts,no_wallet=True)
+if s: seed = s
+else:
+	# Truncate random data for smaller seed lengths
+	seed = os_rand_data[0] + usr_rand_data
+	seed = sha256(seed).digest()[:opts['seed_len']/8]
+
+salt = os_rand_data[1] + usr_rand_data
+salt = sha256(salt).digest()[:salt_len]
+
+passwd = get_first_passphrase_from_user(
+		"{} wallet passphrase".format(proj_name), opts)
+
+key = make_key(passwd, salt, opts['hash_preset'])
+
+enc_seed = encrypt_seed(seed, key, opts)
+
+write_wallet_to_file(seed,passwd,make_chksum_8(key),salt,enc_seed,opts)

+ 68 - 0
mmgen/Opts.py

@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import sys, getopt
+from mmgen.config import *
+
+def usage(hd):
+	print "USAGE: %s %s" % (hd['prog_name'], hd['usage'])
+	sys.exit(2)
+
+def print_help(progname,help_data):
+	pn_len = str(len(progname)+2)
+	print ("  %-"+pn_len+"s %s")    % (progname.upper()+":", help_data['desc'])
+	print ("  %-"+pn_len+"s %s %s") % ("USAGE:", progname, help_data['usage'])
+	sep = "\n    "
+	print "  OPTIONS:"+sep+"%s" % sep.join(help_data['options'].strip().split("\n"))
+
+
+def process_opts(argv,help_data,short_opts,long_opts):
+
+	progname = argv[0].split("/")[-1]
+
+	if debug:
+		print "Short opts: %s" % repr(short_opts)
+		print "Long opts:  %s" % repr(long_opts)
+
+	long_opts  = [i.replace("_","-") for i in long_opts]
+
+	try: cl_opts, args = getopt.getopt(argv[1:], short_opts, long_opts)
+	except getopt.GetoptError as err:
+		print str(err); sys.exit(2)
+
+	opts,short_opts_l = {},[]
+
+	for i in short_opts:
+		if i == ":": short_opts_l[-1] += i
+		else:        short_opts_l     += i
+
+	for opt, arg in cl_opts:
+		if   opt in ("-h","--help"): print_help(progname,help_data); sys.exit()
+		elif opt[:2] == "--" and opt[2:] in long_opts:
+			opts[opt[2:].replace("-","_")] = True
+		elif opt[:2] == "--" and opt[2:]+"=" in long_opts:
+			opts[opt[2:].replace("-","_")] = arg
+		elif opt[0] == "-" and opt[1]     in short_opts_l:
+			opts[long_opts[short_opts_l.index(opt[1:])].replace("-","_")] = True
+		elif opt[0] == "-" and opt[1:]+":" in short_opts_l:
+			opts[long_opts[short_opts_l.index(opt[1:]+":")][:-1].replace("-","_")] = arg
+		else: assert False, "Invalid option"
+
+	if debug: print "User-selected options: %s" % repr(opts)
+
+	return opts,args

+ 38 - 0
mmgen/__init__.py

@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+MMGen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+"""
+
+__all__ = [
+	'addr.py',
+	'bitcoin.py',
+	'config.py',
+	'license.py',
+	'mn_electrum.py',
+	'mnemonic.py',
+	'mn_tirosh.py',
+	'Opts.py',
+	'utils.py',
+	'walletgen.py'
+]
+
+__version__ = '.6.0'     # See also below and setup.py
+
+# New software should look at this instead of at __version__ above.
+version_info = (0, 6, 0)    # See also above and setup.py

+ 187 - 0
mmgen/addr.py

@@ -0,0 +1,187 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+addr.py:  Address generation/display routines for mmgen suite
+"""
+
+import sys
+from hashlib import sha256, sha512
+from binascii import hexlify, unhexlify
+
+from mmgen.bitcoin import numtowif
+
+def test_for_keyconv():
+	"""
+	Test for the presence of 'keyconv' utility on system
+	"""
+
+	keyconv_exec = "keyconv"
+
+	from subprocess import Popen, PIPE
+	try:
+		p = Popen([keyconv_exec, '-h'], stdout=PIPE, stderr=PIPE)
+	except:
+		sys.stderr.write("""
+Executable '%s' unavailable.  Falling back on (slow) internal ECDSA library.
+Please install '%s' from the %s package on your system for much faster
+address generation.
+
+""" % (keyconv_exec, keyconv_exec, "vanitygen"))
+		return False
+	else:
+		return True
+
+
+def generate_addrs(seed, start, end, opts):
+	"""
+	generate_addresses(start, end, seed, opts)  => None
+
+	Generate a series of Bitcoin addresses from start to end based on a
+	seed, optionally outputting secret keys
+
+	The 'keyconv' utility will be used for address generation if
+	installed.  Otherwise an internal function is used
+
+	Supported options:
+	  print_secret, no_addresses, no_keyconv, gen_what
+	
+	Addresses are returned in a list of dictionaries with the following keys:
+	  num, sec, wif, addr
+	"""
+
+	if not 'no_addresses' in opts:
+		if 'no_keyconv' in opts or test_for_keyconv() == False:
+			sys.stderr.write("Using (slow) internal ECDSA library for address generation\n")
+			from mmgen.bitcoin import privnum2addr
+			keyconv = ""
+		else:
+			from subprocess import Popen, PIPE
+			keyconv = "keyconv"
+
+	total_addrs = end - start + 1
+
+	addrlist = []
+
+	for i in range(1, end+1):
+		seed = sha512(seed).digest() # round /i/
+
+		if i < start: continue
+
+		sys.stderr.write("\rGenerating %s: %s of %s" %
+			(opts['gen_what'], (i-start)+1, total_addrs))
+
+		# Secret key is double sha256 of seed hash round /i/
+		sec = sha256(sha256(seed).digest()).hexdigest()
+		wif = numtowif(int(sec,16))
+
+		el = { 'num': i }
+
+		if not 'print_addresses_only' in opts:
+			el['sec'] = sec
+			el['wif'] = wif
+
+		if not 'no_addresses' in opts:
+			if keyconv:
+				p = Popen([keyconv, wif], stdout=PIPE)
+				addr = dict([j.split() for j in p.stdout.readlines()])['Address:']
+			else:
+				addr = privnum2addr(int(sec,16))
+
+			el['addr'] = addr
+
+		addrlist.append(el)
+
+	sys.stderr.write("\rGenerated %s %s-%s%s\n" %
+		(opts['gen_what'], start, end, " "*9))
+
+	return addrlist
+
+
+def format_addr_data(addrlist, seed_chksum, opts):
+	"""
+	print_addresses(addrs, opts)  => None
+
+	Print out the addresses and/or keys generated by generate_addresses()
+
+	By default, prints addresses only
+
+	Output can be customized with the following command line options:
+	  print_secret
+	  no_addresses
+	  b16
+	"""
+
+	start = addrlist[0]['num']
+	end   = addrlist[-1]['num']
+
+	wif_msg = ""
+	if ('b16' in opts and 'print_secret' in opts) \
+		or 'no_addresses' in opts:
+			wif_msg = " (wif)"
+
+	fa = "%s%%-%ss %%-%ss %%s" % (
+			" "*2, len(str(end)) + (0 if 'no_addresses' in opts else 1),
+			(5 if 'print_secret' in opts else 1) + len(wif_msg)
+		)
+
+	data = []
+	data.append("%s {" % seed_chksum.upper())
+
+	for el in addrlist:
+		col1 = el['num']
+		if 'no_addresses' in opts:
+			if 'b16' in opts:
+				data.append(fa % (col1, " (hex):", el['sec']))
+				col1 = ""
+			data.append(fa % (col1, " (wif):", el['wif']))
+			if 'b16' in opts: data.append("")
+		elif 'print_secret' in opts:
+			if 'b16' in opts:
+				data.append(fa % (col1, "sec (hex):", el['sec']))
+				col1 = ""
+			data.append(fa % (col1, "sec"+wif_msg+":", el['wif']))
+			data.append(fa % ("",   "addr:", el['addr']))
+			data.append("")
+		else:
+			data.append(fa % (col1, "", el['addr']))
+
+	if not data[-1]: data.pop()
+	data.append("}")
+
+	return "\n".join(data) + "\n"
+
+
+def write_addr_data_to_file(seed, data, start, end, opts):
+
+	if 'print_addresses_only' in opts: ext = "addrs"
+	elif 'no_addresses' in opts:       ext = "keys"
+	else:                              ext = "akeys"
+
+	if 'b16' in opts: ext = ext.replace("keys","xkeys")
+
+	from mmgen.utils import write_to_file, make_chksum_8, msg
+	addr_range = str(start) if start == end else "%s-%s" % (start,end)
+	outfile = "{}[{}].{}".format(make_chksum_8(seed),addr_range,ext)
+	if 'outdir' in opts:
+		outfile = "%s/%s" % (opts['outdir'], outfile)
+
+#	print outfile; sys.exit(3)
+	write_to_file(outfile,data)
+
+	dtype = "Address" if 'print_addresses_only' in opts else "Key"
+	msg("%s data saved to file '%s'" % (dtype,outfile))

+ 153 - 0
mmgen/bitcoin.py

@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+bitcoin.py:  Bitcoin address/key conversion functions
+"""
+
+import ecdsa
+from binascii import hexlify, unhexlify
+from hashlib import sha256
+from hashlib import new as hashlib_new
+import sys
+
+# From electrum:
+# secp256k1, http://www.oid-info.com/get/1.3.132.0.10
+_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
+_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
+_b = 0x0000000000000000000000000000000000000000000000000000000000000007L
+_a = 0x0000000000000000000000000000000000000000000000000000000000000000L
+_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L
+_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L
+curve_secp256k1 = ecdsa.ellipticcurve.CurveFp( _p, _a, _b )
+generator_secp256k1 = ecdsa.ellipticcurve.Point( curve_secp256k1, _Gx, _Gy, _r )
+oid_secp256k1 = (1,3,132,0,10)
+secp256k1 = ecdsa.curves.Curve("secp256k1", curve_secp256k1, generator_secp256k1, oid_secp256k1)
+
+b58a='123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
+
+#
+# From en.bitcoin.it:
+#   The Base58 encoding used is home made, and has some differences.
+#   Especially, leading zeroes are kept as single zeroes when conversion
+#   happens.
+#
+# Test: 5JbQQTs3cnoYN9vDYaGY6nhQ1DggVsY4FJNBUfEfpSQqrEp3srk
+#
+# The "zero address":
+# 1111111111111111111114oLvT2 (use step2 = ("0" * 40) to generate)
+#
+def _pubhex2addr(pubhex):
+	step1 = sha256(unhexlify(pubhex)).digest()
+	step2 = hashlib_new('ripemd160',step1).hexdigest()
+	# See above:
+	extra_ones = (len(step2) - len(step2.lstrip("0"))) / 2
+	step3 = sha256(unhexlify('00'+step2)).digest()
+	step4 = sha256(step3).hexdigest()
+	pubkey = int(step2 + step4[:8], 16)
+	return "1" + ("1" * extra_ones) + _numtob58(pubkey)
+
+def privnum2addr(numpriv):
+	pko = ecdsa.SigningKey.from_secret_exponent(numpriv,secp256k1)
+	pubkey = hexlify(pko.get_verifying_key().to_string())
+	return _pubhex2addr('04'+pubkey)
+
+# Reworked code from here:
+
+def _numtob58(num):
+	b58conv,i = [],0
+	while True:
+		n = num / (58**i); i += 1
+		if not n: break
+		b58conv.append(b58a[n % 58])
+	return ''.join(b58conv)[::-1]
+
+def _b58tonum(b58num):
+	for i in b58num:
+		if not i in b58a:
+			print "Invalid symbol in b58 number: '%s'" % i
+			sys.exit(9)
+
+	b58deconv = []
+	b58num_r = b58num[::-1]
+	for i in range(len(b58num)):
+		idx = b58a.index(b58num_r[i])
+		b58deconv.append(idx * (58**i))
+	return sum(b58deconv)
+
+def numtowif(numpriv):
+	step1 = '80'+hex(numpriv)[2:].rstrip('L').zfill(64)
+	step2 = sha256(unhexlify(step1)).digest()
+	step3 = sha256(step2).hexdigest()
+	key = step1 + step3[:8]
+	return _numtob58(int(key,16))
+
+
+# The following are mmgen internal (non-bitcoin) b58 functions
+#
+# Drop-in replacements for b64encode() and b64decode():
+# (well, not exactly: they yield numeric but not bytewise equivalence)
+
+def b58encode(s):
+	if s == "": return ""
+	num = int(hexlify(s),16)
+	return _numtob58(num)
+
+def b58decode(b58num):
+	if b58num == "": return ""
+	# Zap all spaces:
+	num = _b58tonum(b58num.translate(None,' \t\n\r'))
+	out = hex(num)[2:].rstrip('L')
+	return unhexlify("0" + out if len(out) % 2 else out)
+
+# These yield bytewise equivalence in our special cases:
+
+bin_lens = 16,24,32
+b58_lens = 22,33,44
+
+def _b58_pad(s,a,b,pad,f,w):
+	try:
+		outlen = b[a.index(len(s))]
+	except:
+	 	print "_b58_pad() accepts only %s %s bytes long "\
+		 "(input was %s bytes)" % (w,",".join([str(i) for i in a]),len(s))
+		sys.exit(9)
+
+	out = f(s)
+	return "%s%s" % (pad * (outlen - len(out)), out)
+
+def b58encode_pad(s):
+	return _b58_pad(s,
+		a=bin_lens,b=b58_lens,pad="1",f=b58encode,w="binary strings")
+
+def b58decode_pad(s):
+	return _b58_pad(s,
+		a=b58_lens,b=bin_lens,pad='\0',f=b58decode,w="base 58 numbers")
+
+
+################### FUNCTIONS UNUSED BY MMGEN: ###################
+
+# To check validity, recode with numtowif()
+def wiftonum(wifpriv):
+	num = _b58tonum(wifpriv)
+	return (num % (1<<288)) >> 32
+
+def wiftohex(wifpriv):
+	key = hex(_b58tonum(wifpriv))[2:].rstrip('L')
+	round1 = sha256(unhexlify(key[:66])).digest()
+	round2 = sha256(round1).hexdigest()
+	return key[2:66] if (key[:2] == '80' and key[66:] == round2[:8]) else False

+ 48 - 0
mmgen/config.py

@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+config.py:  Constants and configuration options for the mmgen suite
+"""
+proj_name     = "mmgen"
+seed_ext      = "mmseed"
+default_wl    = "electrum"
+#default_wl    = "tirosh"
+
+seed_lens = 128,192,256
+seed_len  = 256
+
+mnemonic_lens = [i / 32 * 3 for i in seed_lens]
+
+from os import getenv
+debug = True if getenv("MMGEN_DEBUG") else False
+
+passwd_max_tries = 5
+max_randlen,min_randlen = 80,5
+usr_randlen = 20
+salt_len    = 16
+
+hash_preset = '3'
+hash_presets = {
+#   Scrypt params:
+#   ID    N      p  r
+	'1': [2**12, 8, 1],
+	'2': [2**13, 8, 4],
+	'3': [2**14, 8, 8],
+	'4': [2**15, 8, 12],
+	'5': [2**16, 8, 16],
+}

+ 649 - 0
mmgen/license.py

@@ -0,0 +1,649 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+license.py:  Show the license
+"""
+
+import sys
+from mmgen.config import proj_name
+from mmgen.utils import msg, msg_r
+
+gpl = {
+	'warning': """
+{} Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+This program comes with ABSOLUTELY NO WARRANTY.
+This is free software, and you are welcome to
+redistribute it under certain conditions.
+""".format(proj_name),
+	'prompt': """
+Press 'c' for conditions, 'w' for warranty info,
+or ENTER to continue:
+""",
+	'conditions': """
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+""",
+	'warranty': """
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+"""
+}
+
+def do_license_msg():
+	ls = "\n  "
+	msg("  " + ls.join(gpl['warning'].strip().split("\n")))
+
+	try:
+		import os
+		os.system(
+		"stty -icanon min 1 time 0 -echo -echoe -echok -echonl -crterase noflsh"
+		)
+		pager = os.environ['PAGER'] if 'PAGER' in os.environ else 'more'
+
+		while True:
+			msg_r(ls + ls.join(gpl['prompt'].strip().split("\n")) + " ")
+			reply = sys.stdin.read(1)
+			if   reply == 'c':
+				m = gpl['conditions']
+			elif reply == 'w':
+				m = gpl['warranty']
+			else: break
+			p = os.popen(pager, 'w')
+			p.write(m)
+			p.close()
+	except:
+		msg("\nInterrupted by user")
+		sys.exit(1)
+	finally:
+		os.system("stty sane")

+ 1657 - 0
mmgen/mn_electrum.py

@@ -0,0 +1,1657 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# electrum wordlist
+# Electrum - lightweight Bitcoin client
+# Copyright (C) 2011 thomasv@gitorious
+# list of words from:
+# http://en.wiktionary.org/wiki/Wiktionary:Frequency_lists/Contemporary_poetry
+
+# From mmgen:
+#   this is a sorted version of the wordlist.
+#   Original can be found here:
+#     https://github.com/spesmilo/electrum/blob/master/lib/mnemonic.py
+
+electrum_words = """
+able
+about
+above
+abuse
+accept
+accident
+ache
+acid
+across
+act
+action
+actually
+add
+admire
+admit
+adore
+advice
+affection
+afraid
+after
+afternoon
+again
+against
+age
+agony
+agree
+ahead
+aim
+air
+alas
+alive
+allow
+almost
+alone
+along
+already
+also
+alter
+although
+always
+amaze
+among
+ancient
+angel
+anger
+angry
+animal
+annoy
+another
+answer
+any
+anymore
+anyone
+anything
+anyway
+anywhere
+apart
+apologize
+appear
+apple
+appreciate
+approach
+army
+around
+arrive
+arrow
+art
+ash
+ashamed
+aside
+ask
+asleep
+attack
+attempt
+attention
+aunt
+autumn
+avoid
+await
+awake
+awaken
+away
+awe
+awkward
+baby
+back
+bag
+balance
+ball
+bang
+bank
+bar
+bare
+barely
+bathroom
+battle
+beam
+beard
+beaten
+beautiful
+beauty
+became
+become
+bedroom
+bee
+been
+before
+beg
+began
+begin
+begun
+behind
+belief
+believe
+belly
+belong
+bench
+beneath
+beside
+best
+better
+between
+beyond
+bid
+bird
+birth
+birthday
+bit
+bite
+bitter
+black
+blade
+blame
+blank
+blanket
+bleed
+blend
+bless
+blind
+blink
+bliss
+block
+blonde
+blood
+bloody
+bloom
+blossom
+blow
+blue
+blur
+blush
+board
+boat
+body
+bold
+bomb
+bond
+bone
+book
+boom
+born
+both
+bother
+bottle
+bottom
+bought
+bounce
+bound
+bowl
+box
+boyfriend
+brain
+branch
+brand
+brave
+bread
+break
+breast
+breath
+breathe
+breeze
+bridge
+bright
+bring
+broke
+broken
+brother
+brown
+bruise
+brush
+bubble
+build
+built
+bullet
+bump
+burden
+burn
+burst
+bury
+bus
+busy
+butterfly
+button
+buy
+cage
+calm
+came
+candle
+canvas
+cap
+capture
+card
+careful
+carefully
+caress
+carry
+carve
+cast
+catch
+caught
+cause
+cease
+ceiling
+cell
+center
+certain
+certainly
+chain
+chair
+chance
+change
+character
+charm
+chase
+cheap
+cheat
+check
+cheek
+cheer
+cheese
+chest
+child
+childhood
+children
+chill
+chin
+chocolate
+choice
+choke
+choose
+church
+cigarette
+circle
+city
+claim
+class
+claw
+clay
+clean
+clear
+clearly
+click
+climb
+cling
+clock
+close
+closet
+clothes
+cloud
+clue
+clutch
+coat
+coffee
+cold
+collapse
+collect
+college
+color
+comfort
+commit
+common
+companion
+company
+compare
+complain
+complete
+completely
+concern
+concrete
+confidence
+confuse
+confusion
+connect
+connection
+consider
+constant
+constantly
+consume
+content
+continue
+control
+conversation
+cookie
+cool
+core
+corner
+cost
+couch
+count
+country
+couple
+courage
+course
+cousin
+cover
+coward
+crack
+crap
+crash
+crave
+crawl
+crazy
+creak
+cream
+create
+creation
+creator
+creature
+creek
+creep
+crime
+crimson
+cross
+crowd
+cruel
+crumble
+crush
+cry
+crystal
+cup
+curl
+curse
+curtain
+curve
+cute
+dad
+daddy
+daily
+damn
+dance
+danger
+dark
+darkness
+darling
+dart
+date
+daughter
+dawn
+deadly
+deal
+dear
+death
+decay
+decide
+decision
+deep
+deeply
+defeat
+defense
+define
+delicate
+delight
+demand
+demon
+deny
+depend
+depress
+depression
+depth
+descend
+describe
+desert
+deserve
+desire
+desk
+despair
+desperate
+desperately
+despite
+destination
+destroy
+determine
+devil
+dew
+diamond
+difference
+different
+dig
+dim
+dinner
+direction
+dirt
+dirty
+disappear
+discover
+disguise
+dish
+distance
+distant
+doctor
+dog
+doll
+doom
+door
+dot
+double
+doubt
+dove
+down
+drag
+dragon
+drama
+draw
+drawn
+dread
+dream
+dreamer
+dress
+drift
+drink
+drive
+driver
+drop
+drove
+drug
+drum
+drunk
+dry
+duck
+dude
+due
+dull
+dumb
+during
+dust
+dusty
+dwell
+each
+eager
+early
+earth
+easily
+easy
+eat
+echo
+edge
+effort
+egg
+either
+embarrass
+embrace
+emotion
+emptiness
+empty
+end
+endless
+enemy
+energy
+engine
+enjoy
+enough
+enter
+entire
+erase
+escape
+especially
+essence
+eternal
+eternity
+even
+evening
+eventually
+ever
+everybody
+everyday
+everyone
+everything
+everytime
+everywhere
+evil
+exactly
+example
+except
+excuse
+exist
+existence
+expect
+experience
+explain
+explode
+explore
+express
+expression
+eye
+fact
+fade
+fail
+faint
+fairy
+faith
+false
+familiar
+family
+fan
+fantasy
+fate
+father
+fault
+favorite
+fear
+feast
+feather
+feed
+feet
+felicity
+few
+field
+figure
+fill
+final
+finally
+find
+finger
+finish
+fire
+first
+fish
+fist
+five
+fix
+flag
+flame
+flare
+flash
+flat
+flesh
+flicker
+flight
+flip
+flirt
+float
+flood
+floor
+flow
+flower
+flutter
+fly
+focus
+foe
+fog
+fold
+follow
+foot
+football
+footstep
+force
+forehead
+forest
+forever
+forget
+forgive
+forgot
+forgotten
+form
+former
+forth
+forward
+fought
+foul
+fragile
+frame
+freak
+free
+freedom
+freely
+freeze
+fresh
+friend
+friendship
+fright
+frighten
+front
+frost
+frown
+frozen
+fruit
+frustrate
+fully
+funny
+fur
+further
+future
+gain
+game
+garden
+gas
+gasp
+gather
+gay
+gaze
+generation
+gentle
+gently
+ghost
+giant
+gift
+giggle
+girl
+girlfriend
+give
+given
+glad
+glance
+glare
+glass
+glide
+glorious
+glory
+glove
+glow
+goal
+god
+gone
+good
+goodbye
+goose
+got
+gotta
+gotten
+government
+grab
+grace
+grade
+grand
+grandma
+grant
+grasp
+grass
+great
+green
+greet
+grew
+grey
+grief
+grin
+grip
+ground
+group
+grow
+grown
+guard
+guess
+guide
+guilt
+guilty
+guitar
+gun
+guy
+hair
+half
+hallway
+hand
+handle
+hang
+happen
+happiness
+happy
+hardly
+harm
+harmony
+harsh
+hate
+hatred
+haunt
+heal
+health
+heard
+heart
+heartbeat
+heat
+heaven
+heavy
+heel
+held
+hello
+help
+here
+hero
+hey
+hidden
+hide
+high
+hill
+history
+hit
+hollow
+holy
+home
+honest
+honey
+honor
+hook
+hop
+hope
+hopefully
+horizon
+horrible
+horse
+hospital
+hour
+house
+however
+howl
+hug
+huge
+hum
+human
+hundred
+hunger
+hungry
+hunt
+hurl
+hurry
+hurt
+husband
+ice
+idea
+idiot
+ignorance
+ignore
+illuminate
+illusion
+image
+imagination
+imagine
+important
+impossible
+inch
+indeed
+inhale
+ink
+inner
+innocence
+innocent
+insane
+inside
+instead
+insult
+interest
+into
+invisible
+invite
+iron
+itself
+jaw
+jealous
+jeans
+job
+jock
+join
+joke
+journey
+joy
+judge
+juice
+jump
+just
+keep
+kept
+key
+kick
+kid
+kill
+king
+kingdom
+kiss
+kitchen
+knee
+knife
+knock
+know
+knowledge
+known
+lace
+lady
+laid
+land
+language
+large
+laugh
+laughter
+law
+lazy
+lead
+leaf
+leap
+learn
+least
+leave
+led
+left
+leg
+less
+lesson
+letter
+level
+lick
+lifeless
+lift
+lightning
+like
+limb
+limit
+line
+linger
+lip
+liquid
+listen
+little
+lonely
+long
+look
+loose
+lord
+loser
+loss
+lot
+loud
+love
+lovely
+lucky
+lunch
+lung
+lust
+machine
+made
+magic
+make
+mama
+manage
+many
+march
+mark
+marry
+mask
+mass
+master
+match
+math
+matter
+maybe
+mean
+meant
+measure
+meet
+melody
+melt
+memory
+men
+mend
+mention
+mercy
+mere
+mess
+message
+metal
+middle
+midnight
+might
+mighty
+milk
+million
+mind
+mine
+minute
+mirror
+misery
+mist
+mistake
+mix
+moan
+mock
+mold
+mom
+moment
+money
+monkey
+monster
+month
+moon
+moonlight
+moral
+more
+morning
+mostly
+mother
+motion
+mountain
+mourn
+mouth
+movement
+movie
+much
+mud
+mumble
+murder
+muscle
+muse
+music
+mutter
+myself
+mystery
+nail
+naked
+name
+nation
+natural
+nature
+near
+nearly
+neck
+need
+needle
+neighbor
+neither
+nerd
+nerve
+nervous
+never
+new
+next
+nice
+night
+nightmare
+nine
+nobody
+nod
+noise
+normal
+north
+nose
+note
+nothing
+notice
+nowhere
+numb
+number
+object
+observe
+obviously
+ocean
+odd
+ode
+off
+offer
+often
+okay
+once
+only
+open
+opinion
+opposite
+orange
+order
+other
+ourselves
+out
+outside
+over
+own
+pack
+page
+painful
+paint
+pair
+pale
+palm
+pants
+paper
+paradise
+parent
+park
+party
+pass
+passion
+past
+path
+pathetic
+patience
+patient
+pattern
+pause
+pay
+peace
+peaceful
+peach
+peel
+peer
+pen
+pencil
+people
+perfect
+perfection
+perfectly
+perhaps
+person
+petal
+phone
+physical
+picture
+pie
+piece
+pierce
+pig
+pile
+pillow
+pink
+pity
+place
+plain
+plan
+planet
+plant
+plastic
+plate
+play
+please
+pleasure
+pocket
+poem
+poet
+poetry
+point
+poison
+ponder
+pool
+poor
+pop
+position
+possess
+possible
+possibly
+pound
+pour
+power
+powerful
+practice
+praise
+pray
+prayer
+precious
+prefer
+prepare
+presence
+present
+press
+pressure
+pretend
+pretty
+price
+pride
+prince
+princess
+probably
+problem
+process
+promise
+protect
+proud
+prove
+puff
+pull
+pulse
+punch
+pure
+purple
+purpose
+push
+put
+puzzle
+queen
+question
+quick
+quickly
+quiet
+quietly
+quit
+quite
+rabbit
+radio
+rainbow
+raise
+random
+rant
+rape
+rare
+rather
+raw
+reach
+ready
+real
+reality
+realize
+really
+reason
+rebel
+recall
+receive
+red
+reflect
+reflection
+refuse
+regret
+relationship
+relax
+release
+remain
+remember
+remind
+remove
+repeat
+replace
+reply
+respect
+respond
+rest
+retreat
+return
+reveal
+revenge
+rhyme
+rhythm
+rich
+ring
+rip
+ripple
+rise
+river
+road
+roam
+roar
+rock
+roll
+root
+rope
+rose
+rough
+royal
+rub
+rude
+ruin
+rule
+run
+rush
+sad
+sadness
+safe
+said
+sail
+salt
+salty
+sanctuary
+sane
+sanity
+sat
+satisfy
+save
+savior
+scale
+scar
+scary
+scatter
+scene
+scent
+school
+score
+scrape
+scratch
+scream
+screen
+screw
+sea
+search
+season
+second
+secret
+seek
+seem
+self
+selfish
+sense
+sent
+sentence
+separate
+serious
+serve
+settle
+seven
+several
+shade
+shadow
+shall
+shame
+shape
+sharp
+shatter
+sheep
+sheet
+shelter
+shield
+shift
+shimmer
+shine
+shiny
+ship
+shirt
+shiver
+shock
+shoe
+shook
+shoot
+shore
+should
+shoulder
+shout
+shove
+show
+shower
+shown
+shut
+shy
+sick
+sigh
+sign
+silence
+silent
+silently
+silly
+silver
+simple
+simply
+since
+single
+sink
+sister
+situation
+six
+size
+skill
+skin
+skip
+sky
+slam
+slap
+sleep
+slept
+slice
+slide
+slight
+slightly
+slowly
+small
+smart
+smell
+smile
+smoke
+smooth
+snake
+snap
+sneak
+snow
+soak
+soar
+sob
+social
+society
+soft
+softly
+soldier
+some
+somebody
+someday
+somehow
+someone
+something
+sometimes
+somewhere
+son
+song
+soon
+soothe
+sorrow
+sorry
+sort
+soul
+sound
+space
+speak
+special
+speed
+spell
+spend
+spider
+spill
+spin
+spine
+spiral
+spirit
+split
+spoken
+sport
+spot
+spread
+spring
+square
+squeeze
+stab
+stage
+stain
+stair
+stand
+stare
+start
+state
+stay
+steady
+steal
+steel
+step
+stick
+still
+sting
+stir
+stock
+stole
+stolen
+stomach
+stone
+stood
+stop
+storm
+story
+straight
+strain
+strange
+stranger
+stray
+stream
+street
+strength
+stress
+stretch
+strife
+strike
+string
+strip
+stroke
+strong
+struggle
+stubborn
+stuck
+student
+study
+stuff
+stumble
+stun
+stupid
+style
+subject
+such
+sudden
+suddenly
+suffer
+suffocate
+suicide
+suit
+summer
+sunlight
+sunset
+support
+suppose
+sure
+surely
+surface
+surprise
+surround
+survive
+suspend
+swallow
+sway
+swear
+sweat
+sweet
+swell
+swim
+swing
+swirl
+sword
+sympathy
+table
+taint
+take
+taken
+talent
+talk
+tangle
+tap
+task
+taste
+taught
+tea
+teach
+teacher
+team
+tease
+teeth
+tell
+tender
+terrible
+terror
+test
+thank
+them
+themselves
+then
+there
+thick
+thigh
+thing
+think
+third
+thorn
+those
+thought
+thousand
+thread
+threaten
+three
+threw
+throat
+throne
+through
+throughout
+throw
+thrown
+thump
+thunder
+tickle
+tide
+tie
+tight
+tightly
+time
+tiny
+tired
+today
+toe
+together
+tomorrow
+tongue
+tonight
+too
+tool
+torment
+torture
+toss
+total
+touch
+tough
+toward
+tower
+town
+trace
+trade
+trail
+train
+travel
+treasure
+treat
+tree
+tremble
+trick
+trickle
+trip
+trouble
+truck
+true
+truly
+trust
+truth
+try
+tuck
+tumble
+tune
+turn
+twenty
+twice
+twirl
+twist
+two
+type
+ugly
+unable
+uncle
+under
+underneath
+understand
+universe
+unknown
+unless
+unlike
+unseen
+upon
+upset
+use
+useless
+usually
+utter
+vain
+valley
+value
+vast
+veil
+vein
+velvet
+verse
+very
+victim
+view
+violence
+vision
+visit
+voice
+void
+volume
+waist
+wait
+walk
+wall
+wander
+want
+war
+warm
+warmth
+warn
+warrior
+wash
+waste
+watch
+water
+wave
+weak
+weakness
+weapon
+weary
+weather
+weave
+week
+weep
+weight
+weird
+welcome
+wet
+whatever
+wheel
+whenever
+whether
+whisper
+whistle
+white
+whole
+wife
+wild
+win
+window
+winter
+wipe
+wise
+wish
+witch
+within
+wolf
+woman
+women
+won
+wonder
+wonderful
+wood
+work
+world
+worry
+worse
+worship
+worst
+worth
+worthless
+wound
+wow
+wrap
+wrinkle
+wrist
+write
+written
+wrong
+wrote
+yard
+yeah
+yearn
+yell
+yellow
+yesterday
+yet
+young
+yours
+yourself
+youth
+"""

+ 1658 - 0
mmgen/mn_tirosh.py

@@ -0,0 +1,1658 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Oren Tirosh wordlist
+# Copyright (c) 2000 Oren Tirosh <oren@hishome.net>
+
+# From mmgen: this is a sorted version of the wordlist
+
+tirosh_words = """
+abraham
+absent
+absorb
+academy
+accent
+acid
+acrobat
+action
+active
+actor
+adam
+address
+adios
+admiral
+adrian
+africa
+agatha
+agenda
+agent
+airline
+airport
+alabama
+aladdin
+alamo
+alarm
+alaska
+albert
+albino
+album
+alcohol
+alert
+alex
+alfonso
+alfred
+algebra
+alias
+alibi
+alice
+alien
+almanac
+almond
+aloha
+alpha
+alpine
+amadeus
+amanda
+amazon
+amber
+ambient
+amen
+america
+amigo
+ammonia
+analog
+analyze
+anatomy
+andrea
+andy
+angel
+animal
+anita
+annual
+answer
+antenna
+antonio
+anvil
+apollo
+appear
+apple
+april
+apropos
+arcade
+archer
+archive
+arctic
+arena
+ariel
+arizona
+armada
+armor
+arnold
+aroma
+arrow
+arsenal
+arthur
+artist
+asia
+aspect
+aspirin
+athena
+athlete
+atlanta
+atlas
+atomic
+audio
+august
+aurora
+austin
+austria
+avalon
+avatar
+avenue
+average
+axiom
+axis
+aztec
+baboon
+baby
+bagel
+baggage
+bahama
+baker
+balance
+bali
+ballad
+ballet
+balloon
+balsa
+bambino
+bamboo
+banana
+bandit
+banjo
+bank
+barbara
+barcode
+baron
+basic
+basil
+basket
+battery
+bazaar
+bazooka
+beach
+beast
+beatles
+beauty
+before
+begin
+belgium
+benefit
+benny
+berlin
+bermuda
+bernard
+betty
+between
+beyond
+bicycle
+bikini
+billy
+binary
+bingo
+biology
+biscuit
+bishop
+bison
+blast
+bless
+blitz
+block
+blonde
+blue
+bogart
+bombay
+bonanza
+bonjour
+bonus
+book
+border
+boris
+boston
+bottle
+boxer
+brain
+brandy
+brave
+bravo
+brazil
+bread
+break
+brenda
+bridge
+brigade
+british
+broken
+bronze
+brother
+brown
+bruce
+bruno
+brush
+bucket
+budget
+buenos
+buffalo
+bundle
+burger
+burma
+button
+buzzer
+byte
+cabaret
+cabinet
+cable
+cactus
+cadet
+caesar
+cafe
+cairo
+cake
+calypso
+camel
+camera
+camilla
+campus
+canada
+canal
+canary
+candid
+candle
+cannon
+canoe
+cantina
+canvas
+canyon
+capital
+capitan
+capsule
+caramel
+caravan
+carbon
+career
+cargo
+carlo
+carmen
+carol
+carpet
+carrot
+cartel
+cartoon
+casino
+castle
+castro
+catalog
+cave
+caviar
+cecilia
+cello
+celtic
+cement
+center
+century
+ceramic
+chamber
+chance
+change
+channel
+chant
+chaos
+chapter
+chariot
+charlie
+charm
+charter
+cheese
+chef
+chemist
+cherry
+chess
+chicago
+chicken
+chief
+child
+china
+choice
+chris
+chrome
+cigar
+cinema
+cipher
+circle
+circus
+citizen
+citrus
+city
+civil
+clara
+clarion
+clark
+classic
+claudia
+clean
+clever
+client
+cliff
+climax
+clinic
+clock
+clone
+cloud
+club
+cobalt
+cobra
+cockpit
+coconut
+cola
+collect
+college
+colombo
+colony
+color
+combat
+comedy
+comet
+command
+common
+compact
+company
+compare
+compass
+complex
+comrade
+conan
+concept
+concert
+condor
+conduct
+congo
+connect
+consul
+contact
+content
+context
+contour
+control
+convert
+cool
+copper
+copy
+coral
+corner
+corona
+correct
+cosmos
+costume
+cotton
+couple
+courage
+cover
+cowboy
+crack
+craft
+crash
+crater
+credit
+cricket
+crimson
+critic
+crown
+crystal
+cuba
+cubic
+culture
+cupid
+current
+cycle
+cyclone
+dallas
+dance
+daniel
+danube
+darwin
+data
+david
+deal
+decade
+decide
+decimal
+declare
+degree
+delete
+deliver
+delphi
+delta
+deluxe
+demand
+demo
+denmark
+denver
+depend
+derby
+desert
+design
+desire
+detail
+detect
+develop
+dexter
+diagram
+dialog
+diamond
+diana
+diego
+diesel
+diet
+digital
+dilemma
+dinner
+diploma
+direct
+disco
+disney
+dispute
+distant
+divide
+doctor
+dolby
+dollar
+domain
+domingo
+dominic
+domino
+donald
+donor
+door
+double
+dragon
+drama
+dream
+drink
+driver
+druid
+drum
+dublin
+duet
+dynamic
+dynasty
+eagle
+earth
+east
+easy
+echo
+eclipse
+ecology
+economy
+eddie
+edgar
+edison
+edition
+editor
+educate
+edward
+effect
+ego
+egypt
+elastic
+electra
+elegant
+element
+elite
+elvis
+email
+emerald
+emotion
+empire
+empty
+energy
+engine
+english
+enigma
+enjoy
+enrico
+episode
+epoxy
+equal
+equator
+eric
+erosion
+escape
+escort
+eternal
+ethnic
+europe
+evening
+event
+everest
+evident
+evita
+exact
+example
+except
+exhibit
+exile
+exit
+exodus
+exotic
+expand
+explain
+explore
+export
+express
+extend
+extra
+extreme
+fabric
+factor
+falcon
+fame
+family
+famous
+fantasy
+farmer
+fashion
+fast
+father
+fax
+felix
+ferrari
+fiber
+fiction
+fidel
+field
+fiesta
+figure
+film
+filter
+final
+finance
+finish
+finland
+fiona
+fire
+first
+fish
+flag
+flame
+flash
+flex
+flipper
+float
+flood
+floor
+florida
+flower
+fluid
+flute
+focus
+folio
+food
+forbid
+ford
+forest
+forever
+forget
+formal
+format
+formula
+fortune
+forum
+forward
+fossil
+fractal
+fragile
+frame
+france
+frank
+freddie
+freedom
+fresh
+friday
+friend
+frog
+front
+frozen
+fruit
+fuel
+fuji
+future
+gabriel
+galaxy
+galileo
+gallery
+gallop
+game
+gamma
+garage
+garbo
+garcia
+garden
+garlic
+gate
+gemini
+general
+genesis
+genetic
+geneva
+genius
+gentle
+george
+germany
+giant
+gibson
+gilbert
+ginger
+giraffe
+gizmo
+glass
+global
+gloria
+goblin
+gold
+golf
+gondola
+gong
+good
+gopher
+gordon
+gorilla
+gossip
+grace
+gram
+grand
+granite
+graph
+gravity
+gray
+greek
+green
+gregory
+grid
+griffin
+grille
+ground
+group
+guest
+guide
+guitar
+guru
+gustav
+gyro
+habitat
+hair
+halt
+hamlet
+hammer
+hand
+happy
+harbor
+harlem
+harmony
+harris
+harvard
+harvest
+havana
+hawaii
+hazard
+heart
+heaven
+heavy
+helena
+helium
+hello
+henry
+herbert
+herman
+heroic
+hexagon
+hilton
+hippie
+history
+hobby
+holiday
+honey
+hope
+horizon
+horse
+hostel
+hotel
+house
+human
+humor
+hunter
+husband
+hydro
+ibiza
+iceberg
+icon
+idea
+igloo
+igor
+image
+imagine
+imitate
+immune
+impact
+import
+inca
+inch
+index
+india
+indigo
+infant
+info
+ingrid
+initial
+input
+insect
+inside
+instant
+invent
+invest
+invite
+iris
+iron
+isabel
+isotope
+italian
+ivan
+ivory
+jacket
+jackson
+jacob
+jaguar
+jamaica
+james
+janet
+japan
+jargon
+jasmine
+jason
+java
+jazz
+jeep
+jerome
+jessica
+jester
+jet
+jimmy
+job
+joel
+john
+join
+joker
+jordan
+joseph
+joshua
+journal
+judge
+judo
+juice
+juliet
+julius
+july
+jumbo
+jump
+june
+jungle
+junior
+jupiter
+justice
+justin
+kansas
+karate
+karl
+karma
+kayak
+kermit
+kevin
+kilo
+kimono
+kinetic
+king
+kitchen
+kiwi
+koala
+korea
+labor
+ladder
+lady
+lagoon
+lake
+laptop
+laser
+latin
+laura
+lava
+lazarus
+learn
+lecture
+left
+legacy
+legal
+legend
+lemon
+leonid
+lesson
+letter
+level
+lexicon
+liberal
+libra
+license
+life
+light
+lima
+limbo
+limit
+linda
+linear
+lion
+liquid
+list
+liter
+lithium
+little
+llama
+lobby
+lobster
+local
+locate
+logic
+logo
+lola
+london
+lopez
+lorenzo
+lotus
+love
+loyal
+lucas
+lucky
+lunar
+lunch
+machine
+macro
+madam
+madonna
+madrid
+maestro
+magenta
+magic
+magnet
+magnum
+mailbox
+major
+malta
+mama
+mambo
+mammal
+manager
+mango
+manila
+manual
+marble
+marco
+margo
+marina
+marion
+market
+mars
+martin
+marvin
+mary
+mask
+master
+match
+matrix
+maximum
+maxwell
+mayday
+mayor
+maze
+meaning
+media
+medical
+medusa
+mega
+melody
+melon
+member
+memo
+memphis
+mental
+mentor
+menu
+mercury
+mercy
+message
+metal
+meteor
+meter
+method
+metro
+mexico
+miami
+michael
+micro
+middle
+miguel
+mike
+milan
+mile
+milk
+miller
+million
+mimic
+mimosa
+mineral
+minimum
+minus
+minute
+miracle
+mirage
+miranda
+mirror
+mission
+mister
+mixer
+mobile
+model
+modem
+modern
+modest
+modular
+moment
+monaco
+monarch
+monday
+money
+monica
+monitor
+monkey
+mono
+monster
+montana
+moral
+morgan
+morning
+morph
+morris
+moses
+motel
+mother
+motif
+motor
+mouse
+mozart
+multi
+museum
+music
+mustang
+mystery
+nadia
+nancy
+natasha
+native
+nato
+natural
+navy
+nebula
+nectar
+needle
+nelson
+neon
+nepal
+neptune
+nerve
+network
+neuron
+neutral
+nevada
+never
+news
+newton
+next
+nice
+nickel
+night
+nikita
+nina
+ninja
+nirvana
+nissan
+nitro
+nixon
+nobel
+nobody
+noise
+nominal
+normal
+north
+norway
+nothing
+nova
+novel
+nuclear
+null
+number
+numeric
+nurse
+nylon
+oasis
+oberon
+object
+observe
+ocean
+octavia
+october
+octopus
+office
+ohio
+olga
+oliver
+olivia
+olympic
+omega
+open
+opera
+opinion
+optic
+optimal
+option
+opus
+orange
+orbit
+orca
+orchid
+order
+oregano
+organic
+orient
+origami
+origin
+orinoco
+orion
+orlando
+oscar
+othello
+outside
+oval
+owner
+oxford
+oxygen
+ozone
+pablo
+pacific
+package
+page
+pagoda
+paint
+palace
+palma
+pamela
+panama
+pancake
+panda
+pandora
+panel
+panic
+panther
+papa
+paper
+paprika
+parade
+paradox
+pardon
+parent
+paris
+parker
+parking
+parody
+parole
+partner
+passage
+passive
+pasta
+pastel
+patent
+patient
+patriot
+patrol
+patron
+pattern
+paul
+peace
+pearl
+pedro
+pegasus
+pelican
+pencil
+penguin
+people
+pepper
+percent
+perfect
+perform
+perfume
+period
+permit
+person
+peru
+phantom
+philips
+phoenix
+phone
+photo
+phrase
+piano
+picasso
+picnic
+picture
+pierre
+pigment
+pilgrim
+pilot
+pinball
+pioneer
+pirate
+pixel
+pizza
+place
+planet
+plasma
+plaster
+plastic
+plate
+plato
+plaza
+plume
+pluto
+pocket
+podium
+poem
+poetic
+pogo
+point
+poker
+polaris
+police
+polite
+politic
+polka
+polo
+polygon
+poncho
+pony
+popcorn
+popular
+portal
+postage
+postal
+potato
+powder
+prague
+precise
+prefix
+prelude
+premium
+prepare
+present
+press
+presto
+pretend
+pretty
+price
+prime
+prince
+printer
+prism
+private
+prize
+process
+product
+profile
+profit
+program
+project
+promise
+promo
+protect
+protein
+proton
+provide
+proxy
+public
+pulse
+puma
+pump
+pupil
+puzzle
+pyramid
+python
+quality
+quarter
+quasi
+quebec
+queen
+quest
+quick
+quiet
+quiz
+quota
+rabbit
+race
+rachel
+radar
+radical
+radio
+radius
+rainbow
+raja
+ralph
+ramirez
+random
+ranger
+rapid
+ravioli
+raymond
+rebel
+record
+recycle
+reflex
+reform
+regard
+region
+regular
+relax
+remark
+remote
+rent
+repair
+reply
+report
+reptile
+reserve
+respect
+respond
+result
+resume
+retro
+reunion
+reverse
+reward
+rhino
+ribbon
+ricardo
+richard
+rider
+right
+ringo
+rio
+risk
+ritual
+rival
+river
+riviera
+road
+robert
+robin
+robot
+rocket
+rodent
+rodeo
+roger
+roman
+romeo
+rondo
+roof
+rose
+round
+rover
+royal
+rubber
+ruby
+rudolf
+rufus
+russian
+sabine
+sabrina
+saddle
+safari
+saga
+sahara
+sailor
+saint
+salad
+salami
+salary
+salmon
+salon
+salsa
+salt
+salute
+samba
+sample
+samuel
+sandra
+santana
+sardine
+satire
+saturn
+savage
+scale
+scarlet
+scholar
+school
+scoop
+scorpio
+scratch
+screen
+script
+scroll
+scuba
+season
+second
+secret
+section
+sector
+secure
+segment
+select
+seminar
+senator
+senior
+sensor
+serial
+serpent
+service
+shadow
+shake
+shallow
+shampoo
+shannon
+sharon
+sharp
+shave
+shelf
+shelter
+sheriff
+sherman
+shine
+ship
+shirt
+shock
+shoe
+short
+shrink
+side
+sierra
+sigma
+signal
+silence
+silicon
+silk
+silver
+similar
+simon
+simple
+sinatra
+sincere
+singer
+single
+siren
+sister
+size
+ski
+slalom
+slang
+sleep
+slogan
+slow
+small
+smart
+smile
+smoke
+snake
+snow
+social
+society
+soda
+sofia
+solar
+solid
+solo
+sonar
+sonata
+song
+sonic
+soprano
+sound
+source
+south
+soviet
+spain
+spark
+sparta
+special
+speech
+speed
+spell
+spend
+sphere
+spider
+spiral
+spirit
+split
+sponsor
+spoon
+sport
+spray
+spring
+square
+stadium
+stage
+stamp
+stand
+star
+state
+static
+station
+status
+stella
+stereo
+stick
+sting
+stock
+stone
+stop
+store
+storm
+story
+strange
+street
+stretch
+strong
+stuart
+student
+studio
+style
+subject
+subway
+sugar
+sulfur
+sultan
+summer
+sunday
+sunset
+super
+support
+survive
+susan
+sushi
+suzuki
+sweden
+sweet
+swim
+swing
+switch
+symbol
+system
+table
+taboo
+tactic
+tahiti
+talent
+tango
+tape
+target
+tarzan
+taxi
+teacher
+telecom
+telex
+temple
+tempo
+tennis
+texas
+textile
+theory
+thermos
+think
+thomas
+tibet
+ticket
+tictac
+tiger
+time
+tina
+titanic
+toast
+tobacco
+today
+toga
+tokyo
+tomato
+tommy
+tonight
+topic
+torch
+tornado
+toronto
+torpedo
+torso
+total
+totem
+touch
+tourist
+tower
+toyota
+tractor
+trade
+traffic
+transit
+trapeze
+travel
+tribal
+tribune
+trick
+trident
+trilogy
+trinity
+tripod
+triton
+trivial
+tropic
+truck
+trumpet
+trust
+tulip
+tuna
+tunnel
+turbo
+turtle
+twin
+twist
+type
+ultra
+uncle
+under
+unicorn
+uniform
+union
+unique
+unit
+update
+uranium
+urban
+urgent
+user
+vacuum
+valery
+valid
+value
+vampire
+vanilla
+vatican
+vega
+velvet
+vendor
+venice
+ventura
+venus
+verbal
+verona
+version
+vertigo
+veteran
+vibrate
+victor
+video
+vienna
+viking
+village
+vincent
+violet
+violin
+virgo
+virtual
+virus
+visa
+visible
+vision
+visitor
+vista
+visual
+vital
+vitamin
+viva
+vocal
+vodka
+voice
+volcano
+voltage
+volume
+voodoo
+vortex
+voyage
+waiter
+warning
+watch
+water
+wave
+weather
+wedding
+weekend
+welcome
+western
+wheel
+whiskey
+william
+window
+winter
+wisdom
+wizard
+wolf
+wonder
+world
+xray
+yankee
+year
+yellow
+yes
+yoga
+yogurt
+young
+yoyo
+zebra
+zero
+zigzag
+zipper
+zodiac
+zoom
+"""

+ 112 - 0
mmgen/mnemonic.py

@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+mnemonic.py:  Mnemomic routines for the mmgen suite
+"""
+
+wl_checksums = {
+	"electrum": '5ca31424',
+	"tirosh":   '1a5faeff'
+}
+
+# These are the only base-1626 specific configs:
+mn_base = 1626
+def mn_fill(mn):    return len(mn) * 8 / 3
+def mn_len(hexnum): return len(hexnum) * 3 / 8
+
+import sys
+
+from mmgen.utils import msg,make_chksum_8
+from mmgen.config import *
+
+# These universal base-conversion routines work for any base
+
+def baseNtohex(base,words,wordlist,fill=0):
+	deconv = \
+		[wordlist.index(words[::-1][i])*(base**i) for i in range(len(words))]
+	return hex(sum(deconv))[2:].rstrip('L').zfill(fill)
+
+def hextobaseN(base,hexnum,wordlist,mn_len):
+	num = int(hexnum,16)
+	return [wordlist[num / (base**i) % base] for i in range(mn_len)][::-1]
+
+def get_seed_from_mnemonic(mn,wl):
+
+	if len(mn) not in mnemonic_lens:
+		msg("Bad mnemonic (%i words).  Allowed numbers of words: %s" %
+				(len(mn)," ".join([str(i) for i in mnemonic_lens])))
+		sys.exit(2)
+
+	for w in mn:
+		if w not in wl:
+			msg("Bad mnemonic: '%s' is not in the wordlist" % w)
+			sys.exit(2)
+
+	from binascii import unhexlify
+	seed = unhexlify(baseNtohex(mn_base,mn,wl,mn_fill(mn)))
+	msg("Valid mnemomic for seed ID %s" % make_chksum_8(seed))
+
+	return seed
+
+
+def get_mnemonic_from_seed(seed, wl, label, print_info=False):
+
+	from binascii import hexlify
+
+	if print_info:
+		msg("Wordlist:    %s" % label.capitalize())
+		msg("Seed length: %s bits" % (len(seed) * 8))
+		msg("Seed:        %s" % hexlify(seed))
+
+	hseed = hexlify(seed)
+	mn = hextobaseN(mn_base,hseed,wl,mn_len(hseed))
+
+	if print_info:
+		msg("mnemonic (%s words):\n%s" % (len(mn), " ".join(mn)))
+
+	if int(baseNtohex(mn_base,mn,wl,mn_fill(mn)),16) != int(hexlify(seed),16):
+		msg("ERROR: seed recomputed from wordlist not the same as original seed!")
+		msg("Recomputed seed %s" % baseNtohex(mn_base,mn,wl,mn_fill(mn)))
+		sys.exit(3)
+
+	return mn
+
+
+def check_wordlist(wl_str,label):
+
+	wl = wl_str.strip().split("\n")
+
+	print "Wordlist: %s" % label.capitalize()
+
+	from hashlib import sha256
+
+	print "Length:   %i" % len(wl)
+	new_chksum = sha256(" ".join(wl)).hexdigest()[:8]
+
+	if new_chksum != wl_checksums[label]:
+		print "ERROR: Checksum mismatch.  Computed: %s, Saved: %s" % \
+			(new_chksum,wl_checksums[label])
+		sys.exit(3)
+
+	print "Checksum: %s (matches)" % new_chksum
+
+	if (sorted(wl) == wl):
+		print "List is sorted"
+	else:
+		print "ERROR: List is not sorted!"
+		sys.exit(3)

+ 727 - 0
mmgen/utils.py

@@ -0,0 +1,727 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+utils.py:  Shared routines for the mmgen suite
+"""
+
+import sys
+from mmgen.config import *
+from binascii import hexlify,unhexlify
+
+def msg(s):   sys.stderr.write(s + "\n")
+def msg_r(s): sys.stderr.write(s)
+
+def bail(): sys.exit(9)
+
+def _my_getpass(prompt):
+
+	from getpass import getpass
+	# getpass prompts to stderr, so no trickery required as with raw_input()
+	try: pw = getpass(prompt)
+	except:
+		msg("\nInterrupted by user")
+		sys.exit(1)
+
+	return pw
+
+
+def _my_raw_input(prompt):
+
+	msg_r(prompt)
+	try: pw = raw_input()
+	except:
+		msg("\nInterrupted by user")
+		sys.exit(1)
+
+	return pw
+
+
+def _get_hash_params(hash_preset):
+	if hash_preset in hash_presets:
+		return hash_presets[hash_preset] # N,p,r,buflen
+	else:
+		# Shouldn't be here
+		msg("%s: invalid 'hash_preset' value" % hash_preset)
+		sys.exit(3)
+
+def show_hash_presets():
+	fs = "  {:<7} {:<6} {:<3}  {}"
+	msg("Available parameters for scrypt.hash():")
+	msg(fs.format("Preset","N","r","p"))
+	for i in sorted(hash_presets.keys()):
+		msg(fs.format("'%s'" % i, *hash_presets[i]))
+	msg("N = memory usage, p = iterations (rounds)")
+	sys.exit(0)
+
+
+def check_opts(opts,keys):
+
+	for key in keys:
+		if key not in opts: continue
+
+		val = opts[key]
+		what = "parameter for '--%s' option" % key.replace("_","-")
+
+		if key == 'outdir':
+			what = "output directory"
+			import re, os, stat
+			d = re.sub(r'/*$','', val)
+			opts[key] = d
+
+			try: mode = os.stat(d).st_mode
+			except:
+				msg("Unable to stat requested %s '%s'.  Aborting" % (what,d))
+				sys.exit(1)
+
+			if not stat.S_ISDIR(mode):
+				msg("Requested %s '%s' is not a directory.  Aborting" %(what,d))
+				sys.exit(1)
+
+			if not os.access(d, os.W_OK|os.X_OK):
+				msg("Requested %s '%s' is unwritable by you. Aborting"%(what,d))
+				sys.exit(1)
+
+		elif key == 'label':
+			label = val.strip()
+			opts[key] = label
+
+			if len(label) > 32:
+				msg("Label must be 32 characters or less")
+				sys.exit(1)
+
+			from string import ascii_letters, digits
+			label_chrs = list(ascii_letters + digits) + [".", "_", " "]
+			for ch in list(label):
+				if ch not in label_chrs:
+					msg("'%s': illegal character in label" % ch)
+					sys.exit(1)
+
+		elif key == 'from_brain':
+			try:
+				l,p = val.split(",")
+			except:
+				msg("'%s': invalid %s" % (val,what))
+				sys.exit(1)
+
+			try:
+				int(l)
+			except:
+				msg("'%s': invalid 'l' %s (not an integer)" % (l,what))
+				sys.exit(1)
+
+			if int(l) not in seed_lens:
+				msg("'%s': invalid 'l' %s.  Options: %s" % 
+						(l, what, ", ".join([str(i) for i in seed_lens])))
+				sys.exit(1)
+
+			if p not in hash_presets:
+				hps = ", ".join([i for i in sorted(hash_presets.keys())])
+				msg("'%s': invalid 'p' %s.  Options: %s" % (p, what, hps))
+				sys.exit(1)
+		elif key == 'seed_len':
+			if val not in seed_lens:
+				msg("'%s': invalid %s.  Options: %s"
+				% (val,what,", ".join([str(i) for i in seed_lens])))
+				sys.exit(2)
+		elif key == 'hash_preset':
+			if val not in hash_presets:
+				msg("'%s': invalid %s.  Options: %s"
+				% (val,what,", ".join(sorted(hash_presets.keys()))))
+				sys.exit(2)
+		elif key == 'usr_randlen':
+			if val > max_randlen or val < min_randlen:
+				msg("'%s': invalid %s (must be >= %s and <= %s)"
+				% (val,what,min_randlen,max_randlen))
+				sys.exit(2)
+
+
+cmessages = {
+	'null': "",
+	'unencrypted_secret_keys': """
+This program generates secret keys from your {} seed, outputting them in
+UNENCRYPTED form.  Generate only the key(s) you need and guard them carefully.
+""".format(proj_name),
+	'brain_warning': """
+############################## EXPERTS ONLY! ##############################
+
+A brainwallet will be secure only if you really know what you're doing and
+have put much care into its creation.  {} assumes no responsibility for
+coins stolen as a result of a poorly crafted brainwallet passphrase.
+
+A key will be generated from your passphrase using the parameters requested
+by you: seed length {}, hash preset '{}'.  For brainwallets it's highly
+recommended to use one of the higher-numbered presets
+
+Remember the seed length and hash preset parameters you've specified.  To
+generate the correct keys/addresses associated with this passphrase in the
+future, you must continue using these same parameters
+"""
+}
+
+def confirm_or_exit(message, question):
+
+	if message.strip(): msg(message.strip())
+	msg("")
+
+	conf_msg = "Type uppercase 'YES' to confirm: "
+
+	if question[0].isupper():
+		prompt = question + "  " + conf_msg
+	else:
+		prompt = "Are you sure you want to %s?\n%s" % (question,conf_msg)
+
+	if _my_raw_input(prompt).strip() != "YES":
+		msg("Program aborted by user")
+		sys.exit(2)
+
+	msg("")
+
+
+def set_if_unset_and_typeconvert(opts,item):
+
+#		('usr_randlen',usr_randlen,'int'),
+	for opt,var,dtype in item:
+		if   dtype == 'int': f,s = int,"an integer"
+		elif dtype == 'str': f,s = str,"a string"
+
+		if opt in opts:
+			val = opts[opt]
+			what = "invalid parameter for '--%s' option" % opt.replace("_","-")
+			try:
+				f(val)
+			except:
+				msg("'%s': %s (not %s)" % (val,what,s))
+				sys.exit(1)
+			opts[opt] = f(val)
+		else:
+			opts[opt] = var
+
+
+def make_chksum_8(s):
+	from hashlib import sha256
+	return sha256(sha256(s).digest()).hexdigest()[:8].upper()
+
+def _make_chksum_6(s):
+	from hashlib import sha256
+	return sha256(s).hexdigest()[:6]
+
+
+def _get_from_brain_opt_params(opts):
+	l,p = opts['from_brain'].split(",")
+	return(int(l),p)
+
+
+def check_infile(f):
+
+	import os, stat
+
+	try: mode = os.stat(f).st_mode
+	except:
+		msg("Unable to stat requested input file '%s'.  Aborting" % f)
+		sys.exit(1)
+
+	if not stat.S_ISREG(mode) or stat.S_ISLNK(mode):
+		msg("Requested input file '%s' is not a file.  Aborting" % f)
+		sys.exit(1)
+
+	if not os.access(f, os.R_OK):
+		msg("Requested input file '%s' is unreadable by you.  Aborting" % f)
+		sys.exit(1)
+
+
+def parse_address_range(arg):
+
+	import re
+	m = re.match(r'^(\d+)(-(\d+))*$', arg)
+
+	if m == None:
+		msg(arg + ": invalid argument for address range")
+		sys.exit(2)
+
+	start,end = int(m.group(1)), int(m.group(3) or m.group(1))
+
+	if start < 1:
+		msg(args + ": First address must be >= 1")
+		sys.exit(2)
+
+	if end < start:
+		msg(arg + ": Last address must be >= first address")
+		sys.exit(2)
+
+	return start,end
+
+
+def get_first_passphrase_from_user(what, opts):
+	"""
+	Prompt the user for a passphrase and return it
+
+	Supported options: echo_passphrase
+	"""
+
+	if not 'quiet' in opts:
+		msg("""
+Now you must choose a passphrase to encrypt the seed with.  A key will be
+generated from your passphrase using a hash preset of '%s'.  Please note that
+no strength checking of passphrases is performed.  For an empty passphrase,
+just hit ENTER twice.
+""" % opts['hash_preset'])
+
+	for i in range(passwd_max_tries):
+		if 'echo_passphrase' in opts:
+			return _my_raw_input("Enter %s: " % what)
+		else:
+			ret		= _my_getpass("Enter %s: " % what)
+			if ret == _my_getpass("Repeat %s: " % what):
+				s = " (empty)" if not len(ret) else ""
+				msg("%ss match%s" % (what.capitalize(),s))
+				return ret
+			else:
+				msg("%ss do not match" % what.capitalize())
+
+	msg("User failed to duplicate passphrase in " + str(passwd_max_tries) + " attempts")
+	sys.exit(2)
+
+
+def _scrypt_hash_passphrase(passwd, salt, hash_preset, buflen=32):
+
+	N,r,p = _get_hash_params(hash_preset)
+
+  	import scrypt
+	return scrypt.hash(passwd, salt, N, r, p, buflen=buflen)
+
+
+def _get_seed_from_brain_passphrase(words,opts):
+	bp = " ".join(words)
+	if debug: print "Sanitized brain passphrase: %s" % bp
+	seed_len,hash_preset = _get_from_brain_opt_params(opts)
+	if debug: print "Brainwallet l = %s, p = %s" % (seed_len,hash_preset)
+	msg_r("Hashing brainwallet data.  Please wait...")
+	# Use buflen arg to scrypt.hash() to get seed of desired length
+	seed = _scrypt_hash_passphrase(bp, "", hash_preset, buflen=seed_len/8)
+	msg("Done")
+	return seed
+
+
+def encrypt_seed(seed, key, opts):
+	"""
+	Encrypt a seed for a {} deterministic wallet
+	""".format(proj_name)
+
+    # 192-bit seed is 24 bytes -> not multiple of 16.  Must use MODE_CTR
+	from Crypto.Cipher import AES
+	from Crypto.Util import Counter
+
+	c = AES.new(key, AES.MODE_CTR,counter=Counter.new(128))
+	enc_seed = c.encrypt(seed)
+
+ 	msg_r("Performing a test decryption of the seed...")
+
+	c = AES.new(key, AES.MODE_CTR,counter=Counter.new(128))
+	dec_seed = c.decrypt(enc_seed)
+
+	if dec_seed == seed: msg("done")
+	else:
+		msg("FAILED.\nDecrypted seed doesn't match original seed.  Aborting.")
+		sys.exit(2)
+
+	return enc_seed
+
+
+def	write_to_stdout(data, confirm=True):
+	if sys.stdout.isatty() and confirm:
+		confirm_or_exit("",'output secret keys to screen')
+	elif not sys.stdout.isatty():
+		import os
+		of = os.readlink("/proc/%d/fd/1" % os.getpid())
+		msg("Writing data to file '%s'" % of)
+	sys.stdout.write("\n" + data)
+
+
+def get_default_wordlist():
+
+	wl_id = default_wl
+	if wl_id == "electrum": from mmgen.mn_electrum import electrum_words as wl
+	elif wl_id == "tirosh": from mmgen.mn_tirosh   import tirosh_words as wl
+	return wl.strip().split("\n")
+
+
+def write_to_file(outfile,data,confirm=False):
+
+	if confirm:
+		from os import stat
+		try:
+			stat(outfile)
+		except:
+			pass
+		else:
+			confirm_or_exit("","File '%s' already exists\nOverwrite?" % outfile)
+
+	try:
+		f = open(outfile,'w')
+	except:
+		msg("Failed to open file '%s' for writing" % outfile)
+		sys.exit(2)
+
+	try:
+		f.write(data)
+	except:
+		msg("Failed to write to file '%s'" % outfile)
+		sys.exit(2)
+
+	f.close
+
+
+def write_seed_to_file(seed, opts):
+
+	outfile = "%s.%s" % (make_chksum_8(seed).upper(),seed_ext)
+	if 'outdir' in opts:
+		outfile = "%s/%s" % (opts['outdir'], outfile)
+
+	from mmgen.bitcoin import b58encode_pad
+	data = col4(b58encode_pad(seed))
+	chk = _make_chksum_6(b58encode_pad(seed))
+
+	write_to_file(outfile, "%s %s\n" % (chk,data))
+
+	msg("%s data saved to file '%s'" % ("Seed",outfile))
+
+
+def write_mnemonic_to_file(mn, seed, opts):
+
+	outfile = "%s.words" % make_chksum_8(seed).upper()
+	if 'outdir' in opts:
+		outfile = "%s/%s" % (opts['outdir'], outfile)
+
+	write_to_file(outfile," ".join(mn) + "\n")
+
+	msg("%s data saved to file '%s'" % ("Mnemonic",outfile))
+
+
+def _display_control_data(label,metadata,hash_preset,salt,enc_seed):
+	msg("WALLET DATA")
+	fs = "  {:25} {}"
+	pw_empty = "yes" if metadata[3] == "E" else "no"
+	from mmgen.bitcoin import b58encode_pad
+	for i in (
+		("Label:",               label),
+		("Seed ID:",             metadata[0]),
+		("Key  ID:",             metadata[1]),
+		("Seed length:",         metadata[2]),
+		("Scrypt hash params:",  "Preset '%s' (%s)" % (hash_preset,
+		 " ".join([str(i) for i in _get_hash_params(hash_preset)]))),
+		("Passphrase is empty:", pw_empty),
+		("Timestamp:",           "%s UTC" % metadata[4]),
+		("Salt:",                b58encode_pad(salt)),
+		("Encrypted seed:",      b58encode_pad(enc_seed))
+	): msg(fs.format(*i))
+
+
+def col4(s):
+	nondiv = 1 if len(s) % 4 else 0
+	return " ".join([s[4*i:4*i+4] for i in range(len(s)/4 + nondiv)])
+
+
+def write_wallet_to_file(seed, passwd, key_id, salt, enc_seed, opts):
+
+	import time
+	tv = time.gmtime(time.time())[:6]
+	ts_hdr = "{:04d}{:02d}{:02d}_{:02d}{:02d}{:02d}".format(*tv)
+
+	seed_id = make_chksum_8(seed)
+	seed_len = str(len(seed)*8)
+	pw_status = "NE" if len(passwd) else "E"
+
+	hash_preset = opts['hash_preset']
+
+	outfile = "{}-{}[{},{}].dat".format(seed_id,key_id,seed_len,hash_preset)
+	if 'outdir' in opts:
+		outfile = "%s/%s" % (opts['outdir'], outfile)
+
+	label = opts['label'] if 'label' in opts else "None"
+
+	from mmgen.bitcoin import b58encode_pad
+
+	sf  = b58encode_pad(salt)
+	esf = b58encode_pad(enc_seed)
+
+	metadata = seed_id.lower(),key_id.lower(),seed_len,pw_status,ts_hdr
+
+	lines = (
+		label,
+		"{} {} {} {} {}".format(*metadata),
+		"{}: {} {} {}".format(hash_preset,*_get_hash_params(hash_preset)),
+		"{} {}".format(_make_chksum_6(sf),  col4(sf)),
+		"{} {}".format(_make_chksum_6(esf), col4(esf))
+	)
+
+	chk = _make_chksum_6(" ".join(lines))
+
+	confirm = False if 'quiet' in opts else True
+	write_to_file(outfile, "\n".join((chk,)+lines)+"\n", confirm)
+
+	msg("Wallet saved to file '%s'" % outfile)
+	if 'verbose' in opts:
+		_display_control_data(label,metadata,hash_preset,salt,enc_seed)
+
+
+def	compare_checksums(chksum1, desc1, chksum2, desc2):
+
+	if chksum1.lower() == chksum2.lower():
+		msg("OK (%s)" % chksum1.upper())
+		return True
+	else:
+		msg("ERROR!\nComputed checksum %s (%s) doesn't match checksum %s (%s)" \
+			% (desc1,chksum1,desc2,chksum2))
+		return False
+
+def _is_hex(s):
+	try: int(s,16)
+	except: return False
+	else: return True
+
+
+def	check_mmseed_format(words):
+
+	valid = False
+	what = "%s data" % seed_ext
+	chklen = len(words[0])
+
+	if len(words) < 3 or len(words) > 12:
+		msg("Invalid data length (%s) in %s" % (len(words),what))
+	elif not _is_hex(words[0]):
+		msg("Invalid format of checksum '%s' in %s"%(words[0], what))
+	elif chklen != 6:
+		msg("Incorrect length of checksum (%s) in %s" % (chklen,what))
+	else: valid = True
+
+	if valid == False:
+		msg("Invalid %s data" % seed_ext)
+		sys.exit(3)
+
+
+def	check_wallet_format(infile, lines, opts):
+
+	def vmsg(s):
+		if 'verbose' in opts: msg(s)
+
+	what = "wallet file '%s'" % infile
+	valid = False
+	chklen = len(lines[0])
+	if len(lines) != 6:
+		vmsg("Invalid number of lines (%s) in %s" % (len(lines),what))
+	elif chklen != 6:
+		vmsg("Incorrect length of Master checksum (%s) in %s" % (chklen,what))
+	elif not _is_hex(lines[0]):
+		vmsg("Invalid format of Master checksum '%s' in %s"%(lines[0], what))
+	else: valid = True
+
+	if valid == False:
+		msg("Invalid %s" % what)
+		sys.exit(2)
+
+
+def _check_chksum_6(chk,val,desc,infile):
+	comp_chk = _make_chksum_6(val)
+	if chk != comp_chk:
+		msg("%s checksum incorrect in file '%s'!" % (desc,infile))
+		msg("Checksum: %s. Computed value: %s" % (chk,comp_chk))
+		sys.exit(2)
+	elif debug:
+	 	msg("%s checksum passed: %s" % (desc.capitalize(),chk))
+
+
+#def bin_pad(bindata,length):
+#	return unhexlify(hexlify(bindata).zfill(length*2))
+
+def get_data_from_wallet(infile,opts):
+
+	msg("Getting {} wallet data from file: {}".format(proj_name,infile))
+
+	try:
+		f = open(infile, 'r')
+	except:
+		msg("Unable to open file '" + infile + "' for reading")
+		sys.exit(2)
+
+	lines = [i.strip() for i in f.readlines()]
+	f.close()
+
+	check_wallet_format(infile, lines, opts)
+
+	label = lines[1]
+
+	metadata = lines[2].split()
+
+	for i in 0,1: metadata[i] = metadata[i].upper()
+
+	hd = lines[3].split()
+	hash_preset = hd[0][:-1]
+	hash_params = [int(i) for i in hd[1:]]
+
+	if hash_params != _get_hash_params(hash_preset):
+		msg("Hash parameters '%s' don't match hash preset '%s'" %
+				(" ".join(hash_params), hash_preset))
+		sys.exit(9)
+
+	res = {}
+	from mmgen.bitcoin import b58decode_pad
+	for i,key in (4,"salt"),(5,"enc_seed"):
+		l = lines[i].split()
+		val = "".join(l[1:])
+		_check_chksum_6(l[0], val, key, infile)
+		res[key] = b58decode_pad(val)
+
+	_check_chksum_6(lines[0], " ".join(lines[1:]), "Master", infile)
+
+	return label,metadata,hash_preset,res['salt'],res['enc_seed']
+
+
+def _get_words_from_user(opts, prompt):
+	# split() also strips
+	if 'echo_passphrase' in opts:
+		return _my_raw_input(prompt).split()
+	else:
+		return _my_getpass(prompt).split()
+
+
+def _get_words_from_file(infile,what):
+	msg("Getting %s data from file '%s'" % (what,infile))
+	try:
+		f = open(infile, 'r')
+	except:
+		msg("Unable to open file '%s' for reading" % infile)
+		sys.exit(2)
+	lines = f.readlines()
+	f.close()
+	# split() also strips
+	return [w for l in lines for w in l.split()]
+
+def get_words(infile,what,prompt,opts):
+	if infile:
+		words = _get_words_from_file(infile,what)
+	else:
+		words = _get_words_from_user(opts,prompt)
+	if debug: print "Sanitized input: [%s]" % " ".join(words)
+	return words
+
+
+def get_seed_from_seed_data(words):
+
+	check_mmseed_format(words)
+
+	stored_chk = words[0]
+	seed_b58 = "".join(words[1:])
+
+	chk = _make_chksum_6(seed_b58)
+	msg_r("Validating %s checksum..." % seed_ext)
+
+	if compare_checksums(chk, "from seed", stored_chk, "from input"):
+		from mmgen.bitcoin import b58decode_pad
+		seed = b58decode_pad(seed_b58)
+		msg("%s data produces seed ID: %s" % (seed_ext,make_chksum_8(seed)))
+		return seed
+	else:
+		msg("Invalid checksum for {} seed".format(proj_name))
+		sys.exit(9)
+
+
+def get_seed_from_wallet(infile,opts,
+		prompt="Enter {} wallet passphrase: ".format(proj_name)):
+
+	wdata = get_data_from_wallet(infile,opts)
+	label,metadata,hash_preset,salt,enc_seed = wdata
+
+	if 'verbose' in opts: _display_control_data(*wdata)
+
+	passwd = " ".join(get_words("","",prompt,opts))
+
+	key = make_key(passwd, salt, hash_preset)
+
+	return decrypt_seed(enc_seed, key, metadata[0], metadata[1])
+
+
+def make_key(passwd, salt, hash_preset):
+
+	msg_r("Hashing passphrase.  Please wait...")
+	key = _scrypt_hash_passphrase(passwd, salt, hash_preset)
+	msg("done")
+	return key
+
+
+def decrypt_seed(enc_seed, key, seed_id, key_id):
+
+	msg_r("Checking key...")
+	chk = make_chksum_8(key)
+	if not compare_checksums(chk, "of key", key_id, "in header"):
+		msg("Passphrase incorrect?")
+		sys.exit(3)
+
+	msg_r("Decrypting seed with key...")
+
+	from Crypto.Cipher import AES
+	from Crypto.Util import Counter
+
+	c = AES.new(key, AES.MODE_CTR,counter=Counter.new(128))
+	dec_seed = c.decrypt(enc_seed)
+
+	chk = make_chksum_8(dec_seed)
+	if compare_checksums(chk,"of decrypted seed",seed_id,"in header"):
+		msg("Passphrase is OK")
+	else:
+		if not debug:
+			msg_r("Checking key ID...")
+			chk = make_chksum_8(key)
+			if compare_checksums(chk, "of key", key_id, "in header"):
+				msg("Key ID is correct but decryption of seed failed")
+			else:
+				msg("Incorrect passphrase")
+
+		sys.exit(3)
+
+	if debug: msg("key: %s" % hexlify(key))
+
+	return dec_seed
+
+
+def get_seed(infile,opts,no_wallet=False):
+	if 'from_mnemonic' in opts:
+		prompt = "Enter mnemonic: "
+		words = get_words(infile,"mnemonic",prompt,opts)
+
+		wl = get_default_wordlist()
+		from mmgen.mnemonic import get_seed_from_mnemonic
+		return get_seed_from_mnemonic(words,wl)
+	elif 'from_brain' in opts:
+		msg("")
+		if 'quiet' not in opts:
+			confirm_or_exit(
+				cmessages['brain_warning'].format(
+					proj_name.capitalize(),
+					*_get_from_brain_opt_params(opts)),
+			"continue")
+		prompt = "Enter brainwallet passphrase: "
+		words = get_words(infile,"brainwallet",prompt,opts)
+		return _get_seed_from_brain_passphrase(words,opts)
+	elif 'from_seed' in opts:
+		prompt = "Enter seed in %s format: " % seed_ext
+		words = get_words(infile,"seed",prompt,opts)
+		return get_seed_from_seed_data(words)
+	elif no_wallet:
+		return False
+	else:
+		return get_seed_from_wallet(infile, opts)

+ 87 - 0
mmgen/walletgen.py

@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+walletgen.py:  Routines used for seed generation and wallet creation
+"""
+
+import sys
+from mmgen.utils import msg, msg_r
+from binascii import hexlify
+
+def get_random_data_from_user(opts):
+
+	ulen = opts['usr_randlen']
+
+	if 'quiet' in opts:
+		msg("Enter %s random symbols" % ulen)
+	else:
+		msg("""
+We're going to be paranoid and not fully trust your OS's random number
+generator.  Please type %s symbols on your keyboard.  Type slowly and choose
+your symbols carefully for maximum randomness.  Try to use both upper and
+lowercase as well as punctuation and numerals.  What you type will not be
+displayed on the screen.
+""" % ulen)
+
+	prompt = "You may begin typing.  %s symbols left: "
+	msg_r(prompt % ulen)
+
+	import time
+	# time.clock() always returns zero, so we'll use time.time()
+	saved_time = time.time()
+
+	user_rand_data,intervals = "",[]
+
+	try:
+		import os
+		os.system(
+		"stty -icanon min 1 time 0 -echo -echoe -echok -echonl -crterase noflsh"
+		)
+		for i in range(ulen):
+			user_rand_data += sys.stdin.read(1)
+			msg_r("\r" + prompt % (ulen - i - 1))
+			now = time.time()
+			intervals.append(now - saved_time)
+			saved_time = now
+		if 'quiet' in opts:
+			msg_r("\r")
+		else:
+			msg_r("\rThank you.  That's enough." + " "*15 + "\n\n")
+		time.sleep(0.5)
+		msg_r(
+		"User random data successfully acquired.  Press ENTER to continue: ")
+		raw_input()
+	except:
+		msg("\nUser random input interrupted.  Aborting")
+		sys.exit(1)
+	finally:
+		os.system("stty sane")
+
+	return user_rand_data, ["{:.22f}".format(i) for i in intervals]
+
+
+def display_os_random_data(os_rand_data):
+	print "Rand1: {}\nRand2: {}".format(
+			*[hexlify(i) for i in os_rand_data])
+
+
+def display_user_random_data(user_rand_data,intervals_fmt):
+	msg("\nUser random data: " + user_rand_data)
+	msg("Keystroke time intervals:")
+	for i in range(0,len(intervals_fmt),3):
+		msg("  " + " ".join(intervals_fmt[i:i+3]))

+ 30 - 0
setup.py

@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+from distutils.core import setup
+
+setup(
+		name         = 'mmgen',
+		version      = '0.6',
+		author       = 'Philemon',
+		author_email = 'mmgen-py@yandex.com',
+		url          = 'http://www.python.org/sigs/distutils-sig/',
+		py_modules = [
+			'mmgen.addr',
+			'mmgen.bitcoin',
+			'mmgen.config',
+			'mmgen.license',
+			'mmgen.__init__',
+			'mmgen.mn_electrum',
+			'mmgen.mnemonic',
+			'mmgen.mn_tirosh',
+			'mmgen.Opts',
+			'mmgen.utils',
+			'mmgen.walletgen'
+		],
+		data_files=[('/usr/local/bin', [
+			'mmgen-addrgen',
+			'mmgen-keygen',
+			'mmgen-passchg',
+			'mmgen-walletchk',
+			'mmgen-walletgen'
+		])]
+	)

+ 27 - 0
tests/addr.py

@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+addr.py:  Test suite for mmgen.addr module
+"""
+
+from mmgen.addr import *
+
+tests = "none",
+
+if (len(sys.argv) == 1):
+	print "Available tests: %s" % " ".join(tests)

+ 190 - 0
tests/bitcoin.py

@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+bitcoin.py:  Test suite for mmgen.bitcoin module
+"""
+
+from mmgen.bitcoin import *
+from mmgen.utils import msg
+from test import *
+
+import sys
+
+def b58_randenc():
+	r = get_random(24)
+	r_enc = b58encode(r)
+	print "Data (hex):    %s" % hexlify(r)
+	print "Base 58:       %s" % r_enc
+	r_dec = b58decode(r_enc)
+	print "Decoded data:  %s" % hexlify(r_dec)
+	if r_dec != r:
+		print "ERROR!  Decoded data doesn't match original"
+		sys.exit(9)
+
+def keyconv_compare_randloop(loops, quiet=False):
+	try:
+		for i in range(1,int(loops)+1):
+
+
+			wif = numtowif_rand(quiet=True)
+
+			if not quiet: sys.stderr.write("-- %s --\n" % i)
+			ret = keyconv_compare(wif,quiet)
+			if ret == False: sys.exit(9)
+
+			if quiet:
+				sys.stderr.write("\riteration: %i " % i)
+
+		if quiet:
+			sys.stderr.write("\r%s iterations completed\n" % i)
+		else:
+			print "%s iterations completed" % i
+
+	except:
+		print "\nUser interrupt"
+
+
+def keyconv_compare(wif,quiet=False):
+	do_msg = nomsg if quiet else msg
+	do_msg("WIF:               %s" % wif)
+	from subprocess import Popen, PIPE
+	try:
+		p = Popen(["keyconv", wif], stdout=PIPE)
+	except:
+		print "Error with execution of keyconv"
+		sys.exit(3)
+	kc_addr = dict([j.split() for j in p.stdout.readlines()])['Address:']
+	addr = privnum2addr(wiftonum(wif))
+	do_msg("Address (mmgen):   %s" % addr)
+	do_msg("Address (keyconv): %s" % kc_addr)
+	if (kc_addr != addr):
+		print "'keyconv' addr differs from internally-generated addr!"
+		print "WIF:      %s" % wif
+		print "keyconv:  %s" % kc_addr
+		print "internal: %s" % addr
+		return False
+	else:
+		return True
+
+def _do_hextowif(hex_in,quiet=False):
+	do_msg = nomsg if quiet else msg
+	do_msg("Input:        %s" % hex_in)
+	wif = numtowif(int(hex_in,16))
+	do_msg("WIF encoded:  %s" % wif)
+	wif_dec = wiftohex(wif)
+	do_msg("WIF decoded:  %s" % wif_dec)
+	if hex_in != wif_dec:
+		print "ERROR!  Decoded data doesn't match original data"
+		sys.exit(9)
+	return wif
+
+
+def hextowiftopubkey(hex_in,quiet=False):
+	if len(hex_in) != 64:
+		print "Input must be a hex number 64 bits in length (%s input)" \
+			% len(hex_in)
+		sys.exit(2)
+
+	wif = _do_hextowif(hex_in,quiet=quiet)
+
+	keyconv_compare(wif)
+
+
+def numtowif_rand(quiet=False):
+	r_hex = hexlify(get_random(32))
+
+	return _do_hextowif(r_hex,quiet)
+
+
+def strtob58(s,quiet=False):
+	print "Input:         %s" % s
+	s_enc = b58encode(s)
+	print "Encoded data:  %s" % s_enc
+	s_dec = b58decode(s_enc)
+	print "Decoded data:  %s" % s_dec
+	test_equality(s,s_dec,[""],quiet)
+
+def hextob58(s_in,f_enc=b58encode, f_dec=b58decode, quiet=False):
+	do_msg = nomsg if quiet else msg
+	do_msg("Input:         %s" % s_in)
+	s_bin = unhexlify(s_in)
+	s_enc = f_enc(s_bin)
+	do_msg("Encoded data:  %s" % s_enc)
+	s_dec = hexlify(f_dec(s_enc))
+	do_msg("Recoded data:  %s" % s_dec)
+	test_equality(s_in,s_dec,["0"],quiet)
+
+def b58tohex(s_in,f_dec=b58decode, f_enc=b58encode,quiet=False):
+	print "Input:         %s" % s_in
+	s_dec = f_dec(s_in)
+	print "Decoded data:  %s" % hexlify(s_dec)
+	s_enc = f_enc(s_dec)
+	print "Recoded data:  %s" % s_enc
+	test_equality(s_in,s_enc,["1"],quiet)
+
+def hextob58_pad(s_in, quiet=False):
+	hextob58(s_in,f_enc=b58encode_pad, f_dec=b58decode_pad, quiet=quiet)
+
+def b58tohex_pad(s_in, quiet=False):
+	b58tohex(s_in,f_dec=b58decode_pad, f_enc=b58encode_pad, quiet=quiet)
+
+def	hextob58_pad_randloop(loops, quiet=False):
+	try:
+		for i in range(1,int(loops)+1):
+			r = hexlify(get_random(32))
+			hextob58(r,f_enc=b58encode_pad, f_dec=b58decode_pad, quiet=quiet)
+			if not quiet: print
+			if not i % 100 and quiet:
+				sys.stderr.write("\riteration: %i " % i)
+
+		sys.stderr.write("\r%s iterations completed\n" % i)
+	except:
+		print "User interrupt"
+
+def test_wiftohex(s_in,f_dec=wiftohex,f_enc=numtowif):
+	print "Input:         %s" % s_in
+	s_dec = f_dec(s_in)
+	print "Decoded data:  %s" % s_dec
+	s_enc = f_enc(int(s_dec,16))
+	print "Recoded data:  %s" % s_enc
+
+def hextosha256(s_in):
+	print "Entered data:   %s" % s_in
+	s_enc = sha256(unhexlify(s_in)).hexdigest()
+	print "Encoded data:   %s" % s_enc
+
+
+tests = {
+	"keyconv_compare":          ['wif [str]','quiet [bool=False]'],
+	"keyconv_compare_randloop": ['iterations [int]','quiet [bool=False]'],
+	"b58_randenc":              ['quiet [bool=False]'],
+	"strtob58":                 ['string [str]','quiet [bool=False]'],
+	"hextob58":                 ['hexnum [str]','quiet [bool=False]'],
+	"b58tohex":                 ['b58num [str]','quiet [bool=False]'],
+	"hextob58_pad":             ['hexnum [str]','quiet [bool=False]'],
+	"b58tohex_pad":             ['b58num [str]','quiet [bool=False]'],
+	"hextob58_pad_randloop":    ['iterations [int]','quiet [bool=False]'],
+	"test_wiftohex":            ['wif [str]',       'quiet [bool=False]'],
+	"numtowif_rand":            ['quiet [bool=False]'],
+	"hextosha256":              ['hexnum [str]','quiet [bool=False]'],
+	"hextowiftopubkey":         ['hexnum [str]','quiet [bool=False]'],
+}
+
+
+args = process_test_args(sys.argv, tests)
+eval(sys.argv[1])(*args)

+ 24 - 0
tests/mn_electrum.py

@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+mn_electrum.py:  Test suite for mmgen.mn_electrum module
+"""
+
+from mmgen.mn_electrum import *
+
+print electrum_words.strip()

+ 24 - 0
tests/mn_tirosh.py

@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+mn_tirosh.py:  Test suite for mmgen.mn_tirosh module
+"""
+
+from mmgen.mn_tirosh import *
+
+print tirosh_words.strip()

+ 109 - 0
tests/mnemonic.py

@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+mnemonic.py:  Test suite for mmgen.mnemonic module
+"""
+
+from mmgen.mnemonic import *
+from test import *
+
+import sys
+from binascii import hexlify
+from mmgen.mn_electrum  import electrum_words as el
+from mmgen.mn_tirosh    import tirosh_words   as tl
+
+def do_random_tests(n):
+	r = get_random(n)
+	em = get_mnemonic_from_seed(r,el.strip().split("\n"),
+			"electrum",print_info=False)
+	tm = get_mnemonic_from_seed(r,tl.strip().split("\n"),
+			"tirosh",print_info=False)
+
+	print "Seed:     %s (%s bits)" % (hexlify(r),len(r)*8)
+	print "Electrum: %s" % " ".join(em)
+	print "Tirosh:   %s" % " ".join(tm)
+
+
+def hextobaseN_test(num_in,base,wl,quiet=False):
+	do_msg = nomsg if quiet else msg
+	do_msg("Input:         %s" % num_in)
+	num_enc = "".join(hextobaseN(base,num_in,wl,len(num_in)*2))
+	do_msg("Encoded value: %s" % num_enc)
+	num_dec = baseNtohex(base,num_enc,wl)
+	do_msg("Decoded value: %s" % num_dec)
+	test_equality(num_in,num_dec,wl,quiet)
+	return num_enc,num_dec
+
+
+def baseNtohex_test(num_in,base,wl,quiet=False):
+	do_msg = nomsg if quiet else msg
+	do_msg("Input:         %s" % num_in)
+	num_enc = baseNtohex(base,list(num_in),wl)
+	do_msg("Encoded value: %s" % num_enc)
+	num_dec = "".join(hextobaseN(base,num_enc,wl,len(num_enc)*2))
+	do_msg("Decoded value: %s" % num_dec)
+	test_equality(num_in,num_dec,wl,quiet)
+	return num_enc,num_dec
+
+
+def random128(): do_random_tests(16)
+def random192(): do_random_tests(24)
+def random256(): do_random_tests(32)
+def random512(): do_random_tests(64)
+def electrum():  check_wordlist(el,"electrum")
+def tirosh():    check_wordlist(tl,"tirosh")
+
+def base10tohex(num,quiet=False):
+	enc,dec = baseNtohex_test(num,10,"0123456789",quiet)
+	print "Decimal:           %s" % num
+	print "Hex (encoded):     %s" % enc
+	print "Decimal (recoded): %s" % dec.lstrip("0")
+
+def hextobase10(num,quiet=False):
+	enc,dec= hextobaseN_test(num,10,"0123456789",quiet)
+	print "Hex:               %s" % num
+	print "Decimal (encoded): %s" % enc.lstrip("0")
+	print "Hex (recoded):     %s" % dec
+
+def base8tohex(num,quiet=False):
+	enc,dec = baseNtohex_test(num,8,"01234567",quiet)
+	print "Octal:           %s" % num
+	print "Hex (encoded):   %s" % enc
+	print "Octal (recoded): %s" % "0" + dec.lstrip("0")
+
+def hextobase8(num,quiet=False):
+	enc,dec = hextobaseN_test(num,8,"01234567",quiet)
+	print "Hex:           %s" % num
+	print "Octal:         %s" % "0" + enc.lstrip("0")
+	print "Hex (recoded): %s" % dec
+
+tests = {
+	"random128":      [],
+	"random192":      [],
+	"random256":      [],
+	"random512":      [],
+	"electrum":       [],
+	"tirosh":         [],
+	"base10tohex":    ['base10num [int]','quiet [bool=False]'],
+	"hextobase10":    ['hexnum [str]',   'quiet [bool=False]'],
+	"base8tohex":     ['base8num [int]', 'quiet [bool=False]'],
+	"hextobase8":     ['hexnum [str]',   'quiet [bool=False]'],
+}
+
+args = process_test_args(sys.argv, tests)
+eval(sys.argv[1])(*args)

+ 86 - 0
tests/test.py

@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+test.py:  Shared routines for mmgen test suite
+"""
+
+import sys
+from mmgen.utils import msg
+
+def nomsg(s): pass
+
+def test_equality(num_in,num_out,wl,quiet=False):
+
+	do_msg = nomsg if quiet else msg
+
+	if num_in != num_out:
+		do_msg("WARNING! Recoded number doesn't match input stringwise!")
+		do_msg("Input:  %s" % num_in)
+		do_msg("Output: %s" % num_out)
+
+	i = num_in.lstrip(wl[0])
+	o = num_out.lstrip(wl[0])
+
+	if i != o:
+		print "ERROR! Recoded number doesn't match input numerically!"
+		sys.exit(9)
+
+
+def get_random(length):
+	from Crypto import Random
+	return Random.new().read(length)
+
+def process_test_args(argv, tests):
+	if (len(argv) == 1):
+		print "Usage: %s <test>" % argv[0].split("/")[-1]
+		ls = "\n   "
+		print "Available tests:%s%s" % (ls,ls.join(sorted(tests.keys())))
+		sys.exit(1)
+	elif argv[1] not in tests:
+		print "'%s': no such test" % argv[1]
+		sys.exit(2)
+	else:
+		cargs = tests[argv[1]] 
+		uargs = argv[2:]
+		if len(uargs) > len(cargs):
+			print "Too many arguments\nUsage: %s(%s)" % \
+				(argv[1], ", ".join(cargs))
+			sys.exit()
+
+		for i in range(len(cargs)):
+			try:    uarg = uargs[i]
+			except: uarg = None
+
+			cname,ctype_arg = cargs[i].split()
+			c = ctype_arg[1:-1].split("=")[0:]
+			ctype,cdflt = c[0],c[1:]
+
+			if uarg == None and not cdflt:
+				print "Usage: %s(%s)" % \
+					(argv[1], ", ".join(cargs))
+				sys.exit()
+
+#		print "%-10s %-7s %s" % (uarg, cargs[i], carg)
+
+			if uarg:
+				try: eval(ctype + "('" + uarg + "')")
+				except:
+					print "'%s' Invalid argument (%s required)" % (uarg, ctype)
+					sys.exit()
+
+		return uargs

+ 27 - 0
tests/utils.py

@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+utils.py:  Test suite for mmgen.utils module
+"""
+
+from mmgen.utils import *
+
+tests = "none",
+
+if (len(sys.argv) == 1):
+	print "Available tests: %s" % " ".join(tests)

+ 27 - 0
tests/walletgen.py

@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+#
+# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
+# 
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+walletgen.py:  Test suite for mmgen.walletgen module
+"""
+
+from mmgen.walletgen import *
+
+tests = "none",
+
+if (len(sys.argv) == 1):
+	print "Available tests: %s" % " ".join(tests)

+ 302 - 0
wordlists/mn_wordlist.c

@@ -0,0 +1,302 @@
+/* mn_wordlist.c
+ Copyright (c) 2000  Oren Tirosh <oren@hishome.net>
+ 
+ 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 "mnemonic.h"
+
+const char *mn_wordlist_version =
+  " Wordlist ver 0.7";
+
+const char *mn_words[MN_WORDS + 1] = { 0,
+  "academy",  "acrobat",  "active",   "actor",    "adam",     "admiral",  
+  "adrian",   "africa",   "agenda",   "agent",    "airline",  "airport",  
+  "aladdin",  "alarm",    "alaska",   "albert",   "albino",   "album",    
+  "alcohol",  "alex",     "algebra",  "alibi",    "alice",    "alien",    
+  "alpha",    "alpine",   "amadeus",  "amanda",   "amazon",   "amber",    
+  "america",  "amigo",    "analog",   "anatomy",  "angel",    "animal",   
+  "antenna",  "antonio",  "apollo",   "april",    "archive",  "arctic",   
+  "arizona",  "arnold",   "aroma",    "arthur",   "artist",   "asia",     
+  "aspect",   "aspirin",  "athena",   "athlete",  "atlas",    "audio",    
+  "august",   "austria",  "axiom",    "aztec",    "balance",  "ballad",   
+  "banana",   "bandit",   "banjo",    "barcode",  "baron",    "basic",    
+  "battery",  "belgium",  "berlin",   "bermuda",  "bernard",  "bikini",   
+  "binary",   "bingo",    "biology",  "block",    "blonde",   "bonus",    
+  "boris",    "boston",   "boxer",    "brandy",   "bravo",    "brazil",   
+  "bronze",   "brown",    "bruce",    "bruno",    "burger",   "burma",    
+  "cabinet",  "cactus",   "cafe",     "cairo",    "cake",     "calypso",  
+  "camel",    "camera",   "campus",   "canada",   "canal",    "cannon",   
+  "canoe",    "cantina",  "canvas",   "canyon",   "capital",  "caramel",  
+  "caravan",  "carbon",   "cargo",    "carlo",    "carol",    "carpet",   
+  "cartel",   "casino",   "castle",   "castro",   "catalog",  "caviar",   
+  "cecilia",  "cement",   "center",   "century",  "ceramic",  "chamber",  
+  "chance",   "change",   "chaos",    "charlie",  "charm",    "charter",  
+  "chef",     "chemist",  "cherry",   "chess",    "chicago",  "chicken",  
+  "chief",    "china",    "cigar",    "cinema",   "circus",   "citizen",  
+  "city",     "clara",    "classic",  "claudia",  "clean",    "client",   
+  "climax",   "clinic",   "clock",    "club",     "cobra",    "coconut",  
+  "cola",     "collect",  "colombo",  "colony",   "color",    "combat",   
+  "comedy",   "comet",    "command",  "compact",  "company",  "complex",  
+  "concept",  "concert",  "connect",  "consul",   "contact",  "context",  
+  "contour",  "control",  "convert",  "copy",     "corner",   "corona",   
+  "correct",  "cosmos",   "couple",   "courage",  "cowboy",   "craft",    
+  "crash",    "credit",   "cricket",  "critic",   "crown",    "crystal",  
+  "cuba",     "culture",  "dallas",   "dance",    "daniel",   "david",    
+  "decade",   "decimal",  "deliver",  "delta",    "deluxe",   "demand",   
+  "demo",     "denmark",  "derby",    "design",   "detect",   "develop",  
+  "diagram",  "dialog",   "diamond",  "diana",    "diego",    "diesel",   
+  "diet",     "digital",  "dilemma",  "diploma",  "direct",   "disco",    
+  "disney",   "distant",  "doctor",   "dollar",   "dominic",  "domino",   
+  "donald",   "dragon",   "drama",    "dublin",   "duet",     "dynamic",  
+  "east",     "ecology",  "economy",  "edgar",    "egypt",    "elastic",  
+  "elegant",  "element",  "elite",    "elvis",    "email",    "energy",   
+  "engine",   "english",  "episode",  "equator",  "escort",   "ethnic",   
+  "europe",   "everest",  "evident",  "exact",    "example",  "exit",     
+  "exotic",   "export",   "express",  "extra",    "fabric",   "factor",   
+  "falcon",   "family",   "fantasy",  "fashion",  "fiber",    "fiction",  
+  "fidel",    "fiesta",   "figure",   "film",     "filter",   "final",    
+  "finance",  "finish",   "finland",  "flash",    "florida",  "flower",   
+  "fluid",    "flute",    "focus",    "ford",     "forest",   "formal",   
+  "format",   "formula",  "fortune",  "forum",    "fragile",  "france",   
+  "frank",    "friend",   "frozen",   "future",   "gabriel",  "galaxy",   
+  "gallery",  "gamma",    "garage",   "garden",   "garlic",   "gemini",   
+  "general",  "genetic",  "genius",   "germany",  "global",   "gloria",   
+  "golf",     "gondola",  "gong",     "good",     "gordon",   "gorilla",  
+  "grand",    "granite",  "graph",    "green",    "group",    "guide",    
+  "guitar",   "guru",     "hand",     "happy",    "harbor",   "harmony",  
+  "harvard",  "havana",   "hawaii",   "helena",   "hello",    "henry",    
+  "hilton",   "history",  "horizon",  "hotel",    "human",    "humor",    
+  "icon",     "idea",     "igloo",    "igor",     "image",    "impact",   
+  "import",   "index",    "india",    "indigo",   "input",    "insect",   
+  "instant",  "iris",     "italian",  "jacket",   "jacob",    "jaguar",   
+  "janet",    "japan",    "jargon",   "jazz",     "jeep",     "john",     
+  "joker",    "jordan",   "jumbo",    "june",     "jungle",   "junior",   
+  "jupiter",  "karate",   "karma",    "kayak",    "kermit",   "kilo",     
+  "king",     "koala",    "korea",    "labor",    "lady",     "lagoon",   
+  "laptop",   "laser",    "latin",    "lava",     "lecture",  "left",     
+  "legal",    "lemon",    "level",    "lexicon",  "liberal",  "libra",    
+  "limbo",    "limit",    "linda",    "linear",   "lion",     "liquid",   
+  "liter",    "little",   "llama",    "lobby",    "lobster",  "local",    
+  "logic",    "logo",     "lola",     "london",   "lotus",    "lucas",    
+  "lunar",    "machine",  "macro",    "madam",    "madonna",  "madrid",   
+  "maestro",  "magic",    "magnet",   "magnum",   "major",    "mama",     
+  "mambo",    "manager",  "mango",    "manila",   "marco",    "marina",   
+  "market",   "mars",     "martin",   "marvin",   "master",   "matrix",   
+  "maximum",  "media",    "medical",  "mega",     "melody",   "melon",    
+  "memo",     "mental",   "mentor",   "menu",     "mercury",  "message",  
+  "metal",    "meteor",   "meter",    "method",   "metro",    "mexico",   
+  "miami",    "micro",    "million",  "mineral",  "minimum",  "minus",    
+  "minute",   "miracle",  "mirage",   "miranda",  "mister",   "mixer",    
+  "mobile",   "model",    "modem",    "modern",   "modular",  "moment",   
+  "monaco",   "monica",   "monitor",  "mono",     "monster",  "montana",  
+  "morgan",   "motel",    "motif",    "motor",    "mozart",   "multi",    
+  "museum",   "music",    "mustang",  "natural",  "neon",     "nepal",    
+  "neptune",  "nerve",    "neutral",  "nevada",   "news",     "ninja",    
+  "nirvana",  "normal",   "nova",     "novel",    "nuclear",  "numeric",  
+  "nylon",    "oasis",    "object",   "observe",  "ocean",    "octopus",  
+  "olivia",   "olympic",  "omega",    "opera",    "optic",    "optimal",  
+  "orange",   "orbit",    "organic",  "orient",   "origin",   "orlando",  
+  "oscar",    "oxford",   "oxygen",   "ozone",    "pablo",    "pacific",  
+  "pagoda",   "palace",   "pamela",   "panama",   "panda",    "panel",    
+  "panic",    "paradox",  "pardon",   "paris",    "parker",   "parking",  
+  "parody",   "partner",  "passage",  "passive",  "pasta",    "pastel",   
+  "patent",   "patriot",  "patrol",   "patron",   "pegasus",  "pelican",  
+  "penguin",  "pepper",   "percent",  "perfect",  "perfume",  "period",   
+  "permit",   "person",   "peru",     "phone",    "photo",    "piano",    
+  "picasso",  "picnic",   "picture",  "pigment",  "pilgrim",  "pilot",    
+  "pirate",   "pixel",    "pizza",    "planet",   "plasma",   "plaster",  
+  "plastic",  "plaza",    "pocket",   "poem",     "poetic",   "poker",    
+  "polaris",  "police",   "politic",  "polo",     "polygon",  "pony",     
+  "popcorn",  "popular",  "postage",  "postal",   "precise",  "prefix",   
+  "premium",  "present",  "price",    "prince",   "printer",  "prism",    
+  "private",  "product",  "profile",  "program",  "project",  "protect",  
+  "proton",   "public",   "pulse",    "puma",     "pyramid",  "queen",    
+  "radar",    "radio",    "random",   "rapid",    "rebel",    "record",   
+  "recycle",  "reflex",   "reform",   "regard",   "regular",  "relax",    
+  "report",   "reptile",  "reverse",  "ricardo",  "ringo",    "ritual",   
+  "robert",   "robot",    "rocket",   "rodeo",    "romeo",    "royal",    
+  "russian",  "safari",   "salad",    "salami",   "salmon",   "salon",    
+  "salute",   "samba",    "sandra",   "santana",  "sardine",  "school",   
+  "screen",   "script",   "second",   "secret",   "section",  "segment",  
+  "select",   "seminar",  "senator",  "senior",   "sensor",   "serial",   
+  "service",  "sheriff",  "shock",    "sierra",   "signal",   "silicon",  
+  "silver",   "similar",  "simon",    "single",   "siren",    "slogan",   
+  "social",   "soda",     "solar",    "solid",    "solo",     "sonic",    
+  "soviet",   "special",  "speed",    "spiral",   "spirit",   "sport",    
+  "static",   "station",  "status",   "stereo",   "stone",    "stop",     
+  "street",   "strong",   "student",  "studio",   "style",    "subject",  
+  "sultan",   "super",    "susan",    "sushi",    "suzuki",   "switch",   
+  "symbol",   "system",   "tactic",   "tahiti",   "talent",   "tango",    
+  "tarzan",   "taxi",     "telex",    "tempo",    "tennis",   "texas",    
+  "textile",  "theory",   "thermos",  "tiger",    "titanic",  "tokyo",    
+  "tomato",   "topic",    "tornado",  "toronto",  "torpedo",  "total",    
+  "totem",    "tourist",  "tractor",  "traffic",  "transit",  "trapeze",  
+  "travel",   "tribal",   "trick",    "trident",  "trilogy",  "tripod",   
+  "tropic",   "trumpet",  "tulip",    "tuna",     "turbo",    "twist",    
+  "ultra",    "uniform",  "union",    "uranium",  "vacuum",   "valid",    
+  "vampire",  "vanilla",  "vatican",  "velvet",   "ventura",  "venus",    
+  "vertigo",  "veteran",  "victor",   "video",    "vienna",   "viking",   
+  "village",  "vincent",  "violet",   "violin",   "virtual",  "virus",    
+  "visa",     "vision",   "visitor",  "visual",   "vitamin",  "viva",     
+  "vocal",    "vodka",    "volcano",  "voltage",  "volume",   "voyage",   
+  "water",    "weekend",  "welcome",  "western",  "window",   "winter",   
+  "wizard",   "wolf",     "world",    "xray",     "yankee",   "yoga",     
+  "yogurt",   "yoyo",     "zebra",    "zero",     "zigzag",   "zipper",   
+  "zodiac",   "zoom",     "abraham",  "action",   "address",  "alabama",  
+  "alfred",   "almond",   "ammonia",  "analyze",  "annual",   "answer",   
+  "apple",    "arena",    "armada",   "arsenal",  "atlanta",  "atomic",   
+  "avenue",   "average",  "bagel",    "baker",    "ballet",   "bambino",  
+  "bamboo",   "barbara",  "basket",   "bazaar",   "benefit",  "bicycle",  
+  "bishop",   "blitz",    "bonjour",  "bottle",   "bridge",   "british",  
+  "brother",  "brush",    "budget",   "cabaret",  "cadet",    "candle",   
+  "capitan",  "capsule",  "career",   "cartoon",  "channel",  "chapter",  
+  "cheese",   "circle",   "cobalt",   "cockpit",  "college",  "compass",  
+  "comrade",  "condor",   "crimson",  "cyclone",  "darwin",   "declare",  
+  "degree",   "delete",   "delphi",   "denver",   "desert",   "divide",   
+  "dolby",    "domain",   "domingo",  "double",   "drink",    "driver",   
+  "eagle",    "earth",    "echo",     "eclipse",  "editor",   "educate",  
+  "edward",   "effect",   "electra",  "emerald",  "emotion",  "empire",   
+  "empty",    "escape",   "eternal",  "evening",  "exhibit",  "expand",   
+  "explore",  "extreme",  "ferrari",  "first",    "flag",     "folio",    
+  "forget",   "forward",  "freedom",  "fresh",    "friday",   "fuji",     
+  "galileo",  "garcia",   "genesis",  "gold",     "gravity",  "habitat",  
+  "hamlet",   "harlem",   "helium",   "holiday",  "house",    "hunter",   
+  "ibiza",    "iceberg",  "imagine",  "infant",   "isotope",  "jackson",  
+  "jamaica",  "jasmine",  "java",     "jessica",  "judo",     "kitchen",  
+  "lazarus",  "letter",   "license",  "lithium",  "loyal",    "lucky",    
+  "magenta",  "mailbox",  "manual",   "marble",   "mary",     "maxwell",  
+  "mayor",    "milk",     "monarch",  "monday",   "money",    "morning",  
+  "mother",   "mystery",  "native",   "nectar",   "nelson",   "network",  
+  "next",     "nikita",   "nobel",    "nobody",   "nominal",  "norway",   
+  "nothing",  "number",   "october",  "office",   "oliver",   "opinion",  
+  "option",   "order",    "outside",  "package",  "pancake",  "pandora",  
+  "panther",  "papa",     "patient",  "pattern",  "pedro",    "pencil",   
+  "people",   "phantom",  "philips",  "pioneer",  "pluto",    "podium",   
+  "portal",   "potato",   "prize",    "process",  "protein",  "proxy",    
+  "pump",     "pupil",    "python",   "quality",  "quarter",  "quiet",    
+  "rabbit",   "radical",  "radius",   "rainbow",  "ralph",    "ramirez",  
+  "ravioli",  "raymond",  "respect",  "respond",  "result",   "resume",   
+  "retro",    "richard",  "right",    "risk",     "river",    "roger",    
+  "roman",    "rondo",    "sabrina",  "salary",   "salsa",    "sample",   
+  "samuel",   "saturn",   "savage",   "scarlet",  "scoop",    "scorpio",  
+  "scratch",  "scroll",   "sector",   "serpent",  "shadow",   "shampoo",  
+  "sharon",   "sharp",    "short",    "shrink",   "silence",  "silk",     
+  "simple",   "slang",    "smart",    "smoke",    "snake",    "society",  
+  "sonar",    "sonata",   "soprano",  "source",   "sparta",   "sphere",   
+  "spider",   "sponsor",  "spring",   "acid",     "adios",    "agatha",   
+  "alamo",    "alert",    "almanac",  "aloha",    "andrea",   "anita",    
+  "arcade",   "aurora",   "avalon",   "baby",     "baggage",  "balloon",  
+  "bank",     "basil",    "begin",    "biscuit",  "blue",     "bombay",   
+  "brain",    "brenda",   "brigade",  "cable",    "carmen",   "cello",    
+  "celtic",   "chariot",  "chrome",   "citrus",   "civil",    "cloud",    
+  "common",   "compare",  "cool",     "copper",   "coral",    "crater",   
+  "cubic",    "cupid",    "cycle",    "depend",   "door",     "dream",    
+  "dynasty",  "edison",   "edition",  "enigma",   "equal",    "eric",     
+  "event",    "evita",    "exodus",   "extend",   "famous",   "farmer",   
+  "food",     "fossil",   "frog",     "fruit",    "geneva",   "gentle",   
+  "george",   "giant",    "gilbert",  "gossip",   "gram",     "greek",    
+  "grille",   "hammer",   "harvest",  "hazard",   "heaven",   "herbert",  
+  "heroic",   "hexagon",  "husband",  "immune",   "inca",     "inch",     
+  "initial",  "isabel",   "ivory",    "jason",    "jerome",   "joel",     
+  "joshua",   "journal",  "judge",    "juliet",   "jump",     "justice",  
+  "kimono",   "kinetic",  "leonid",   "lima",     "maze",     "medusa",   
+  "member",   "memphis",  "michael",  "miguel",   "milan",    "mile",     
+  "miller",   "mimic",    "mimosa",   "mission",  "monkey",   "moral",    
+  "moses",    "mouse",    "nancy",    "natasha",  "nebula",   "nickel",   
+  "nina",     "noise",    "orchid",   "oregano",  "origami",  "orinoco",  
+  "orion",    "othello",  "paper",    "paprika",  "prelude",  "prepare",  
+  "pretend",  "profit",   "promise",  "provide",  "puzzle",   "remote",   
+  "repair",   "reply",    "rival",    "riviera",  "robin",    "rose",     
+  "rover",    "rudolf",   "saga",     "sahara",   "scholar",  "shelter",  
+  "ship",     "shoe",     "sigma",    "sister",   "sleep",    "smile",    
+  "spain",    "spark",    "split",    "spray",    "square",   "stadium",  
+  "star",     "storm",    "story",    "strange",  "stretch",  "stuart",   
+  "subway",   "sugar",    "sulfur",   "summer",   "survive",  "sweet",    
+  "swim",     "table",    "taboo",    "target",   "teacher",  "telecom",  
+  "temple",   "tibet",    "ticket",   "tina",     "today",    "toga",     
+  "tommy",    "tower",    "trivial",  "tunnel",   "turtle",   "twin",     
+  "uncle",    "unicorn",  "unique",   "update",   "valery",   "vega",     
+  "version",  "voodoo",   "warning",  "william",  "wonder",   "year",     
+  "yellow",   "young",    "absent",   "absorb",   "accent",   "alfonso",  
+  "alias",    "ambient",  "andy",     "anvil",    "appear",   "apropos",  
+  "archer",   "ariel",    "armor",    "arrow",    "austin",   "avatar",   
+  "axis",     "baboon",   "bahama",   "bali",     "balsa",    "bazooka",  
+  "beach",    "beast",    "beatles",  "beauty",   "before",   "benny",    
+  "betty",    "between",  "beyond",   "billy",    "bison",    "blast",    
+  "bless",    "bogart",   "bonanza",  "book",     "border",   "brave",    
+  "bread",    "break",    "broken",   "bucket",   "buenos",   "buffalo",  
+  "bundle",   "button",   "buzzer",   "byte",     "caesar",   "camilla",  
+  "canary",   "candid",   "carrot",   "cave",     "chant",    "child",    
+  "choice",   "chris",    "cipher",   "clarion",  "clark",    "clever",   
+  "cliff",    "clone",    "conan",    "conduct",  "congo",    "content",  
+  "costume",  "cotton",   "cover",    "crack",    "current",  "danube",   
+  "data",     "decide",   "desire",   "detail",   "dexter",   "dinner",   
+  "dispute",  "donor",    "druid",    "drum",     "easy",     "eddie",    
+  "enjoy",    "enrico",   "epoxy",    "erosion",  "except",   "exile",    
+  "explain",  "fame",     "fast",     "father",   "felix",    "field",    
+  "fiona",    "fire",     "fish",     "flame",    "flex",     "flipper",  
+  "float",    "flood",    "floor",    "forbid",   "forever",  "fractal",  
+  "frame",    "freddie",  "front",    "fuel",     "gallop",   "game",     
+  "garbo",    "gate",     "gibson",   "ginger",   "giraffe",  "gizmo",    
+  "glass",    "goblin",   "gopher",   "grace",    "gray",     "gregory",  
+  "grid",     "griffin",  "ground",   "guest",    "gustav",   "gyro",     
+  "hair",     "halt",     "harris",   "heart",    "heavy",    "herman",   
+  "hippie",   "hobby",    "honey",    "hope",     "horse",    "hostel",   
+  "hydro",    "imitate",  "info",     "ingrid",   "inside",   "invent",   
+  "invest",   "invite",   "iron",     "ivan",     "james",    "jester",   
+  "jimmy",    "join",     "joseph",   "juice",    "julius",   "july",     
+  "justin",   "kansas",   "karl",     "kevin",    "kiwi",     "ladder",   
+  "lake",     "laura",    "learn",    "legacy",   "legend",   "lesson",   
+  "life",     "light",    "list",     "locate",   "lopez",    "lorenzo",  
+  "love",     "lunch",    "malta",    "mammal",   "margo",    "marion",   
+  "mask",     "match",    "mayday",   "meaning",  "mercy",    "middle",   
+  "mike",     "mirror",   "modest",   "morph",    "morris",   "nadia",    
+  "nato",     "navy",     "needle",   "neuron",   "never",    "newton",   
+  "nice",     "night",    "nissan",   "nitro",    "nixon",    "north",    
+  "oberon",   "octavia",  "ohio",     "olga",     "open",     "opus",     
+  "orca",     "oval",     "owner",    "page",     "paint",    "palma",    
+  "parade",   "parent",   "parole",   "paul",     "peace",    "pearl",    
+  "perform",  "phoenix",  "phrase",   "pierre",   "pinball",  "place",    
+  "plate",    "plato",    "plume",    "pogo",     "point",    "polite",   
+  "polka",    "poncho",   "powder",   "prague",   "press",    "presto",   
+  "pretty",   "prime",    "promo",    "quasi",    "quest",    "quick",    
+  "quiz",     "quota",    "race",     "rachel",   "raja",     "ranger",   
+  "region",   "remark",   "rent",     "reward",   "rhino",    "ribbon",   
+  "rider",    "road",     "rodent",   "round",    "rubber",   "ruby",     
+  "rufus",    "sabine",   "saddle",   "sailor",   "saint",    "salt",     
+  "satire",   "scale",    "scuba",    "season",   "secure",   "shake",    
+  "shallow",  "shannon",  "shave",    "shelf",    "sherman",  "shine",    
+  "shirt",    "side",     "sinatra",  "sincere",  "size",     "slalom",   
+  "slow",     "small",    "snow",     "sofia",    "song",     "sound",    
+  "south",    "speech",   "spell",    "spend",    "spoon",    "stage",    
+  "stamp",    "stand",    "state",    "stella",   "stick",    "sting",    
+  "stock",    "store",    "sunday",   "sunset",   "support",  "sweden",   
+  "swing",    "tape",     "think",    "thomas",   "tictac",   "time",     
+  "toast",    "tobacco",  "tonight",  "torch",    "torso",    "touch",    
+  "toyota",   "trade",    "tribune",  "trinity",  "triton",   "truck",    
+  "trust",    "type",     "under",    "unit",     "urban",    "urgent",   
+  "user",     "value",    "vendor",   "venice",   "verona",   "vibrate",  
+  "virgo",    "visible",  "vista",    "vital",    "voice",    "vortex",   
+  "waiter",   "watch",    "wave",     "weather",  "wedding",  "wheel",    
+  "whiskey",  "wisdom",   "deal",     "null",     "nurse",    "quebec",   
+  "reserve",  "reunion",  "roof",     "singer",   "verbal",   "amen",     
+  "ego",      "fax",      "jet",      "job",      "rio",      "ski",      
+  "yes"
+};    

+ 292 - 0
wordlists/mn_wordlist.py

@@ -0,0 +1,292 @@
+#!/usr/bin/python
+
+"""
+mn_words.py:  Mnemomic wordlist
+
+Copyright (c) 2000  Oren Tirosh <oren@hishome.net>
+
+Oren Tirosh is no longer maintaining the original version of this
+project.
+
+Stephen Paul Weber likes it and is making it accessible on GitHub.
+https://github.com/singpolyma/mnemonicode
+"""
+
+mn_words = [
+  "academy",  "acrobat",  "active",   "actor",    "adam",     "admiral",
+  "adrian",   "africa",   "agenda",   "agent",    "airline",  "airport",
+  "aladdin",  "alarm",    "alaska",   "albert",   "albino",   "album",
+  "alcohol",  "alex",     "algebra",  "alibi",    "alice",    "alien",
+  "alpha",    "alpine",   "amadeus",  "amanda",   "amazon",   "amber",
+  "america",  "amigo",    "analog",   "anatomy",  "angel",    "animal",
+  "antenna",  "antonio",  "apollo",   "april",    "archive",  "arctic",
+  "arizona",  "arnold",   "aroma",    "arthur",   "artist",   "asia",
+  "aspect",   "aspirin",  "athena",   "athlete",  "atlas",    "audio",
+  "august",   "austria",  "axiom",    "aztec",    "balance",  "ballad",
+  "banana",   "bandit",   "banjo",    "barcode",  "baron",    "basic",
+  "battery",  "belgium",  "berlin",   "bermuda",  "bernard",  "bikini",
+  "binary",   "bingo",    "biology",  "block",    "blonde",   "bonus",
+  "boris",    "boston",   "boxer",    "brandy",   "bravo",    "brazil",
+  "bronze",   "brown",    "bruce",    "bruno",    "burger",   "burma",
+  "cabinet",  "cactus",   "cafe",     "cairo",    "cake",     "calypso",
+  "camel",    "camera",   "campus",   "canada",   "canal",    "cannon",
+  "canoe",    "cantina",  "canvas",   "canyon",   "capital",  "caramel",
+  "caravan",  "carbon",   "cargo",    "carlo",    "carol",    "carpet",
+  "cartel",   "casino",   "castle",   "castro",   "catalog",  "caviar",
+  "cecilia",  "cement",   "center",   "century",  "ceramic",  "chamber",
+  "chance",   "change",   "chaos",    "charlie",  "charm",    "charter",
+  "chef",     "chemist",  "cherry",   "chess",    "chicago",  "chicken",
+  "chief",    "china",    "cigar",    "cinema",   "circus",   "citizen",
+  "city",     "clara",    "classic",  "claudia",  "clean",    "client",
+  "climax",   "clinic",   "clock",    "club",     "cobra",    "coconut",
+  "cola",     "collect",  "colombo",  "colony",   "color",    "combat",
+  "comedy",   "comet",    "command",  "compact",  "company",  "complex",
+  "concept",  "concert",  "connect",  "consul",   "contact",  "context",
+  "contour",  "control",  "convert",  "copy",     "corner",   "corona",
+  "correct",  "cosmos",   "couple",   "courage",  "cowboy",   "craft",
+  "crash",    "credit",   "cricket",  "critic",   "crown",    "crystal",
+  "cuba",     "culture",  "dallas",   "dance",    "daniel",   "david",
+  "decade",   "decimal",  "deliver",  "delta",    "deluxe",   "demand",
+  "demo",     "denmark",  "derby",    "design",   "detect",   "develop",
+  "diagram",  "dialog",   "diamond",  "diana",    "diego",    "diesel",
+  "diet",     "digital",  "dilemma",  "diploma",  "direct",   "disco",
+  "disney",   "distant",  "doctor",   "dollar",   "dominic",  "domino",
+  "donald",   "dragon",   "drama",    "dublin",   "duet",     "dynamic",
+  "east",     "ecology",  "economy",  "edgar",    "egypt",    "elastic",
+  "elegant",  "element",  "elite",    "elvis",    "email",    "energy",
+  "engine",   "english",  "episode",  "equator",  "escort",   "ethnic",
+  "europe",   "everest",  "evident",  "exact",    "example",  "exit",
+  "exotic",   "export",   "express",  "extra",    "fabric",   "factor",
+  "falcon",   "family",   "fantasy",  "fashion",  "fiber",    "fiction",
+  "fidel",    "fiesta",   "figure",   "film",     "filter",   "final",
+  "finance",  "finish",   "finland",  "flash",    "florida",  "flower",
+  "fluid",    "flute",    "focus",    "ford",     "forest",   "formal",
+  "format",   "formula",  "fortune",  "forum",    "fragile",  "france",
+  "frank",    "friend",   "frozen",   "future",   "gabriel",  "galaxy",
+  "gallery",  "gamma",    "garage",   "garden",   "garlic",   "gemini",
+  "general",  "genetic",  "genius",   "germany",  "global",   "gloria",
+  "golf",     "gondola",  "gong",     "good",     "gordon",   "gorilla",
+  "grand",    "granite",  "graph",    "green",    "group",    "guide",
+  "guitar",   "guru",     "hand",     "happy",    "harbor",   "harmony",
+  "harvard",  "havana",   "hawaii",   "helena",   "hello",    "henry",
+  "hilton",   "history",  "horizon",  "hotel",    "human",    "humor",
+  "icon",     "idea",     "igloo",    "igor",     "image",    "impact",
+  "import",   "index",    "india",    "indigo",   "input",    "insect",
+  "instant",  "iris",     "italian",  "jacket",   "jacob",    "jaguar",
+  "janet",    "japan",    "jargon",   "jazz",     "jeep",     "john",
+  "joker",    "jordan",   "jumbo",    "june",     "jungle",   "junior",
+  "jupiter",  "karate",   "karma",    "kayak",    "kermit",   "kilo",
+  "king",     "koala",    "korea",    "labor",    "lady",     "lagoon",
+  "laptop",   "laser",    "latin",    "lava",     "lecture",  "left",
+  "legal",    "lemon",    "level",    "lexicon",  "liberal",  "libra",
+  "limbo",    "limit",    "linda",    "linear",   "lion",     "liquid",
+  "liter",    "little",   "llama",    "lobby",    "lobster",  "local",
+  "logic",    "logo",     "lola",     "london",   "lotus",    "lucas",
+  "lunar",    "machine",  "macro",    "madam",    "madonna",  "madrid",
+  "maestro",  "magic",    "magnet",   "magnum",   "major",    "mama",
+  "mambo",    "manager",  "mango",    "manila",   "marco",    "marina",
+  "market",   "mars",     "martin",   "marvin",   "master",   "matrix",
+  "maximum",  "media",    "medical",  "mega",     "melody",   "melon",
+  "memo",     "mental",   "mentor",   "menu",     "mercury",  "message",
+  "metal",    "meteor",   "meter",    "method",   "metro",    "mexico",
+  "miami",    "micro",    "million",  "mineral",  "minimum",  "minus",
+  "minute",   "miracle",  "mirage",   "miranda",  "mister",   "mixer",
+  "mobile",   "model",    "modem",    "modern",   "modular",  "moment",
+  "monaco",   "monica",   "monitor",  "mono",     "monster",  "montana",
+  "morgan",   "motel",    "motif",    "motor",    "mozart",   "multi",
+  "museum",   "music",    "mustang",  "natural",  "neon",     "nepal",
+  "neptune",  "nerve",    "neutral",  "nevada",   "news",     "ninja",
+  "nirvana",  "normal",   "nova",     "novel",    "nuclear",  "numeric",
+  "nylon",    "oasis",    "object",   "observe",  "ocean",    "octopus",
+  "olivia",   "olympic",  "omega",    "opera",    "optic",    "optimal",
+  "orange",   "orbit",    "organic",  "orient",   "origin",   "orlando",
+  "oscar",    "oxford",   "oxygen",   "ozone",    "pablo",    "pacific",
+  "pagoda",   "palace",   "pamela",   "panama",   "panda",    "panel",
+  "panic",    "paradox",  "pardon",   "paris",    "parker",   "parking",
+  "parody",   "partner",  "passage",  "passive",  "pasta",    "pastel",
+  "patent",   "patriot",  "patrol",   "patron",   "pegasus",  "pelican",
+  "penguin",  "pepper",   "percent",  "perfect",  "perfume",  "period",
+  "permit",   "person",   "peru",     "phone",    "photo",    "piano",
+  "picasso",  "picnic",   "picture",  "pigment",  "pilgrim",  "pilot",
+  "pirate",   "pixel",    "pizza",    "planet",   "plasma",   "plaster",
+  "plastic",  "plaza",    "pocket",   "poem",     "poetic",   "poker",
+  "polaris",  "police",   "politic",  "polo",     "polygon",  "pony",
+  "popcorn",  "popular",  "postage",  "postal",   "precise",  "prefix",
+  "premium",  "present",  "price",    "prince",   "printer",  "prism",
+  "private",  "product",  "profile",  "program",  "project",  "protect",
+  "proton",   "public",   "pulse",    "puma",     "pyramid",  "queen",
+  "radar",    "radio",    "random",   "rapid",    "rebel",    "record",
+  "recycle",  "reflex",   "reform",   "regard",   "regular",  "relax",
+  "report",   "reptile",  "reverse",  "ricardo",  "ringo",    "ritual",
+  "robert",   "robot",    "rocket",   "rodeo",    "romeo",    "royal",
+  "russian",  "safari",   "salad",    "salami",   "salmon",   "salon",
+  "salute",   "samba",    "sandra",   "santana",  "sardine",  "school",
+  "screen",   "script",   "second",   "secret",   "section",  "segment",
+  "select",   "seminar",  "senator",  "senior",   "sensor",   "serial",
+  "service",  "sheriff",  "shock",    "sierra",   "signal",   "silicon",
+  "silver",   "similar",  "simon",    "single",   "siren",    "slogan",
+  "social",   "soda",     "solar",    "solid",    "solo",     "sonic",
+  "soviet",   "special",  "speed",    "spiral",   "spirit",   "sport",
+  "static",   "station",  "status",   "stereo",   "stone",    "stop",
+  "street",   "strong",   "student",  "studio",   "style",    "subject",
+  "sultan",   "super",    "susan",    "sushi",    "suzuki",   "switch",
+  "symbol",   "system",   "tactic",   "tahiti",   "talent",   "tango",
+  "tarzan",   "taxi",     "telex",    "tempo",    "tennis",   "texas",
+  "textile",  "theory",   "thermos",  "tiger",    "titanic",  "tokyo",
+  "tomato",   "topic",    "tornado",  "toronto",  "torpedo",  "total",
+  "totem",    "tourist",  "tractor",  "traffic",  "transit",  "trapeze",
+  "travel",   "tribal",   "trick",    "trident",  "trilogy",  "tripod",
+  "tropic",   "trumpet",  "tulip",    "tuna",     "turbo",    "twist",
+  "ultra",    "uniform",  "union",    "uranium",  "vacuum",   "valid",
+  "vampire",  "vanilla",  "vatican",  "velvet",   "ventura",  "venus",
+  "vertigo",  "veteran",  "victor",   "video",    "vienna",   "viking",
+  "village",  "vincent",  "violet",   "violin",   "virtual",  "virus",
+  "visa",     "vision",   "visitor",  "visual",   "vitamin",  "viva",
+  "vocal",    "vodka",    "volcano",  "voltage",  "volume",   "voyage",
+  "water",    "weekend",  "welcome",  "western",  "window",   "winter",
+  "wizard",   "wolf",     "world",    "xray",     "yankee",   "yoga",
+  "yogurt",   "yoyo",     "zebra",    "zero",     "zigzag",   "zipper",
+  "zodiac",   "zoom",     "abraham",  "action",   "address",  "alabama",
+  "alfred",   "almond",   "ammonia",  "analyze",  "annual",   "answer",
+  "apple",    "arena",    "armada",   "arsenal",  "atlanta",  "atomic",
+  "avenue",   "average",  "bagel",    "baker",    "ballet",   "bambino",
+  "bamboo",   "barbara",  "basket",   "bazaar",   "benefit",  "bicycle",
+  "bishop",   "blitz",    "bonjour",  "bottle",   "bridge",   "british",
+  "brother",  "brush",    "budget",   "cabaret",  "cadet",    "candle",
+  "capitan",  "capsule",  "career",   "cartoon",  "channel",  "chapter",
+  "cheese",   "circle",   "cobalt",   "cockpit",  "college",  "compass",
+  "comrade",  "condor",   "crimson",  "cyclone",  "darwin",   "declare",
+  "degree",   "delete",   "delphi",   "denver",   "desert",   "divide",
+  "dolby",    "domain",   "domingo",  "double",   "drink",    "driver",
+  "eagle",    "earth",    "echo",     "eclipse",  "editor",   "educate",
+  "edward",   "effect",   "electra",  "emerald",  "emotion",  "empire",
+  "empty",    "escape",   "eternal",  "evening",  "exhibit",  "expand",
+  "explore",  "extreme",  "ferrari",  "first",    "flag",     "folio",
+  "forget",   "forward",  "freedom",  "fresh",    "friday",   "fuji",
+  "galileo",  "garcia",   "genesis",  "gold",     "gravity",  "habitat",
+  "hamlet",   "harlem",   "helium",   "holiday",  "house",    "hunter",
+  "ibiza",    "iceberg",  "imagine",  "infant",   "isotope",  "jackson",
+  "jamaica",  "jasmine",  "java",     "jessica",  "judo",     "kitchen",
+  "lazarus",  "letter",   "license",  "lithium",  "loyal",    "lucky",
+  "magenta",  "mailbox",  "manual",   "marble",   "mary",     "maxwell",
+  "mayor",    "milk",     "monarch",  "monday",   "money",    "morning",
+  "mother",   "mystery",  "native",   "nectar",   "nelson",   "network",
+  "next",     "nikita",   "nobel",    "nobody",   "nominal",  "norway",
+  "nothing",  "number",   "october",  "office",   "oliver",   "opinion",
+  "option",   "order",    "outside",  "package",  "pancake",  "pandora",
+  "panther",  "papa",     "patient",  "pattern",  "pedro",    "pencil",
+  "people",   "phantom",  "philips",  "pioneer",  "pluto",    "podium",
+  "portal",   "potato",   "prize",    "process",  "protein",  "proxy",
+  "pump",     "pupil",    "python",   "quality",  "quarter",  "quiet",
+  "rabbit",   "radical",  "radius",   "rainbow",  "ralph",    "ramirez",
+  "ravioli",  "raymond",  "respect",  "respond",  "result",   "resume",
+  "retro",    "richard",  "right",    "risk",     "river",    "roger",
+  "roman",    "rondo",    "sabrina",  "salary",   "salsa",    "sample",
+  "samuel",   "saturn",   "savage",   "scarlet",  "scoop",    "scorpio",
+  "scratch",  "scroll",   "sector",   "serpent",  "shadow",   "shampoo",
+  "sharon",   "sharp",    "short",    "shrink",   "silence",  "silk",
+  "simple",   "slang",    "smart",    "smoke",    "snake",    "society",
+  "sonar",    "sonata",   "soprano",  "source",   "sparta",   "sphere",
+  "spider",   "sponsor",  "spring",   "acid",     "adios",    "agatha",
+  "alamo",    "alert",    "almanac",  "aloha",    "andrea",   "anita",
+  "arcade",   "aurora",   "avalon",   "baby",     "baggage",  "balloon",
+  "bank",     "basil",    "begin",    "biscuit",  "blue",     "bombay",
+  "brain",    "brenda",   "brigade",  "cable",    "carmen",   "cello",
+  "celtic",   "chariot",  "chrome",   "citrus",   "civil",    "cloud",
+  "common",   "compare",  "cool",     "copper",   "coral",    "crater",
+  "cubic",    "cupid",    "cycle",    "depend",   "door",     "dream",
+  "dynasty",  "edison",   "edition",  "enigma",   "equal",    "eric",
+  "event",    "evita",    "exodus",   "extend",   "famous",   "farmer",
+  "food",     "fossil",   "frog",     "fruit",    "geneva",   "gentle",
+  "george",   "giant",    "gilbert",  "gossip",   "gram",     "greek",
+  "grille",   "hammer",   "harvest",  "hazard",   "heaven",   "herbert",
+  "heroic",   "hexagon",  "husband",  "immune",   "inca",     "inch",
+  "initial",  "isabel",   "ivory",    "jason",    "jerome",   "joel",
+  "joshua",   "journal",  "judge",    "juliet",   "jump",     "justice",
+  "kimono",   "kinetic",  "leonid",   "lima",     "maze",     "medusa",
+  "member",   "memphis",  "michael",  "miguel",   "milan",    "mile",
+  "miller",   "mimic",    "mimosa",   "mission",  "monkey",   "moral",
+  "moses",    "mouse",    "nancy",    "natasha",  "nebula",   "nickel",
+  "nina",     "noise",    "orchid",   "oregano",  "origami",  "orinoco",
+  "orion",    "othello",  "paper",    "paprika",  "prelude",  "prepare",
+  "pretend",  "profit",   "promise",  "provide",  "puzzle",   "remote",
+  "repair",   "reply",    "rival",    "riviera",  "robin",    "rose",
+  "rover",    "rudolf",   "saga",     "sahara",   "scholar",  "shelter",
+  "ship",     "shoe",     "sigma",    "sister",   "sleep",    "smile",
+  "spain",    "spark",    "split",    "spray",    "square",   "stadium",
+  "star",     "storm",    "story",    "strange",  "stretch",  "stuart",
+  "subway",   "sugar",    "sulfur",   "summer",   "survive",  "sweet",
+  "swim",     "table",    "taboo",    "target",   "teacher",  "telecom",
+  "temple",   "tibet",    "ticket",   "tina",     "today",    "toga",
+  "tommy",    "tower",    "trivial",  "tunnel",   "turtle",   "twin",
+  "uncle",    "unicorn",  "unique",   "update",   "valery",   "vega",
+  "version",  "voodoo",   "warning",  "william",  "wonder",   "year",
+  "yellow",   "young",    "absent",   "absorb",   "accent",   "alfonso",
+  "alias",    "ambient",  "andy",     "anvil",    "appear",   "apropos",
+  "archer",   "ariel",    "armor",    "arrow",    "austin",   "avatar",
+  "axis",     "baboon",   "bahama",   "bali",     "balsa",    "bazooka",
+  "beach",    "beast",    "beatles",  "beauty",   "before",   "benny",
+  "betty",    "between",  "beyond",   "billy",    "bison",    "blast",
+  "bless",    "bogart",   "bonanza",  "book",     "border",   "brave",
+  "bread",    "break",    "broken",   "bucket",   "buenos",   "buffalo",
+  "bundle",   "button",   "buzzer",   "byte",     "caesar",   "camilla",
+  "canary",   "candid",   "carrot",   "cave",     "chant",    "child",
+  "choice",   "chris",    "cipher",   "clarion",  "clark",    "clever",
+  "cliff",    "clone",    "conan",    "conduct",  "congo",    "content",
+  "costume",  "cotton",   "cover",    "crack",    "current",  "danube",
+  "data",     "decide",   "desire",   "detail",   "dexter",   "dinner",
+  "dispute",  "donor",    "druid",    "drum",     "easy",     "eddie",
+  "enjoy",    "enrico",   "epoxy",    "erosion",  "except",   "exile",
+  "explain",  "fame",     "fast",     "father",   "felix",    "field",
+  "fiona",    "fire",     "fish",     "flame",    "flex",     "flipper",
+  "float",    "flood",    "floor",    "forbid",   "forever",  "fractal",
+  "frame",    "freddie",  "front",    "fuel",     "gallop",   "game",
+  "garbo",    "gate",     "gibson",   "ginger",   "giraffe",  "gizmo",
+  "glass",    "goblin",   "gopher",   "grace",    "gray",     "gregory",
+  "grid",     "griffin",  "ground",   "guest",    "gustav",   "gyro",
+  "hair",     "halt",     "harris",   "heart",    "heavy",    "herman",
+  "hippie",   "hobby",    "honey",    "hope",     "horse",    "hostel",
+  "hydro",    "imitate",  "info",     "ingrid",   "inside",   "invent",
+  "invest",   "invite",   "iron",     "ivan",     "james",    "jester",
+  "jimmy",    "join",     "joseph",   "juice",    "julius",   "july",
+  "justin",   "kansas",   "karl",     "kevin",    "kiwi",     "ladder",
+  "lake",     "laura",    "learn",    "legacy",   "legend",   "lesson",
+  "life",     "light",    "list",     "locate",   "lopez",    "lorenzo",
+  "love",     "lunch",    "malta",    "mammal",   "margo",    "marion",
+  "mask",     "match",    "mayday",   "meaning",  "mercy",    "middle",
+  "mike",     "mirror",   "modest",   "morph",    "morris",   "nadia",
+  "nato",     "navy",     "needle",   "neuron",   "never",    "newton",
+  "nice",     "night",    "nissan",   "nitro",    "nixon",    "north",
+  "oberon",   "octavia",  "ohio",     "olga",     "open",     "opus",
+  "orca",     "oval",     "owner",    "page",     "paint",    "palma",
+  "parade",   "parent",   "parole",   "paul",     "peace",    "pearl",
+  "perform",  "phoenix",  "phrase",   "pierre",   "pinball",  "place",
+  "plate",    "plato",    "plume",    "pogo",     "point",    "polite",
+  "polka",    "poncho",   "powder",   "prague",   "press",    "presto",
+  "pretty",   "prime",    "promo",    "quasi",    "quest",    "quick",
+  "quiz",     "quota",    "race",     "rachel",   "raja",     "ranger",
+  "region",   "remark",   "rent",     "reward",   "rhino",    "ribbon",
+  "rider",    "road",     "rodent",   "round",    "rubber",   "ruby",
+  "rufus",    "sabine",   "saddle",   "sailor",   "saint",    "salt",
+  "satire",   "scale",    "scuba",    "season",   "secure",   "shake",
+  "shallow",  "shannon",  "shave",    "shelf",    "sherman",  "shine",
+  "shirt",    "side",     "sinatra",  "sincere",  "size",     "slalom",
+  "slow",     "small",    "snow",     "sofia",    "song",     "sound",
+  "south",    "speech",   "spell",    "spend",    "spoon",    "stage",
+  "stamp",    "stand",    "state",    "stella",   "stick",    "sting",
+  "stock",    "store",    "sunday",   "sunset",   "support",  "sweden",
+  "swing",    "tape",     "think",    "thomas",   "tictac",   "time",
+  "toast",    "tobacco",  "tonight",  "torch",    "torso",    "touch",
+  "toyota",   "trade",    "tribune",  "trinity",  "triton",   "truck",
+  "trust",    "type",     "under",    "unit",     "urban",    "urgent",
+  "user",     "value",    "vendor",   "venice",   "verona",   "vibrate",
+  "virgo",    "visible",  "vista",    "vital",    "voice",    "vortex",
+  "waiter",   "watch",    "wave",     "weather",  "wedding",  "wheel",
+  "whiskey",  "wisdom",   "deal",     "null",     "nurse",    "quebec",
+  "reserve",  "reunion",  "roof",     "singer",   "verbal",   "amen",
+  "ego",      "fax",      "jet",      "job",      "rio",      "ski",
+  "yes"
+]
+
+if __name__ == "__main__":
+	print "\n".join(mn_words)

+ 1642 - 0
wordlists/mn_wordlist.sort.py

@@ -0,0 +1,1642 @@
+#!/usr/bin/python
+
+# Oren Tirosh wordlist
+# Copyright (c) 2000  Oren Tirosh <oren@hishome.net>
+
+# This is a sorted version of the wordlist
+
+oren_tirosh_wordlist = """
+abraham
+absent
+absorb
+academy
+accent
+acid
+acrobat
+action
+active
+actor
+adam
+address
+adios
+admiral
+adrian
+africa
+agatha
+agenda
+agent
+airline
+airport
+alabama
+aladdin
+alamo
+alarm
+alaska
+albert
+albino
+album
+alcohol
+alert
+alex
+alfonso
+alfred
+algebra
+alias
+alibi
+alice
+alien
+almanac
+almond
+aloha
+alpha
+alpine
+amadeus
+amanda
+amazon
+amber
+ambient
+amen
+america
+amigo
+ammonia
+analog
+analyze
+anatomy
+andrea
+andy
+angel
+animal
+anita
+annual
+answer
+antenna
+antonio
+anvil
+apollo
+appear
+apple
+april
+apropos
+arcade
+archer
+archive
+arctic
+arena
+ariel
+arizona
+armada
+armor
+arnold
+aroma
+arrow
+arsenal
+arthur
+artist
+asia
+aspect
+aspirin
+athena
+athlete
+atlanta
+atlas
+atomic
+audio
+august
+aurora
+austin
+austria
+avalon
+avatar
+avenue
+average
+axiom
+axis
+aztec
+baboon
+baby
+bagel
+baggage
+bahama
+baker
+balance
+bali
+ballad
+ballet
+balloon
+balsa
+bambino
+bamboo
+banana
+bandit
+banjo
+bank
+barbara
+barcode
+baron
+basic
+basil
+basket
+battery
+bazaar
+bazooka
+beach
+beast
+beatles
+beauty
+before
+begin
+belgium
+benefit
+benny
+berlin
+bermuda
+bernard
+betty
+between
+beyond
+bicycle
+bikini
+billy
+binary
+bingo
+biology
+biscuit
+bishop
+bison
+blast
+bless
+blitz
+block
+blonde
+blue
+bogart
+bombay
+bonanza
+bonjour
+bonus
+book
+border
+boris
+boston
+bottle
+boxer
+brain
+brandy
+brave
+bravo
+brazil
+bread
+break
+brenda
+bridge
+brigade
+british
+broken
+bronze
+brother
+brown
+bruce
+bruno
+brush
+bucket
+budget
+buenos
+buffalo
+bundle
+burger
+burma
+button
+buzzer
+byte
+cabaret
+cabinet
+cable
+cactus
+cadet
+caesar
+cafe
+cairo
+cake
+calypso
+camel
+camera
+camilla
+campus
+canada
+canal
+canary
+candid
+candle
+cannon
+canoe
+cantina
+canvas
+canyon
+capital
+capitan
+capsule
+caramel
+caravan
+carbon
+career
+cargo
+carlo
+carmen
+carol
+carpet
+carrot
+cartel
+cartoon
+casino
+castle
+castro
+catalog
+cave
+caviar
+cecilia
+cello
+celtic
+cement
+center
+century
+ceramic
+chamber
+chance
+change
+channel
+chant
+chaos
+chapter
+chariot
+charlie
+charm
+charter
+cheese
+chef
+chemist
+cherry
+chess
+chicago
+chicken
+chief
+child
+china
+choice
+chris
+chrome
+cigar
+cinema
+cipher
+circle
+circus
+citizen
+citrus
+city
+civil
+clara
+clarion
+clark
+classic
+claudia
+clean
+clever
+client
+cliff
+climax
+clinic
+clock
+clone
+cloud
+club
+cobalt
+cobra
+cockpit
+coconut
+cola
+collect
+college
+colombo
+colony
+color
+combat
+comedy
+comet
+command
+common
+compact
+company
+compare
+compass
+complex
+comrade
+conan
+concept
+concert
+condor
+conduct
+congo
+connect
+consul
+contact
+content
+context
+contour
+control
+convert
+cool
+copper
+copy
+coral
+corner
+corona
+correct
+cosmos
+costume
+cotton
+couple
+courage
+cover
+cowboy
+crack
+craft
+crash
+crater
+credit
+cricket
+crimson
+critic
+crown
+crystal
+cuba
+cubic
+culture
+cupid
+current
+cycle
+cyclone
+dallas
+dance
+daniel
+danube
+darwin
+data
+david
+deal
+decade
+decide
+decimal
+declare
+degree
+delete
+deliver
+delphi
+delta
+deluxe
+demand
+demo
+denmark
+denver
+depend
+derby
+desert
+design
+desire
+detail
+detect
+develop
+dexter
+diagram
+dialog
+diamond
+diana
+diego
+diesel
+diet
+digital
+dilemma
+dinner
+diploma
+direct
+disco
+disney
+dispute
+distant
+divide
+doctor
+dolby
+dollar
+domain
+domingo
+dominic
+domino
+donald
+donor
+door
+double
+dragon
+drama
+dream
+drink
+driver
+druid
+drum
+dublin
+duet
+dynamic
+dynasty
+eagle
+earth
+east
+easy
+echo
+eclipse
+ecology
+economy
+eddie
+edgar
+edison
+edition
+editor
+educate
+edward
+effect
+ego
+egypt
+elastic
+electra
+elegant
+element
+elite
+elvis
+email
+emerald
+emotion
+empire
+empty
+energy
+engine
+english
+enigma
+enjoy
+enrico
+episode
+epoxy
+equal
+equator
+eric
+erosion
+escape
+escort
+eternal
+ethnic
+europe
+evening
+event
+everest
+evident
+evita
+exact
+example
+except
+exhibit
+exile
+exit
+exodus
+exotic
+expand
+explain
+explore
+export
+express
+extend
+extra
+extreme
+fabric
+factor
+falcon
+fame
+family
+famous
+fantasy
+farmer
+fashion
+fast
+father
+fax
+felix
+ferrari
+fiber
+fiction
+fidel
+field
+fiesta
+figure
+film
+filter
+final
+finance
+finish
+finland
+fiona
+fire
+first
+fish
+flag
+flame
+flash
+flex
+flipper
+float
+flood
+floor
+florida
+flower
+fluid
+flute
+focus
+folio
+food
+forbid
+ford
+forest
+forever
+forget
+formal
+format
+formula
+fortune
+forum
+forward
+fossil
+fractal
+fragile
+frame
+france
+frank
+freddie
+freedom
+fresh
+friday
+friend
+frog
+front
+frozen
+fruit
+fuel
+fuji
+future
+gabriel
+galaxy
+galileo
+gallery
+gallop
+game
+gamma
+garage
+garbo
+garcia
+garden
+garlic
+gate
+gemini
+general
+genesis
+genetic
+geneva
+genius
+gentle
+george
+germany
+giant
+gibson
+gilbert
+ginger
+giraffe
+gizmo
+glass
+global
+gloria
+goblin
+gold
+golf
+gondola
+gong
+good
+gopher
+gordon
+gorilla
+gossip
+grace
+gram
+grand
+granite
+graph
+gravity
+gray
+greek
+green
+gregory
+grid
+griffin
+grille
+ground
+group
+guest
+guide
+guitar
+guru
+gustav
+gyro
+habitat
+hair
+halt
+hamlet
+hammer
+hand
+happy
+harbor
+harlem
+harmony
+harris
+harvard
+harvest
+havana
+hawaii
+hazard
+heart
+heaven
+heavy
+helena
+helium
+hello
+henry
+herbert
+herman
+heroic
+hexagon
+hilton
+hippie
+history
+hobby
+holiday
+honey
+hope
+horizon
+horse
+hostel
+hotel
+house
+human
+humor
+hunter
+husband
+hydro
+ibiza
+iceberg
+icon
+idea
+igloo
+igor
+image
+imagine
+imitate
+immune
+impact
+import
+inca
+inch
+index
+india
+indigo
+infant
+info
+ingrid
+initial
+input
+insect
+inside
+instant
+invent
+invest
+invite
+iris
+iron
+isabel
+isotope
+italian
+ivan
+ivory
+jacket
+jackson
+jacob
+jaguar
+jamaica
+james
+janet
+japan
+jargon
+jasmine
+jason
+java
+jazz
+jeep
+jerome
+jessica
+jester
+jet
+jimmy
+job
+joel
+john
+join
+joker
+jordan
+joseph
+joshua
+journal
+judge
+judo
+juice
+juliet
+julius
+july
+jumbo
+jump
+june
+jungle
+junior
+jupiter
+justice
+justin
+kansas
+karate
+karl
+karma
+kayak
+kermit
+kevin
+kilo
+kimono
+kinetic
+king
+kitchen
+kiwi
+koala
+korea
+labor
+ladder
+lady
+lagoon
+lake
+laptop
+laser
+latin
+laura
+lava
+lazarus
+learn
+lecture
+left
+legacy
+legal
+legend
+lemon
+leonid
+lesson
+letter
+level
+lexicon
+liberal
+libra
+license
+life
+light
+lima
+limbo
+limit
+linda
+linear
+lion
+liquid
+list
+liter
+lithium
+little
+llama
+lobby
+lobster
+local
+locate
+logic
+logo
+lola
+london
+lopez
+lorenzo
+lotus
+love
+loyal
+lucas
+lucky
+lunar
+lunch
+machine
+macro
+madam
+madonna
+madrid
+maestro
+magenta
+magic
+magnet
+magnum
+mailbox
+major
+malta
+mama
+mambo
+mammal
+manager
+mango
+manila
+manual
+marble
+marco
+margo
+marina
+marion
+market
+mars
+martin
+marvin
+mary
+mask
+master
+match
+matrix
+maximum
+maxwell
+mayday
+mayor
+maze
+meaning
+media
+medical
+medusa
+mega
+melody
+melon
+member
+memo
+memphis
+mental
+mentor
+menu
+mercury
+mercy
+message
+metal
+meteor
+meter
+method
+metro
+mexico
+miami
+michael
+micro
+middle
+miguel
+mike
+milan
+mile
+milk
+miller
+million
+mimic
+mimosa
+mineral
+minimum
+minus
+minute
+miracle
+mirage
+miranda
+mirror
+mission
+mister
+mixer
+mobile
+model
+modem
+modern
+modest
+modular
+moment
+monaco
+monarch
+monday
+money
+monica
+monitor
+monkey
+mono
+monster
+montana
+moral
+morgan
+morning
+morph
+morris
+moses
+motel
+mother
+motif
+motor
+mouse
+mozart
+multi
+museum
+music
+mustang
+mystery
+nadia
+nancy
+natasha
+native
+nato
+natural
+navy
+nebula
+nectar
+needle
+nelson
+neon
+nepal
+neptune
+nerve
+network
+neuron
+neutral
+nevada
+never
+news
+newton
+next
+nice
+nickel
+night
+nikita
+nina
+ninja
+nirvana
+nissan
+nitro
+nixon
+nobel
+nobody
+noise
+nominal
+normal
+north
+norway
+nothing
+nova
+novel
+nuclear
+null
+number
+numeric
+nurse
+nylon
+oasis
+oberon
+object
+observe
+ocean
+octavia
+october
+octopus
+office
+ohio
+olga
+oliver
+olivia
+olympic
+omega
+open
+opera
+opinion
+optic
+optimal
+option
+opus
+orange
+orbit
+orca
+orchid
+order
+oregano
+organic
+orient
+origami
+origin
+orinoco
+orion
+orlando
+oscar
+othello
+outside
+oval
+owner
+oxford
+oxygen
+ozone
+pablo
+pacific
+package
+page
+pagoda
+paint
+palace
+palma
+pamela
+panama
+pancake
+panda
+pandora
+panel
+panic
+panther
+papa
+paper
+paprika
+parade
+paradox
+pardon
+parent
+paris
+parker
+parking
+parody
+parole
+partner
+passage
+passive
+pasta
+pastel
+patent
+patient
+patriot
+patrol
+patron
+pattern
+paul
+peace
+pearl
+pedro
+pegasus
+pelican
+pencil
+penguin
+people
+pepper
+percent
+perfect
+perform
+perfume
+period
+permit
+person
+peru
+phantom
+philips
+phoenix
+phone
+photo
+phrase
+piano
+picasso
+picnic
+picture
+pierre
+pigment
+pilgrim
+pilot
+pinball
+pioneer
+pirate
+pixel
+pizza
+place
+planet
+plasma
+plaster
+plastic
+plate
+plato
+plaza
+plume
+pluto
+pocket
+podium
+poem
+poetic
+pogo
+point
+poker
+polaris
+police
+polite
+politic
+polka
+polo
+polygon
+poncho
+pony
+popcorn
+popular
+portal
+postage
+postal
+potato
+powder
+prague
+precise
+prefix
+prelude
+premium
+prepare
+present
+press
+presto
+pretend
+pretty
+price
+prime
+prince
+printer
+prism
+private
+prize
+process
+product
+profile
+profit
+program
+project
+promise
+promo
+protect
+protein
+proton
+provide
+proxy
+public
+pulse
+puma
+pump
+pupil
+puzzle
+pyramid
+python
+quality
+quarter
+quasi
+quebec
+queen
+quest
+quick
+quiet
+quiz
+quota
+rabbit
+race
+rachel
+radar
+radical
+radio
+radius
+rainbow
+raja
+ralph
+ramirez
+random
+ranger
+rapid
+ravioli
+raymond
+rebel
+record
+recycle
+reflex
+reform
+regard
+region
+regular
+relax
+remark
+remote
+rent
+repair
+reply
+report
+reptile
+reserve
+respect
+respond
+result
+resume
+retro
+reunion
+reverse
+reward
+rhino
+ribbon
+ricardo
+richard
+rider
+right
+ringo
+rio
+risk
+ritual
+rival
+river
+riviera
+road
+robert
+robin
+robot
+rocket
+rodent
+rodeo
+roger
+roman
+romeo
+rondo
+roof
+rose
+round
+rover
+royal
+rubber
+ruby
+rudolf
+rufus
+russian
+sabine
+sabrina
+saddle
+safari
+saga
+sahara
+sailor
+saint
+salad
+salami
+salary
+salmon
+salon
+salsa
+salt
+salute
+samba
+sample
+samuel
+sandra
+santana
+sardine
+satire
+saturn
+savage
+scale
+scarlet
+scholar
+school
+scoop
+scorpio
+scratch
+screen
+script
+scroll
+scuba
+season
+second
+secret
+section
+sector
+secure
+segment
+select
+seminar
+senator
+senior
+sensor
+serial
+serpent
+service
+shadow
+shake
+shallow
+shampoo
+shannon
+sharon
+sharp
+shave
+shelf
+shelter
+sheriff
+sherman
+shine
+ship
+shirt
+shock
+shoe
+short
+shrink
+side
+sierra
+sigma
+signal
+silence
+silicon
+silk
+silver
+similar
+simon
+simple
+sinatra
+sincere
+singer
+single
+siren
+sister
+size
+ski
+slalom
+slang
+sleep
+slogan
+slow
+small
+smart
+smile
+smoke
+snake
+snow
+social
+society
+soda
+sofia
+solar
+solid
+solo
+sonar
+sonata
+song
+sonic
+soprano
+sound
+source
+south
+soviet
+spain
+spark
+sparta
+special
+speech
+speed
+spell
+spend
+sphere
+spider
+spiral
+spirit
+split
+sponsor
+spoon
+sport
+spray
+spring
+square
+stadium
+stage
+stamp
+stand
+star
+state
+static
+station
+status
+stella
+stereo
+stick
+sting
+stock
+stone
+stop
+store
+storm
+story
+strange
+street
+stretch
+strong
+stuart
+student
+studio
+style
+subject
+subway
+sugar
+sulfur
+sultan
+summer
+sunday
+sunset
+super
+support
+survive
+susan
+sushi
+suzuki
+sweden
+sweet
+swim
+swing
+switch
+symbol
+system
+table
+taboo
+tactic
+tahiti
+talent
+tango
+tape
+target
+tarzan
+taxi
+teacher
+telecom
+telex
+temple
+tempo
+tennis
+texas
+textile
+theory
+thermos
+think
+thomas
+tibet
+ticket
+tictac
+tiger
+time
+tina
+titanic
+toast
+tobacco
+today
+toga
+tokyo
+tomato
+tommy
+tonight
+topic
+torch
+tornado
+toronto
+torpedo
+torso
+total
+totem
+touch
+tourist
+tower
+toyota
+tractor
+trade
+traffic
+transit
+trapeze
+travel
+tribal
+tribune
+trick
+trident
+trilogy
+trinity
+tripod
+triton
+trivial
+tropic
+truck
+trumpet
+trust
+tulip
+tuna
+tunnel
+turbo
+turtle
+twin
+twist
+type
+ultra
+uncle
+under
+unicorn
+uniform
+union
+unique
+unit
+update
+uranium
+urban
+urgent
+user
+vacuum
+valery
+valid
+value
+vampire
+vanilla
+vatican
+vega
+velvet
+vendor
+venice
+ventura
+venus
+verbal
+verona
+version
+vertigo
+veteran
+vibrate
+victor
+video
+vienna
+viking
+village
+vincent
+violet
+violin
+virgo
+virtual
+virus
+visa
+visible
+vision
+visitor
+vista
+visual
+vital
+vitamin
+viva
+vocal
+vodka
+voice
+volcano
+voltage
+volume
+voodoo
+vortex
+voyage
+waiter
+warning
+watch
+water
+wave
+weather
+wedding
+weekend
+welcome
+western
+wheel
+whiskey
+william
+window
+winter
+wisdom
+wizard
+wolf
+wonder
+world
+xray
+yankee
+year
+yellow
+yes
+yoga
+yogurt
+young
+yoyo
+zebra
+zero
+zigzag
+zipper
+zodiac
+zoom
+"""

+ 1691 - 0
wordlists/mnemonic.py

@@ -0,0 +1,1691 @@
+#!/usr/bin/env python
+#
+# Electrum - lightweight Bitcoin client
+# Copyright (C) 2011 thomasv@gitorious
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+
+# list of words from http://en.wiktionary.org/wiki/Wiktionary:Frequency_lists/Contemporary_poetry
+
+words = [
+"like",
+"just",
+"love",
+"know",
+"never",
+"want",
+"time",
+"out",
+"there",
+"make",
+"look",
+"eye",
+"down",
+"only",
+"think",
+"heart",
+"back",
+"then",
+"into",
+"about",
+"more",
+"away",
+"still",
+"them",
+"take",
+"thing",
+"even",
+"through",
+"long",
+"always",
+"world",
+"too",
+"friend",
+"tell",
+"try",
+"hand",
+"thought",
+"over",
+"here",
+"other",
+"need",
+"smile",
+"again",
+"much",
+"cry",
+"been",
+"night",
+"ever",
+"little",
+"said",
+"end",
+"some",
+"those",
+"around",
+"mind",
+"people",
+"girl",
+"leave",
+"dream",
+"left",
+"turn",
+"myself",
+"give",
+"nothing",
+"really",
+"off",
+"before",
+"something",
+"find",
+"walk",
+"wish",
+"good",
+"once",
+"place",
+"ask",
+"stop",
+"keep",
+"watch",
+"seem",
+"everything",
+"wait",
+"got",
+"yet",
+"made",
+"remember",
+"start",
+"alone",
+"run",
+"hope",
+"maybe",
+"believe",
+"body",
+"hate",
+"after",
+"close",
+"talk",
+"stand",
+"own",
+"each",
+"hurt",
+"help",
+"home",
+"god",
+"soul",
+"new",
+"many",
+"two",
+"inside",
+"should",
+"true",
+"first",
+"fear",
+"mean",
+"better",
+"play",
+"another",
+"gone",
+"change",
+"use",
+"wonder",
+"someone",
+"hair",
+"cold",
+"open",
+"best",
+"any",
+"behind",
+"happen",
+"water",
+"dark",
+"laugh",
+"stay",
+"forever",
+"name",
+"work",
+"show",
+"sky",
+"break",
+"came",
+"deep",
+"door",
+"put",
+"black",
+"together",
+"upon",
+"happy",
+"such",
+"great",
+"white",
+"matter",
+"fill",
+"past",
+"please",
+"burn",
+"cause",
+"enough",
+"touch",
+"moment",
+"soon",
+"voice",
+"scream",
+"anything",
+"stare",
+"sound",
+"red",
+"everyone",
+"hide",
+"kiss",
+"truth",
+"death",
+"beautiful",
+"mine",
+"blood",
+"broken",
+"very",
+"pass",
+"next",
+"forget",
+"tree",
+"wrong",
+"air",
+"mother",
+"understand",
+"lip",
+"hit",
+"wall",
+"memory",
+"sleep",
+"free",
+"high",
+"realize",
+"school",
+"might",
+"skin",
+"sweet",
+"perfect",
+"blue",
+"kill",
+"breath",
+"dance",
+"against",
+"fly",
+"between",
+"grow",
+"strong",
+"under",
+"listen",
+"bring",
+"sometimes",
+"speak",
+"pull",
+"person",
+"become",
+"family",
+"begin",
+"ground",
+"real",
+"small",
+"father",
+"sure",
+"feet",
+"rest",
+"young",
+"finally",
+"land",
+"across",
+"today",
+"different",
+"guy",
+"line",
+"fire",
+"reason",
+"reach",
+"second",
+"slowly",
+"write",
+"eat",
+"smell",
+"mouth",
+"step",
+"learn",
+"three",
+"floor",
+"promise",
+"breathe",
+"darkness",
+"push",
+"earth",
+"guess",
+"save",
+"song",
+"above",
+"along",
+"both",
+"color",
+"house",
+"almost",
+"sorry",
+"anymore",
+"brother",
+"okay",
+"dear",
+"game",
+"fade",
+"already",
+"apart",
+"warm",
+"beauty",
+"heard",
+"notice",
+"question",
+"shine",
+"began",
+"piece",
+"whole",
+"shadow",
+"secret",
+"street",
+"within",
+"finger",
+"point",
+"morning",
+"whisper",
+"child",
+"moon",
+"green",
+"story",
+"glass",
+"kid",
+"silence",
+"since",
+"soft",
+"yourself",
+"empty",
+"shall",
+"angel",
+"answer",
+"baby",
+"bright",
+"dad",
+"path",
+"worry",
+"hour",
+"drop",
+"follow",
+"power",
+"war",
+"half",
+"flow",
+"heaven",
+"act",
+"chance",
+"fact",
+"least",
+"tired",
+"children",
+"near",
+"quite",
+"afraid",
+"rise",
+"sea",
+"taste",
+"window",
+"cover",
+"nice",
+"trust",
+"lot",
+"sad",
+"cool",
+"force",
+"peace",
+"return",
+"blind",
+"easy",
+"ready",
+"roll",
+"rose",
+"drive",
+"held",
+"music",
+"beneath",
+"hang",
+"mom",
+"paint",
+"emotion",
+"quiet",
+"clear",
+"cloud",
+"few",
+"pretty",
+"bird",
+"outside",
+"paper",
+"picture",
+"front",
+"rock",
+"simple",
+"anyone",
+"meant",
+"reality",
+"road",
+"sense",
+"waste",
+"bit",
+"leaf",
+"thank",
+"happiness",
+"meet",
+"men",
+"smoke",
+"truly",
+"decide",
+"self",
+"age",
+"book",
+"form",
+"alive",
+"carry",
+"escape",
+"damn",
+"instead",
+"able",
+"ice",
+"minute",
+"throw",
+"catch",
+"leg",
+"ring",
+"course",
+"goodbye",
+"lead",
+"poem",
+"sick",
+"corner",
+"desire",
+"known",
+"problem",
+"remind",
+"shoulder",
+"suppose",
+"toward",
+"wave",
+"drink",
+"jump",
+"woman",
+"pretend",
+"sister",
+"week",
+"human",
+"joy",
+"crack",
+"grey",
+"pray",
+"surprise",
+"dry",
+"knee",
+"less",
+"search",
+"bleed",
+"caught",
+"clean",
+"embrace",
+"future",
+"king",
+"son",
+"sorrow",
+"chest",
+"hug",
+"remain",
+"sat",
+"worth",
+"blow",
+"daddy",
+"final",
+"parent",
+"tight",
+"also",
+"create",
+"lonely",
+"safe",
+"cross",
+"dress",
+"evil",
+"silent",
+"bone",
+"fate",
+"perhaps",
+"anger",
+"class",
+"scar",
+"snow",
+"tiny",
+"tonight",
+"continue",
+"control",
+"dog",
+"edge",
+"mirror",
+"month",
+"suddenly",
+"comfort",
+"given",
+"loud",
+"quickly",
+"gaze",
+"plan",
+"rush",
+"stone",
+"town",
+"battle",
+"ignore",
+"spirit",
+"stood",
+"stupid",
+"yours",
+"brown",
+"build",
+"dust",
+"hey",
+"kept",
+"pay",
+"phone",
+"twist",
+"although",
+"ball",
+"beyond",
+"hidden",
+"nose",
+"taken",
+"fail",
+"float",
+"pure",
+"somehow",
+"wash",
+"wrap",
+"angry",
+"cheek",
+"creature",
+"forgotten",
+"heat",
+"rip",
+"single",
+"space",
+"special",
+"weak",
+"whatever",
+"yell",
+"anyway",
+"blame",
+"job",
+"choose",
+"country",
+"curse",
+"drift",
+"echo",
+"figure",
+"grew",
+"laughter",
+"neck",
+"suffer",
+"worse",
+"yeah",
+"disappear",
+"foot",
+"forward",
+"knife",
+"mess",
+"somewhere",
+"stomach",
+"storm",
+"beg",
+"idea",
+"lift",
+"offer",
+"breeze",
+"field",
+"five",
+"often",
+"simply",
+"stuck",
+"win",
+"allow",
+"confuse",
+"enjoy",
+"except",
+"flower",
+"seek",
+"strength",
+"calm",
+"grin",
+"gun",
+"heavy",
+"hill",
+"large",
+"ocean",
+"shoe",
+"sigh",
+"straight",
+"summer",
+"tongue",
+"accept",
+"crazy",
+"everyday",
+"exist",
+"grass",
+"mistake",
+"sent",
+"shut",
+"surround",
+"table",
+"ache",
+"brain",
+"destroy",
+"heal",
+"nature",
+"shout",
+"sign",
+"stain",
+"choice",
+"doubt",
+"glance",
+"glow",
+"mountain",
+"queen",
+"stranger",
+"throat",
+"tomorrow",
+"city",
+"either",
+"fish",
+"flame",
+"rather",
+"shape",
+"spin",
+"spread",
+"ash",
+"distance",
+"finish",
+"image",
+"imagine",
+"important",
+"nobody",
+"shatter",
+"warmth",
+"became",
+"feed",
+"flesh",
+"funny",
+"lust",
+"shirt",
+"trouble",
+"yellow",
+"attention",
+"bare",
+"bite",
+"money",
+"protect",
+"amaze",
+"appear",
+"born",
+"choke",
+"completely",
+"daughter",
+"fresh",
+"friendship",
+"gentle",
+"probably",
+"six",
+"deserve",
+"expect",
+"grab",
+"middle",
+"nightmare",
+"river",
+"thousand",
+"weight",
+"worst",
+"wound",
+"barely",
+"bottle",
+"cream",
+"regret",
+"relationship",
+"stick",
+"test",
+"crush",
+"endless",
+"fault",
+"itself",
+"rule",
+"spill",
+"art",
+"circle",
+"join",
+"kick",
+"mask",
+"master",
+"passion",
+"quick",
+"raise",
+"smooth",
+"unless",
+"wander",
+"actually",
+"broke",
+"chair",
+"deal",
+"favorite",
+"gift",
+"note",
+"number",
+"sweat",
+"box",
+"chill",
+"clothes",
+"lady",
+"mark",
+"park",
+"poor",
+"sadness",
+"tie",
+"animal",
+"belong",
+"brush",
+"consume",
+"dawn",
+"forest",
+"innocent",
+"pen",
+"pride",
+"stream",
+"thick",
+"clay",
+"complete",
+"count",
+"draw",
+"faith",
+"press",
+"silver",
+"struggle",
+"surface",
+"taught",
+"teach",
+"wet",
+"bless",
+"chase",
+"climb",
+"enter",
+"letter",
+"melt",
+"metal",
+"movie",
+"stretch",
+"swing",
+"vision",
+"wife",
+"beside",
+"crash",
+"forgot",
+"guide",
+"haunt",
+"joke",
+"knock",
+"plant",
+"pour",
+"prove",
+"reveal",
+"steal",
+"stuff",
+"trip",
+"wood",
+"wrist",
+"bother",
+"bottom",
+"crawl",
+"crowd",
+"fix",
+"forgive",
+"frown",
+"grace",
+"loose",
+"lucky",
+"party",
+"release",
+"surely",
+"survive",
+"teacher",
+"gently",
+"grip",
+"speed",
+"suicide",
+"travel",
+"treat",
+"vein",
+"written",
+"cage",
+"chain",
+"conversation",
+"date",
+"enemy",
+"however",
+"interest",
+"million",
+"page",
+"pink",
+"proud",
+"sway",
+"themselves",
+"winter",
+"church",
+"cruel",
+"cup",
+"demon",
+"experience",
+"freedom",
+"pair",
+"pop",
+"purpose",
+"respect",
+"shoot",
+"softly",
+"state",
+"strange",
+"bar",
+"birth",
+"curl",
+"dirt",
+"excuse",
+"lord",
+"lovely",
+"monster",
+"order",
+"pack",
+"pants",
+"pool",
+"scene",
+"seven",
+"shame",
+"slide",
+"ugly",
+"among",
+"blade",
+"blonde",
+"closet",
+"creek",
+"deny",
+"drug",
+"eternity",
+"gain",
+"grade",
+"handle",
+"key",
+"linger",
+"pale",
+"prepare",
+"swallow",
+"swim",
+"tremble",
+"wheel",
+"won",
+"cast",
+"cigarette",
+"claim",
+"college",
+"direction",
+"dirty",
+"gather",
+"ghost",
+"hundred",
+"loss",
+"lung",
+"orange",
+"present",
+"swear",
+"swirl",
+"twice",
+"wild",
+"bitter",
+"blanket",
+"doctor",
+"everywhere",
+"flash",
+"grown",
+"knowledge",
+"numb",
+"pressure",
+"radio",
+"repeat",
+"ruin",
+"spend",
+"unknown",
+"buy",
+"clock",
+"devil",
+"early",
+"false",
+"fantasy",
+"pound",
+"precious",
+"refuse",
+"sheet",
+"teeth",
+"welcome",
+"add",
+"ahead",
+"block",
+"bury",
+"caress",
+"content",
+"depth",
+"despite",
+"distant",
+"marry",
+"purple",
+"threw",
+"whenever",
+"bomb",
+"dull",
+"easily",
+"grasp",
+"hospital",
+"innocence",
+"normal",
+"receive",
+"reply",
+"rhyme",
+"shade",
+"someday",
+"sword",
+"toe",
+"visit",
+"asleep",
+"bought",
+"center",
+"consider",
+"flat",
+"hero",
+"history",
+"ink",
+"insane",
+"muscle",
+"mystery",
+"pocket",
+"reflection",
+"shove",
+"silently",
+"smart",
+"soldier",
+"spot",
+"stress",
+"train",
+"type",
+"view",
+"whether",
+"bus",
+"energy",
+"explain",
+"holy",
+"hunger",
+"inch",
+"magic",
+"mix",
+"noise",
+"nowhere",
+"prayer",
+"presence",
+"shock",
+"snap",
+"spider",
+"study",
+"thunder",
+"trail",
+"admit",
+"agree",
+"bag",
+"bang",
+"bound",
+"butterfly",
+"cute",
+"exactly",
+"explode",
+"familiar",
+"fold",
+"further",
+"pierce",
+"reflect",
+"scent",
+"selfish",
+"sharp",
+"sink",
+"spring",
+"stumble",
+"universe",
+"weep",
+"women",
+"wonderful",
+"action",
+"ancient",
+"attempt",
+"avoid",
+"birthday",
+"branch",
+"chocolate",
+"core",
+"depress",
+"drunk",
+"especially",
+"focus",
+"fruit",
+"honest",
+"match",
+"palm",
+"perfectly",
+"pillow",
+"pity",
+"poison",
+"roar",
+"shift",
+"slightly",
+"thump",
+"truck",
+"tune",
+"twenty",
+"unable",
+"wipe",
+"wrote",
+"coat",
+"constant",
+"dinner",
+"drove",
+"egg",
+"eternal",
+"flight",
+"flood",
+"frame",
+"freak",
+"gasp",
+"glad",
+"hollow",
+"motion",
+"peer",
+"plastic",
+"root",
+"screen",
+"season",
+"sting",
+"strike",
+"team",
+"unlike",
+"victim",
+"volume",
+"warn",
+"weird",
+"attack",
+"await",
+"awake",
+"built",
+"charm",
+"crave",
+"despair",
+"fought",
+"grant",
+"grief",
+"horse",
+"limit",
+"message",
+"ripple",
+"sanity",
+"scatter",
+"serve",
+"split",
+"string",
+"trick",
+"annoy",
+"blur",
+"boat",
+"brave",
+"clearly",
+"cling",
+"connect",
+"fist",
+"forth",
+"imagination",
+"iron",
+"jock",
+"judge",
+"lesson",
+"milk",
+"misery",
+"nail",
+"naked",
+"ourselves",
+"poet",
+"possible",
+"princess",
+"sail",
+"size",
+"snake",
+"society",
+"stroke",
+"torture",
+"toss",
+"trace",
+"wise",
+"bloom",
+"bullet",
+"cell",
+"check",
+"cost",
+"darling",
+"during",
+"footstep",
+"fragile",
+"hallway",
+"hardly",
+"horizon",
+"invisible",
+"journey",
+"midnight",
+"mud",
+"nod",
+"pause",
+"relax",
+"shiver",
+"sudden",
+"value",
+"youth",
+"abuse",
+"admire",
+"blink",
+"breast",
+"bruise",
+"constantly",
+"couple",
+"creep",
+"curve",
+"difference",
+"dumb",
+"emptiness",
+"gotta",
+"honor",
+"plain",
+"planet",
+"recall",
+"rub",
+"ship",
+"slam",
+"soar",
+"somebody",
+"tightly",
+"weather",
+"adore",
+"approach",
+"bond",
+"bread",
+"burst",
+"candle",
+"coffee",
+"cousin",
+"crime",
+"desert",
+"flutter",
+"frozen",
+"grand",
+"heel",
+"hello",
+"language",
+"level",
+"movement",
+"pleasure",
+"powerful",
+"random",
+"rhythm",
+"settle",
+"silly",
+"slap",
+"sort",
+"spoken",
+"steel",
+"threaten",
+"tumble",
+"upset",
+"aside",
+"awkward",
+"bee",
+"blank",
+"board",
+"button",
+"card",
+"carefully",
+"complain",
+"crap",
+"deeply",
+"discover",
+"drag",
+"dread",
+"effort",
+"entire",
+"fairy",
+"giant",
+"gotten",
+"greet",
+"illusion",
+"jeans",
+"leap",
+"liquid",
+"march",
+"mend",
+"nervous",
+"nine",
+"replace",
+"rope",
+"spine",
+"stole",
+"terror",
+"accident",
+"apple",
+"balance",
+"boom",
+"childhood",
+"collect",
+"demand",
+"depression",
+"eventually",
+"faint",
+"glare",
+"goal",
+"group",
+"honey",
+"kitchen",
+"laid",
+"limb",
+"machine",
+"mere",
+"mold",
+"murder",
+"nerve",
+"painful",
+"poetry",
+"prince",
+"rabbit",
+"shelter",
+"shore",
+"shower",
+"soothe",
+"stair",
+"steady",
+"sunlight",
+"tangle",
+"tease",
+"treasure",
+"uncle",
+"begun",
+"bliss",
+"canvas",
+"cheer",
+"claw",
+"clutch",
+"commit",
+"crimson",
+"crystal",
+"delight",
+"doll",
+"existence",
+"express",
+"fog",
+"football",
+"gay",
+"goose",
+"guard",
+"hatred",
+"illuminate",
+"mass",
+"math",
+"mourn",
+"rich",
+"rough",
+"skip",
+"stir",
+"student",
+"style",
+"support",
+"thorn",
+"tough",
+"yard",
+"yearn",
+"yesterday",
+"advice",
+"appreciate",
+"autumn",
+"bank",
+"beam",
+"bowl",
+"capture",
+"carve",
+"collapse",
+"confusion",
+"creation",
+"dove",
+"feather",
+"girlfriend",
+"glory",
+"government",
+"harsh",
+"hop",
+"inner",
+"loser",
+"moonlight",
+"neighbor",
+"neither",
+"peach",
+"pig",
+"praise",
+"screw",
+"shield",
+"shimmer",
+"sneak",
+"stab",
+"subject",
+"throughout",
+"thrown",
+"tower",
+"twirl",
+"wow",
+"army",
+"arrive",
+"bathroom",
+"bump",
+"cease",
+"cookie",
+"couch",
+"courage",
+"dim",
+"guilt",
+"howl",
+"hum",
+"husband",
+"insult",
+"led",
+"lunch",
+"mock",
+"mostly",
+"natural",
+"nearly",
+"needle",
+"nerd",
+"peaceful",
+"perfection",
+"pile",
+"price",
+"remove",
+"roam",
+"sanctuary",
+"serious",
+"shiny",
+"shook",
+"sob",
+"stolen",
+"tap",
+"vain",
+"void",
+"warrior",
+"wrinkle",
+"affection",
+"apologize",
+"blossom",
+"bounce",
+"bridge",
+"cheap",
+"crumble",
+"decision",
+"descend",
+"desperately",
+"dig",
+"dot",
+"flip",
+"frighten",
+"heartbeat",
+"huge",
+"lazy",
+"lick",
+"odd",
+"opinion",
+"process",
+"puzzle",
+"quietly",
+"retreat",
+"score",
+"sentence",
+"separate",
+"situation",
+"skill",
+"soak",
+"square",
+"stray",
+"taint",
+"task",
+"tide",
+"underneath",
+"veil",
+"whistle",
+"anywhere",
+"bedroom",
+"bid",
+"bloody",
+"burden",
+"careful",
+"compare",
+"concern",
+"curtain",
+"decay",
+"defeat",
+"describe",
+"double",
+"dreamer",
+"driver",
+"dwell",
+"evening",
+"flare",
+"flicker",
+"grandma",
+"guitar",
+"harm",
+"horrible",
+"hungry",
+"indeed",
+"lace",
+"melody",
+"monkey",
+"nation",
+"object",
+"obviously",
+"rainbow",
+"salt",
+"scratch",
+"shown",
+"shy",
+"stage",
+"stun",
+"third",
+"tickle",
+"useless",
+"weakness",
+"worship",
+"worthless",
+"afternoon",
+"beard",
+"boyfriend",
+"bubble",
+"busy",
+"certain",
+"chin",
+"concrete",
+"desk",
+"diamond",
+"doom",
+"drawn",
+"due",
+"felicity",
+"freeze",
+"frost",
+"garden",
+"glide",
+"harmony",
+"hopefully",
+"hunt",
+"jealous",
+"lightning",
+"mama",
+"mercy",
+"peel",
+"physical",
+"position",
+"pulse",
+"punch",
+"quit",
+"rant",
+"respond",
+"salty",
+"sane",
+"satisfy",
+"savior",
+"sheep",
+"slept",
+"social",
+"sport",
+"tuck",
+"utter",
+"valley",
+"wolf",
+"aim",
+"alas",
+"alter",
+"arrow",
+"awaken",
+"beaten",
+"belief",
+"brand",
+"ceiling",
+"cheese",
+"clue",
+"confidence",
+"connection",
+"daily",
+"disguise",
+"eager",
+"erase",
+"essence",
+"everytime",
+"expression",
+"fan",
+"flag",
+"flirt",
+"foul",
+"fur",
+"giggle",
+"glorious",
+"ignorance",
+"law",
+"lifeless",
+"measure",
+"mighty",
+"muse",
+"north",
+"opposite",
+"paradise",
+"patience",
+"patient",
+"pencil",
+"petal",
+"plate",
+"ponder",
+"possibly",
+"practice",
+"slice",
+"spell",
+"stock",
+"strife",
+"strip",
+"suffocate",
+"suit",
+"tender",
+"tool",
+"trade",
+"velvet",
+"verse",
+"waist",
+"witch",
+"aunt",
+"bench",
+"bold",
+"cap",
+"certainly",
+"click",
+"companion",
+"creator",
+"dart",
+"delicate",
+"determine",
+"dish",
+"dragon",
+"drama",
+"drum",
+"dude",
+"everybody",
+"feast",
+"forehead",
+"former",
+"fright",
+"fully",
+"gas",
+"hook",
+"hurl",
+"invite",
+"juice",
+"manage",
+"moral",
+"possess",
+"raw",
+"rebel",
+"royal",
+"scale",
+"scary",
+"several",
+"slight",
+"stubborn",
+"swell",
+"talent",
+"tea",
+"terrible",
+"thread",
+"torment",
+"trickle",
+"usually",
+"vast",
+"violence",
+"weave",
+"acid",
+"agony",
+"ashamed",
+"awe",
+"belly",
+"blend",
+"blush",
+"character",
+"cheat",
+"common",
+"company",
+"coward",
+"creak",
+"danger",
+"deadly",
+"defense",
+"define",
+"depend",
+"desperate",
+"destination",
+"dew",
+"duck",
+"dusty",
+"embarrass",
+"engine",
+"example",
+"explore",
+"foe",
+"freely",
+"frustrate",
+"generation",
+"glove",
+"guilty",
+"health",
+"hurry",
+"idiot",
+"impossible",
+"inhale",
+"jaw",
+"kingdom",
+"mention",
+"mist",
+"moan",
+"mumble",
+"mutter",
+"observe",
+"ode",
+"pathetic",
+"pattern",
+"pie",
+"prefer",
+"puff",
+"rape",
+"rare",
+"revenge",
+"rude",
+"scrape",
+"spiral",
+"squeeze",
+"strain",
+"sunset",
+"suspend",
+"sympathy",
+"thigh",
+"throne",
+"total",
+"unseen",
+"weapon",
+"weary"
+]
+
+
+
+n = 1626
+
+# Note about US patent no 5892470: Here each word does not represent a given digit.
+# Instead, the digit represented by a word is variable, it depends on the previous word.
+
+def mn_encode( message ):
+    out = []
+    for i in range(len(message)/8):
+        word = message[8*i:8*i+8]
+        x = int(word, 16)
+        w1 = (x%n)
+        w2 = ((x/n) + w1)%n
+        w3 = ((x/n/n) + w2)%n
+        out += [ words[w1], words[w2], words[w3] ]
+    return out
+
+def mn_decode( wlist ):
+    out = ''
+    for i in range(len(wlist)/3):
+        word1, word2, word3 = wlist[3*i:3*i+3]
+        w1 =  words.index(word1)
+        w2 = (words.index(word2))%n
+        w3 = (words.index(word3))%n
+        x = w1 +n*((w2-w1)%n) +n*n*((w3-w2)%n)
+        out += '%08x'%x
+    return out
+
+if __name__ == '__main__':
+	print "\n".join(words)
+
+# if __name__ == '__main__':
+#     import sys
+#     if len( sys.argv ) == 1:
+#         print 'I need arguments: a hex string to encode, or a list of words to decode'
+#     elif len( sys.argv ) == 2:
+#         print ' '.join(mn_encode(sys.argv[1]))
+#     else:
+#         print mn_decode(sys.argv[1:])

+ 1638 - 0
wordlists/mnemonic.sort.py

@@ -0,0 +1,1638 @@
+#!/usr/bin/python
+
+# electrum wordlist
+# Electrum - lightweight Bitcoin client
+# Copyright (C) 2011 thomasv@gitorious
+# list of words from:
+# http://en.wiktionary.org/wiki/Wiktionary:Frequency_lists/Contemporary_poetry
+
+# This is a sorted version of the wordlist
+
+electrum_wordlist = """
+able
+about
+above
+abuse
+accept
+accident
+ache
+acid
+across
+act
+action
+actually
+add
+admire
+admit
+adore
+advice
+affection
+afraid
+after
+afternoon
+again
+against
+age
+agony
+agree
+ahead
+aim
+air
+alas
+alive
+allow
+almost
+alone
+along
+already
+also
+alter
+although
+always
+amaze
+among
+ancient
+angel
+anger
+angry
+animal
+annoy
+another
+answer
+any
+anymore
+anyone
+anything
+anyway
+anywhere
+apart
+apologize
+appear
+apple
+appreciate
+approach
+army
+around
+arrive
+arrow
+art
+ash
+ashamed
+aside
+ask
+asleep
+attack
+attempt
+attention
+aunt
+autumn
+avoid
+await
+awake
+awaken
+away
+awe
+awkward
+baby
+back
+bag
+balance
+ball
+bang
+bank
+bar
+bare
+barely
+bathroom
+battle
+beam
+beard
+beaten
+beautiful
+beauty
+became
+become
+bedroom
+bee
+been
+before
+beg
+began
+begin
+begun
+behind
+belief
+believe
+belly
+belong
+bench
+beneath
+beside
+best
+better
+between
+beyond
+bid
+bird
+birth
+birthday
+bit
+bite
+bitter
+black
+blade
+blame
+blank
+blanket
+bleed
+blend
+bless
+blind
+blink
+bliss
+block
+blonde
+blood
+bloody
+bloom
+blossom
+blow
+blue
+blur
+blush
+board
+boat
+body
+bold
+bomb
+bond
+bone
+book
+boom
+born
+both
+bother
+bottle
+bottom
+bought
+bounce
+bound
+bowl
+box
+boyfriend
+brain
+branch
+brand
+brave
+bread
+break
+breast
+breath
+breathe
+breeze
+bridge
+bright
+bring
+broke
+broken
+brother
+brown
+bruise
+brush
+bubble
+build
+built
+bullet
+bump
+burden
+burn
+burst
+bury
+bus
+busy
+butterfly
+button
+buy
+cage
+calm
+came
+candle
+canvas
+cap
+capture
+card
+careful
+carefully
+caress
+carry
+carve
+cast
+catch
+caught
+cause
+cease
+ceiling
+cell
+center
+certain
+certainly
+chain
+chair
+chance
+change
+character
+charm
+chase
+cheap
+cheat
+check
+cheek
+cheer
+cheese
+chest
+child
+childhood
+children
+chill
+chin
+chocolate
+choice
+choke
+choose
+church
+cigarette
+circle
+city
+claim
+class
+claw
+clay
+clean
+clear
+clearly
+click
+climb
+cling
+clock
+close
+closet
+clothes
+cloud
+clue
+clutch
+coat
+coffee
+cold
+collapse
+collect
+college
+color
+comfort
+commit
+common
+companion
+company
+compare
+complain
+complete
+completely
+concern
+concrete
+confidence
+confuse
+confusion
+connect
+connection
+consider
+constant
+constantly
+consume
+content
+continue
+control
+conversation
+cookie
+cool
+core
+corner
+cost
+couch
+count
+country
+couple
+courage
+course
+cousin
+cover
+coward
+crack
+crap
+crash
+crave
+crawl
+crazy
+creak
+cream
+create
+creation
+creator
+creature
+creek
+creep
+crime
+crimson
+cross
+crowd
+cruel
+crumble
+crush
+cry
+crystal
+cup
+curl
+curse
+curtain
+curve
+cute
+dad
+daddy
+daily
+damn
+dance
+danger
+dark
+darkness
+darling
+dart
+date
+daughter
+dawn
+deadly
+deal
+dear
+death
+decay
+decide
+decision
+deep
+deeply
+defeat
+defense
+define
+delicate
+delight
+demand
+demon
+deny
+depend
+depress
+depression
+depth
+descend
+describe
+desert
+deserve
+desire
+desk
+despair
+desperate
+desperately
+despite
+destination
+destroy
+determine
+devil
+dew
+diamond
+difference
+different
+dig
+dim
+dinner
+direction
+dirt
+dirty
+disappear
+discover
+disguise
+dish
+distance
+distant
+doctor
+dog
+doll
+doom
+door
+dot
+double
+doubt
+dove
+down
+drag
+dragon
+drama
+draw
+drawn
+dread
+dream
+dreamer
+dress
+drift
+drink
+drive
+driver
+drop
+drove
+drug
+drum
+drunk
+dry
+duck
+dude
+due
+dull
+dumb
+during
+dust
+dusty
+dwell
+each
+eager
+early
+earth
+easily
+easy
+eat
+echo
+edge
+effort
+egg
+either
+embarrass
+embrace
+emotion
+emptiness
+empty
+end
+endless
+enemy
+energy
+engine
+enjoy
+enough
+enter
+entire
+erase
+escape
+especially
+essence
+eternal
+eternity
+even
+evening
+eventually
+ever
+everybody
+everyday
+everyone
+everything
+everytime
+everywhere
+evil
+exactly
+example
+except
+excuse
+exist
+existence
+expect
+experience
+explain
+explode
+explore
+express
+expression
+eye
+fact
+fade
+fail
+faint
+fairy
+faith
+false
+familiar
+family
+fan
+fantasy
+fate
+father
+fault
+favorite
+fear
+feast
+feather
+feed
+feet
+felicity
+few
+field
+figure
+fill
+final
+finally
+find
+finger
+finish
+fire
+first
+fish
+fist
+five
+fix
+flag
+flame
+flare
+flash
+flat
+flesh
+flicker
+flight
+flip
+flirt
+float
+flood
+floor
+flow
+flower
+flutter
+fly
+focus
+foe
+fog
+fold
+follow
+foot
+football
+footstep
+force
+forehead
+forest
+forever
+forget
+forgive
+forgot
+forgotten
+form
+former
+forth
+forward
+fought
+foul
+fragile
+frame
+freak
+free
+freedom
+freely
+freeze
+fresh
+friend
+friendship
+fright
+frighten
+front
+frost
+frown
+frozen
+fruit
+frustrate
+fully
+funny
+fur
+further
+future
+gain
+game
+garden
+gas
+gasp
+gather
+gay
+gaze
+generation
+gentle
+gently
+ghost
+giant
+gift
+giggle
+girl
+girlfriend
+give
+given
+glad
+glance
+glare
+glass
+glide
+glorious
+glory
+glove
+glow
+goal
+god
+gone
+good
+goodbye
+goose
+got
+gotta
+gotten
+government
+grab
+grace
+grade
+grand
+grandma
+grant
+grasp
+grass
+great
+green
+greet
+grew
+grey
+grief
+grin
+grip
+ground
+group
+grow
+grown
+guard
+guess
+guide
+guilt
+guilty
+guitar
+gun
+guy
+hair
+half
+hallway
+hand
+handle
+hang
+happen
+happiness
+happy
+hardly
+harm
+harmony
+harsh
+hate
+hatred
+haunt
+heal
+health
+heard
+heart
+heartbeat
+heat
+heaven
+heavy
+heel
+held
+hello
+help
+here
+hero
+hey
+hidden
+hide
+high
+hill
+history
+hit
+hollow
+holy
+home
+honest
+honey
+honor
+hook
+hop
+hope
+hopefully
+horizon
+horrible
+horse
+hospital
+hour
+house
+however
+howl
+hug
+huge
+hum
+human
+hundred
+hunger
+hungry
+hunt
+hurl
+hurry
+hurt
+husband
+ice
+idea
+idiot
+ignorance
+ignore
+illuminate
+illusion
+image
+imagination
+imagine
+important
+impossible
+inch
+indeed
+inhale
+ink
+inner
+innocence
+innocent
+insane
+inside
+instead
+insult
+interest
+into
+invisible
+invite
+iron
+itself
+jaw
+jealous
+jeans
+job
+jock
+join
+joke
+journey
+joy
+judge
+juice
+jump
+just
+keep
+kept
+key
+kick
+kid
+kill
+king
+kingdom
+kiss
+kitchen
+knee
+knife
+knock
+know
+knowledge
+known
+lace
+lady
+laid
+land
+language
+large
+laugh
+laughter
+law
+lazy
+lead
+leaf
+leap
+learn
+least
+leave
+led
+left
+leg
+less
+lesson
+letter
+level
+lick
+lifeless
+lift
+lightning
+like
+limb
+limit
+line
+linger
+lip
+liquid
+listen
+little
+lonely
+long
+look
+loose
+lord
+loser
+loss
+lot
+loud
+love
+lovely
+lucky
+lunch
+lung
+lust
+machine
+made
+magic
+make
+mama
+manage
+many
+march
+mark
+marry
+mask
+mass
+master
+match
+math
+matter
+maybe
+mean
+meant
+measure
+meet
+melody
+melt
+memory
+men
+mend
+mention
+mercy
+mere
+mess
+message
+metal
+middle
+midnight
+might
+mighty
+milk
+million
+mind
+mine
+minute
+mirror
+misery
+mist
+mistake
+mix
+moan
+mock
+mold
+mom
+moment
+money
+monkey
+monster
+month
+moon
+moonlight
+moral
+more
+morning
+mostly
+mother
+motion
+mountain
+mourn
+mouth
+movement
+movie
+much
+mud
+mumble
+murder
+muscle
+muse
+music
+mutter
+myself
+mystery
+nail
+naked
+name
+nation
+natural
+nature
+near
+nearly
+neck
+need
+needle
+neighbor
+neither
+nerd
+nerve
+nervous
+never
+new
+next
+nice
+night
+nightmare
+nine
+nobody
+nod
+noise
+normal
+north
+nose
+note
+nothing
+notice
+nowhere
+numb
+number
+object
+observe
+obviously
+ocean
+odd
+ode
+off
+offer
+often
+okay
+once
+only
+open
+opinion
+opposite
+orange
+order
+other
+ourselves
+out
+outside
+over
+own
+pack
+page
+painful
+paint
+pair
+pale
+palm
+pants
+paper
+paradise
+parent
+park
+party
+pass
+passion
+past
+path
+pathetic
+patience
+patient
+pattern
+pause
+pay
+peace
+peaceful
+peach
+peel
+peer
+pen
+pencil
+people
+perfect
+perfection
+perfectly
+perhaps
+person
+petal
+phone
+physical
+picture
+pie
+piece
+pierce
+pig
+pile
+pillow
+pink
+pity
+place
+plain
+plan
+planet
+plant
+plastic
+plate
+play
+please
+pleasure
+pocket
+poem
+poet
+poetry
+point
+poison
+ponder
+pool
+poor
+pop
+position
+possess
+possible
+possibly
+pound
+pour
+power
+powerful
+practice
+praise
+pray
+prayer
+precious
+prefer
+prepare
+presence
+present
+press
+pressure
+pretend
+pretty
+price
+pride
+prince
+princess
+probably
+problem
+process
+promise
+protect
+proud
+prove
+puff
+pull
+pulse
+punch
+pure
+purple
+purpose
+push
+put
+puzzle
+queen
+question
+quick
+quickly
+quiet
+quietly
+quit
+quite
+rabbit
+radio
+rainbow
+raise
+random
+rant
+rape
+rare
+rather
+raw
+reach
+ready
+real
+reality
+realize
+really
+reason
+rebel
+recall
+receive
+red
+reflect
+reflection
+refuse
+regret
+relationship
+relax
+release
+remain
+remember
+remind
+remove
+repeat
+replace
+reply
+respect
+respond
+rest
+retreat
+return
+reveal
+revenge
+rhyme
+rhythm
+rich
+ring
+rip
+ripple
+rise
+river
+road
+roam
+roar
+rock
+roll
+root
+rope
+rose
+rough
+royal
+rub
+rude
+ruin
+rule
+run
+rush
+sad
+sadness
+safe
+said
+sail
+salt
+salty
+sanctuary
+sane
+sanity
+sat
+satisfy
+save
+savior
+scale
+scar
+scary
+scatter
+scene
+scent
+school
+score
+scrape
+scratch
+scream
+screen
+screw
+sea
+search
+season
+second
+secret
+seek
+seem
+self
+selfish
+sense
+sent
+sentence
+separate
+serious
+serve
+settle
+seven
+several
+shade
+shadow
+shall
+shame
+shape
+sharp
+shatter
+sheep
+sheet
+shelter
+shield
+shift
+shimmer
+shine
+shiny
+ship
+shirt
+shiver
+shock
+shoe
+shook
+shoot
+shore
+should
+shoulder
+shout
+shove
+show
+shower
+shown
+shut
+shy
+sick
+sigh
+sign
+silence
+silent
+silently
+silly
+silver
+simple
+simply
+since
+single
+sink
+sister
+situation
+six
+size
+skill
+skin
+skip
+sky
+slam
+slap
+sleep
+slept
+slice
+slide
+slight
+slightly
+slowly
+small
+smart
+smell
+smile
+smoke
+smooth
+snake
+snap
+sneak
+snow
+soak
+soar
+sob
+social
+society
+soft
+softly
+soldier
+some
+somebody
+someday
+somehow
+someone
+something
+sometimes
+somewhere
+son
+song
+soon
+soothe
+sorrow
+sorry
+sort
+soul
+sound
+space
+speak
+special
+speed
+spell
+spend
+spider
+spill
+spin
+spine
+spiral
+spirit
+split
+spoken
+sport
+spot
+spread
+spring
+square
+squeeze
+stab
+stage
+stain
+stair
+stand
+stare
+start
+state
+stay
+steady
+steal
+steel
+step
+stick
+still
+sting
+stir
+stock
+stole
+stolen
+stomach
+stone
+stood
+stop
+storm
+story
+straight
+strain
+strange
+stranger
+stray
+stream
+street
+strength
+stress
+stretch
+strife
+strike
+string
+strip
+stroke
+strong
+struggle
+stubborn
+stuck
+student
+study
+stuff
+stumble
+stun
+stupid
+style
+subject
+such
+sudden
+suddenly
+suffer
+suffocate
+suicide
+suit
+summer
+sunlight
+sunset
+support
+suppose
+sure
+surely
+surface
+surprise
+surround
+survive
+suspend
+swallow
+sway
+swear
+sweat
+sweet
+swell
+swim
+swing
+swirl
+sword
+sympathy
+table
+taint
+take
+taken
+talent
+talk
+tangle
+tap
+task
+taste
+taught
+tea
+teach
+teacher
+team
+tease
+teeth
+tell
+tender
+terrible
+terror
+test
+thank
+them
+themselves
+then
+there
+thick
+thigh
+thing
+think
+third
+thorn
+those
+thought
+thousand
+thread
+threaten
+three
+threw
+throat
+throne
+through
+throughout
+throw
+thrown
+thump
+thunder
+tickle
+tide
+tie
+tight
+tightly
+time
+tiny
+tired
+today
+toe
+together
+tomorrow
+tongue
+tonight
+too
+tool
+torment
+torture
+toss
+total
+touch
+tough
+toward
+tower
+town
+trace
+trade
+trail
+train
+travel
+treasure
+treat
+tree
+tremble
+trick
+trickle
+trip
+trouble
+truck
+true
+truly
+trust
+truth
+try
+tuck
+tumble
+tune
+turn
+twenty
+twice
+twirl
+twist
+two
+type
+ugly
+unable
+uncle
+under
+underneath
+understand
+universe
+unknown
+unless
+unlike
+unseen
+upon
+upset
+use
+useless
+usually
+utter
+vain
+valley
+value
+vast
+veil
+vein
+velvet
+verse
+very
+victim
+view
+violence
+vision
+visit
+voice
+void
+volume
+waist
+wait
+walk
+wall
+wander
+want
+war
+warm
+warmth
+warn
+warrior
+wash
+waste
+watch
+water
+wave
+weak
+weakness
+weapon
+weary
+weather
+weave
+week
+weep
+weight
+weird
+welcome
+wet
+whatever
+wheel
+whenever
+whether
+whisper
+whistle
+white
+whole
+wife
+wild
+win
+window
+winter
+wipe
+wise
+wish
+witch
+within
+wolf
+woman
+women
+won
+wonder
+wonderful
+wood
+work
+world
+worry
+worse
+worship
+worst
+worth
+worthless
+wound
+wow
+wrap
+wrinkle
+wrist
+write
+written
+wrong
+wrote
+yard
+yeah
+yearn
+yell
+yellow
+yesterday
+yet
+young
+yours
+yourself
+youth
+"""