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
This commit is contained in:
commit
9f28397cfe
32 changed files with 12725 additions and 0 deletions
674
LICENSE
Normal file
674
LICENSE
Normal file
|
|
@ -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
MANIFEST
Normal file
18
MANIFEST
Normal file
|
|
@ -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
mmgen-addrgen
Symbolic link
1
mmgen-addrgen
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
mmgen-keygen
|
||||||
175
mmgen-keygen
Executable file
175
mmgen-keygen
Executable file
|
|
@ -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
mmgen-passchg
Executable file
121
mmgen-passchg
Executable file
|
|
@ -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
mmgen-walletchk
Executable file
75
mmgen-walletchk
Executable file
|
|
@ -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
mmgen-walletgen
Executable file
168
mmgen-walletgen
Executable file
|
|
@ -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
mmgen/Opts.py
Executable file
68
mmgen/Opts.py
Executable file
|
|
@ -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
mmgen/__init__.py
Executable file
38
mmgen/__init__.py
Executable file
|
|
@ -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
mmgen/addr.py
Executable file
187
mmgen/addr.py
Executable file
|
|
@ -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
mmgen/bitcoin.py
Executable file
153
mmgen/bitcoin.py
Executable file
|
|
@ -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
mmgen/config.py
Executable file
48
mmgen/config.py
Executable file
|
|
@ -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
mmgen/license.py
Executable file
649
mmgen/license.py
Executable file
|
|
@ -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
mmgen/mn_electrum.py
Executable file
1657
mmgen/mn_electrum.py
Executable file
File diff suppressed because it is too large
Load diff
1658
mmgen/mn_tirosh.py
Executable file
1658
mmgen/mn_tirosh.py
Executable file
File diff suppressed because it is too large
Load diff
112
mmgen/mnemonic.py
Executable file
112
mmgen/mnemonic.py
Executable file
|
|
@ -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
mmgen/utils.py
Executable file
727
mmgen/utils.py
Executable file
|
|
@ -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
mmgen/walletgen.py
Executable file
87
mmgen/walletgen.py
Executable file
|
|
@ -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
setup.py
Executable file
30
setup.py
Executable file
|
|
@ -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
tests/addr.py
Executable file
27
tests/addr.py
Executable file
|
|
@ -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
tests/bitcoin.py
Executable file
190
tests/bitcoin.py
Executable file
|
|
@ -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
tests/mn_electrum.py
Executable file
24
tests/mn_electrum.py
Executable file
|
|
@ -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
tests/mn_tirosh.py
Executable file
24
tests/mn_tirosh.py
Executable file
|
|
@ -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
tests/mnemonic.py
Executable file
109
tests/mnemonic.py
Executable file
|
|
@ -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
tests/test.py
Executable file
86
tests/test.py
Executable file
|
|
@ -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
tests/utils.py
Executable file
27
tests/utils.py
Executable file
|
|
@ -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
tests/walletgen.py
Executable file
27
tests/walletgen.py
Executable file
|
|
@ -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
wordlists/mn_wordlist.c
Normal file
302
wordlists/mn_wordlist.c
Normal file
|
|
@ -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
wordlists/mn_wordlist.py
Executable file
292
wordlists/mn_wordlist.py
Executable file
|
|
@ -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
wordlists/mn_wordlist.sort.py
Normal file
1642
wordlists/mn_wordlist.sort.py
Normal file
File diff suppressed because it is too large
Load diff
1691
wordlists/mnemonic.py
Executable file
1691
wordlists/mnemonic.py
Executable file
File diff suppressed because it is too large
Load diff
1638
wordlists/mnemonic.sort.py
Normal file
1638
wordlists/mnemonic.sort.py
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue